シラネーヨとマターリしよーヨ(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版
- ジャヴァでシラネーヨとマターリしよーヨ ― このアプレットの紹介文