シラネーヨとマターリしよーヨ(Java)
「シラネーヨ」がマウスカーソルを追いかけます。マウスカーソルをつかまえると,「マターリしよーヨ」とおねだりします。
アプレットが起動しない方へ
Windowsの場合
ウェブブラウザでアプレットを実行するのではなくて,アプレットヴューワ(jview.exeまたはwjview.exe)を使います。
[スタート] → [ファイル名を指定して実行] をクリックすると,「ファイル名を指定して実行」ダイアログが表示されます。「名前」の欄に
wjview /a http://yumi-ii.squares.net/shiraneyo/archives/2001/01/20010130000001.html
と入力後[OK]をクリックしてください。単体のウィンドウ開きアプレットが起動します。
Macintos(Mac OS X),Linuxの場合
Sunのアプレットヴューワ(appletviewer)を使います。「ターミナル」を起動しプロンプト画面から
appletviewer http://yumi-ii.squares.net/shiraneyo/archives/2001/01/20010130000001.html
と入力後[return]キーを押してください。単体のウィンドウ開きアプレットが起動します。
技術資料
今回もMicrosoft Visual J++ 6.0を使いました。あまり細かいことを考えずに拵えてみたのだが,意外ときれいにまとまりました(設計図どおり作っただけだから当たり前なんだけど)。
おおまかな構造図
重要な点は以下の4項目ほどです。
- Characterは一つのスレッドとして動作する。
- Characterの数に制限はない。
- Characterの振る舞いはrun()メソッドに記述される。
- アニメーションの画像は,Action抽象クラスのサブクラスにカプセル化されている。
ちなみに,マウスイベントを処理するクラスとか,Action抽象クラスはCharacterクラスの内部クラスとして定義されているとか,そういう話はどうでもいいことなので,図には含めていません。
ソースファイル
アプレットを作るときに開発ツールが用意しているテンプレートを使ったので,コードに変なコメントが入っています。
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
* このクラスは、HTML ホストページから PARAM タグを読み、アプレット
* の color および label プロパティを設定します。プログラムの実行は init()
* メソッドから始まります。
*/
public class Mattari extends Applet
{
/**
* アプレットのためのエントリ ポイントです。
*/
public void init()
{
initForm();
usePageParams();
// TODO: 構築用のコードを追加します。initForm の呼び出し前には追加しないでください。
Character agent = new Character();
Thread agentThread = new Thread(agent, "agent-thread");
setLayout(null);
add(agent);
addMouseListener(agent.createMouseListener());
addMouseMotionListener(agent.createMouseMotionListener());
agentThread.start();
}
private final String backgroundParam = "background";
private final String foregroundParam = "foreground";
/**
* このアプレットを含む HTML ページのパラメータを読み、プロパティを
* 設定します。
*/
private void usePageParams()
{
final String defaultBackground = "C0C0C0";
final String defaultForeground = "000000";
String backgroundValue;
String foregroundValue;
/**
* アプレットを含む HTML ページから、以下のタグを読みます。
* <PARAM NAME="background" VALUE="rrggbb">
* <PARAM NAME="foreground" VALUE="rrggbb">
*/
backgroundValue = getParameter(backgroundParam);
foregroundValue = getParameter(foregroundParam);
if ((backgroundValue == null) ||
(foregroundValue == null))
{
/**
* HTML のタグに問題がありました。
* 既定値で生成します。
*/
backgroundValue = defaultBackground;
foregroundValue = defaultForeground;
}
/**
* アプレットのラベル文字列、背景色および前景色
* を設定します。
*/
this.setBackground(stringToColor(backgroundValue));
this.setForeground(stringToColor(foregroundValue));
}
/**
* "rrggbb" 形式の文字列を awt.Color オブジェクトに変換します。
*/
private Color stringToColor(String paramValue)
{
int red;
int green;
int blue;
red = (Integer.decode("0x" + paramValue.substring(0,2))).intValue();
green = (Integer.decode("0x" + paramValue.substring(2,4))).intValue();
blue = (Integer.decode("0x" + paramValue.substring(4,6))).intValue();
return new Color(red,green,blue);
}
/**
* デザイン ツールがアプレットのプロパティを表示するための外部インターフェイスです。
*/
public String[][] getParameterInfo()
{
String[][] info =
{
{ backgroundParam, "String", "Background color, format \"rrggbb\"" },
{ foregroundParam, "String", "Foreground color, format \"rrggbb\"" },
};
return info;
}
/**
* アプレットおよび、そのコンポーネントの値を初期化します
*/
void initForm()
{
this.setBackground(Color.lightGray);
this.setForeground(Color.black);
}
}
class Character extends Panel implements Runnable {
Image[] imgs = {
null,
getToolkit().getImage(getClass().getResource("img01.gif")),
getToolkit().getImage(getClass().getResource("img02.gif")),
getToolkit().getImage(getClass().getResource("img03.gif")),
getToolkit().getImage(getClass().getResource("img04.gif")),
getToolkit().getImage(getClass().getResource("img05.gif")),
getToolkit().getImage(getClass().getResource("img06.gif")),
getToolkit().getImage(getClass().getResource("img07.gif")),
getToolkit().getImage(getClass().getResource("img08.gif")),
getToolkit().getImage(getClass().getResource("img09.gif")),
getToolkit().getImage(getClass().getResource("img10.gif")),
getToolkit().getImage(getClass().getResource("img11.gif")),
};
abstract class Action {
Image[] actionFrames;
int frameCount = 0;
public void play() {
Image[] actionFrames = getFrames();
frameCount = (frameCount + 1) % actionFrames.length;
}
public void paint(Graphics g) {
Image[] actionFrames = getFrames();
g.drawImage(actionFrames[frameCount], 0, 0, null);
}
protected abstract Image[] getFrames();
}
final class LeftTurn extends Action {
Image[] frames1 = {imgs[1], imgs[2]};
Image[] frames2 = {imgs[11], imgs[2]};
public Image[] getFrames() {
return (Math.random() < 0.90) ? frames1 : frames2;
}
}
final class RightTurn extends Action {
Image[] frames1 = {imgs[8], imgs[9]};
Image[] frames2 = {imgs[10], imgs[9]};
public Image[] getFrames() {
return (Math.random() < 0.90) ? frames1 : frames2;
}
}
final class Lost extends Action {
Image[] frames = {
imgs[6], imgs[3], imgs[6], imgs[3],
imgs[3], imgs[3], imgs[7], imgs[7],
imgs[7], imgs[7], imgs[7]
};
public Image[] getFrames() {
return frames;
}
}
final class Mattari extends Action {
Image[] frames = {imgs[5]};
public Image[] getFrames() {
return frames;
}
}
Action currentAction;
Hashtable actionTable;
Image buffer = null;
Graphics bufferGraphics;
Character() {
MediaTracker tracker = new MediaTracker(this);
for (int i = 0; i < imgs.length; i ++) {
if (imgs[i] != null) {
tracker.addImage(imgs[i], i);
}
}
try {
tracker.waitForAll();
} catch (InterruptedException ie) {}
/////
actionTable = new Hashtable();
actionTable.put("left", new LeftTurn());
actionTable.put("right", new RightTurn());
actionTable.put("lost", new Lost());
actionTable.put("mattari", new Mattari());
setBounds(0, 0, 292, 126);
setEnabled(false);
}
public void play() {
currentAction.play();
}
public void update(Graphics g) {
if (buffer == null) {
Dimension d = this.getSize();
buffer = createImage(d.width, d.height);
bufferGraphics = buffer.getGraphics();
}
if (currentAction != null) {
currentAction.paint(bufferGraphics);
}
g.drawImage(buffer, 0, 0, this);
}
public void paint(Graphics g) {
update(g);
}
public void setAction(String action) {
currentAction = (Action)actionTable.get(action);
}
Point mousePos = null;
public void run() {
while (true) {
if (mousePos == null) {
this.setAction("lost");
} else {
Point p0 = mousePos;
Point p1 = this.getLocation();
int step = 10;
int dx = p0.x > p1.x ? step : -step;
int dy = p0.y > p1.y ? step : -step;
if (Math.abs(p0.x - p1.x) < 8) {
dx = p0.x - p1.x;
}
this.setAction((p0.x <= p1.x) ? "left" : "right");
if (Math.abs(p0.x - p1.x) < 8 && Math.abs(p0.y - p1.y) < 8) {
this.setAction("mattari");
dx = 4;
dy = 4;
}
this.setLocation(p1.x + dx, p1.y + dy);
}
this.play();
this.repaint();
try {
Thread.sleep(250);
} catch (InterruptedException e) {}
}
}
public MouseListener createMouseListener() {
return new MouseAdapter() {
public void mouseExited(MouseEvent e) {
mousePos = null;
}
};
}
public MouseMotionListener createMouseMotionListener() {
return new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
mousePos = e.getPoint();
}
};
}
}
関連リンク
- シラネーヨとマターリしよーヨ (JScript) ― MS-IE/JScript版
- ジャヴァでシラネーヨとマターリしよーヨ ― このアプレットの紹介文