はざまさんの作成された「めだかっち」の完成品です。 見せていただきましょう!
PigFaceMedakaクラスとDeadMedakaクラスはメダカクラスのサブクラスにしました。 意外と簡単にメダカの仲間が作れて、変身も簡単に出来てしまって驚きです。(^_^) 変数のprivateやprotected指定はこんなもんでいいでしょうか? MedakAappletクラスでtime、Vector mucks、Vector foodsをstatic変数にしてしまい ましたが...。(^^; 何も指定しないで、例えば int food_x; とした場合は public指定したことに なるのですか? 見た目にはわかりませんが、欠陥があります。それは、メダカがブタメダカに 変身した時(体重80gで変身)、lossWeight が0から1になるまでは メダカは泳ぐ方向を変えたり出来ないみたいです。(?_?) time変数はMedakaAppletクラスのを使いました。そうしないと メダカクラスの lossWeight メソッドがどうも働かないようです。(。_゜)? 疑問点がいくつかありますが、原因がよくわからないので そのままにしてあります。^^)^^);; 実際に音をつけるとゲームらしくなりますね。(^_^) ボタンの横に表示されているのはめだかっち世界時刻です。
//------------------ medaka.html ------------------------------- <HTML> <HEAD> <TITLE>Medakatch</TITLE> </HEAD> <BODY> <APPLET CODE="MedakaApplet.class" WIDTH=350 HEIGHT=250 > </APPLET> </BODY> </HTML>
//------------------- MedakaApplet.java ----------------------- import java.awt.*; import java.applet.*; import java.util.*; //**************** メダカクラス ******************* class Medaka{ private MedakaApplet applet = new MedakaApplet(); protected String figure[]; //メダカの姿(文字列)を入れる配列 private int OffsetFigure; //メダカの一方向の姿の数の変数 int x; //メダカが最初にいるx座標 int y; //メダカが最初にいるy座標 private int direction = 1;//メダカの泳ぐ方向 protected int ownW; //めだかの長さ protected int ownH; //メダカの幅 protected Color color; protected Dimension dimension; private AudioClip song, help; //メダカの鳴き声 protected int initialWeight; //最初の体重 protected int weight; //現在の体重 private int lossWeight; //減少体重 private int eatFoodCount; //食べた餌の数 private int longevity;//寿命 Medaka(int x, int y, Applet a){ this.x = x; this.y = y; song = a.getAudioClip(a.getDocumentBase(),"medaka.au"); help = a.getAudioClip(a.getDocumentBase(),"help.au"); setFigure(); getLifeSpan(); //寿命を算出 } public void setFigure(){ figure = new String[4]; //文字列を入れるための配列(4個入る) figure[0] = ">^)))><"; figure[1] = "=^)))><"; figure[2] = "><(((^<"; figure[3] = "><(((^="; ownW = 40; ownH = 13; color = Color.blue; initialWeight = 30; } //寿命は最初っから決まってる(¨;)、運がよくて幸せだと長生き (^_^) public int getLifeSpan(){ int lifeSpan , happiness; lifeSpan = (int)(Math.random()*100000); happiness = (int)(Math.random()*10) + 1; longevity = lifeSpan * happiness; return longevity; } public Rectangle getRectangle(){ return new Rectangle(x, y, ownW, ownH); } public void addMuck(){ //糞をする if(MedakaApplet.time%50 == 0) MedakaApplet.mucks.addElement( new Muck ( x + (ownW/2) , y )); } public int getWeight(){//体重を計算:餌は必ず食べる:1個5グラム weight = initialWeight + ((MedakaApplet.FOOD_WEIGHT * eatFoodCount) - lossWeight); return weight; } public void lossWeight(){//エネルギー消費 int loss = 1; if(MedakaApplet.time%20 == 0)lossWeight += loss; } public void directionOfMedaka(Dimension dimension){//泳ぐ方向 this.dimension = dimension; int margin = 5; //メダカが端まで行かないようマージン if(MedakaApplet.foods.size() > 0 ){//餌がある時の動く方向 Food food = (Food)MedakaApplet.foods.elementAt(0); if(y < food.food_y){ if(x < food.food_x ) direction = 5; if(x > food.food_x ) direction = 6; } if(y == food.food_y ){ if(x < food.food_x ) direction = 4; if(x > food.food_x ) direction = 1; } if(y > food.food_y ){ if(x < food.food_x ) direction = 3; if(x > food.food_x ) direction = 2; } //餌に接すると食べる if (getRectangle().intersects(food.getRectangle())){ applet.removeFood(); eatFoodCount++; //食べた餌の数 } } else{ //水槽内に餌が無い時泳ぐ方向 if(MedakaApplet.time % 20 == 0){//20回数えてモードを変える direction = 1 + (int)(Math.random() * 10); } if(dimension.width - (x + ownW) < margin ){ direction = 1; //右端に来ると左に進む } if(x < margin){ direction = 4; //左端に来ると右に進む } if(y < margin + MedakaApplet.MARGIN_H + ownH){ //上端に来たら if(x < dimension.width/2){//左寄りの時は右下へ direction = 5; } else{//右寄りの時は左下へ direction = 6; } } if(y > dimension.height - MedakaApplet.MARGIN_H - margin - ownH){ //下端に来た時 if(x < dimension.width/2){//左寄りの時は右上へ direction = 3; } else{//右寄りの時は左上へ direction = 2; } } } } // 左上 2 ~\ /~ 3 右上 // 左 1 - @ - 4 右 // 左下 6 _/ \_ 5 右下 public void medakaMove(){ int move_x = 0; //メダカのx座標移動数値 int move_y = 0; //メダカのy座標移動数値 int LEFT=0; int RIGHT=2; switch(direction){ case 1: //左向きに泳ぐ OffsetFigure = LEFT; move_x = -5; move_y = 0; break; case 2: //左上向きに泳ぐ OffsetFigure = LEFT; move_x = -5; move_y = -5; break; case 3: //右上に進む OffsetFigure = RIGHT; move_x = 5; move_y = -5; break; case 4: //右向きに泳ぐ OffsetFigure = RIGHT; move_x = 5; move_y =0; break; case 5: //右下に進む OffsetFigure = RIGHT; move_x = 5; move_y = 5; break; case 6: //左下に進む OffsetFigure = LEFT; move_x = -5; move_y = 5; break; case 7: OffsetFigure = LEFT; move_x = -2; move_y = 2; break; default: //モード1〜7以外は右下へ進む OffsetFigure = RIGHT; move_x = 2; move_y = 2; OffsetFigure = RIGHT; break; } x = x + move_x; //メダカのx座標移動 y = y + move_y; //メダカのy座標移動 } //健康状態良くて、水槽もきれいだと「めだかの学校」を歌う public void singSong(){ if( 65 > weight && weight > 55 ){ if(MedakaApplet.mucks.size() < 5){ song.play(); } } } //痩せすぎたり、糞がたまると泣く public void singHelp(){ if(10 > weight && weight > 6)help.play(); if(30 < MedakaApplet.mucks.size() && MedakaApplet.mucks.size() < 35)help.play(); } public void action(Dimension dimension){ this.dimension = dimension; directionOfMedaka(dimension); medakaMove(); addMuck(); lossWeight(); singSong(); singHelp(); } public void draw(Graphics g){ g.setColor(color); g.drawString(figure[MedakaApplet.time%2+OffsetFigure],x,y); } } //**************** ブタメダカクラス *************** class PigFaceMedaka extends Medaka{ public PigFaceMedaka(int x, int y, Applet a){ super(x, y, a); } public void setFigure(){ figure = new String[4]; //文字列を入れるための配列 figure[0] = ">(oo) ))))><"; //(oo)ブタの鼻に見える? figure[1] = "=(oo) ))))><"; figure[2] = "><(((( (oo)<"; figure[3] = "><(((( (oo)="; ownW = 55; ownH = 13; color = Color.black; initialWeight = 80; } } //**************** 永眠クラス ************************* class DeadMedaka extends Medaka{ private String figure; public DeadMedaka (int x, int y, Applet a){ super(x, y, a); } public void setFigure(){ figure = "@++++++<"; //黒田さんのを真似てみました color = Color.black; ownH = 4; } public int getWeight(){ weight = 3; return weight; } public void medakaMove(Dimension dimension){ this.dimension = dimension; int move_y = 3; if(dimension.height - (y + ownH) < MedakaApplet.MARGIN_H){ move_y = 0; } y += move_y; } public void action(Dimension dimension){ medakaMove(dimension); } public void draw(Graphics g){ g.setColor(color); g.drawString(figure, x, y); } } //*************** MedakaApplet.class ********************** public class MedakaApplet extends Applet implements Runnable{ private Dimension appletSize; //Dimensionオブジェクトを作成 private Image offScreen; //ちらつき防止のためのImageオブジェクト private Graphics offGraphics; //ちらつき防止のためのGraphicsオブジェクト private Label conditionLabel; //メダカの状態を表示するためのラベル変数 private Label weightLabel; //体重表示 private Label ageLabel; //年齢表示 private Label medakaWTimeLabel; //メダカワールド時刻表示 private Panel top, bottom; //パネル2個作成するための変数 private Button foodButton, cleanButton; //ボタン2個作成するための変数 private Thread m_Thread; //スレッド変数 private Medaka medaka; private Plant plant; private VirtualTime medakaTime; final static int MARGIN_H = 30; //縦のマージン(ラベル幅) final static int FOOD_WEIGHT = 5;//餌の重さ一個5グラム final int MILLI_SEC_PER_DAY = 1000*60*60*24;//1日のミリ秒 static int time; static Vector mucks; static Vector foods; public void init() { setBackground(Color.gray); //背景をグレイにする appletSize = size(); //アプレットの幅と高さを得る //描画用領域を生成 offScreen=createImage(appletSize.width, appletSize.height); //offScreenに描くためのGraphicsオブジェクト offGraphics=offScreen.getGraphics(); top = new Panel(); foodButton = new Button("FOOD "); //餌ボタン cleanButton = new Button("CLEAN"); //掃除ボタン medakaWTimeLabel = new Label("Date : "); top.setLayout(new FlowLayout(FlowLayout.CENTER)); top.add(foodButton); //ボタンをパネルに貼り付ける top.add(cleanButton); top.add(medakaWTimeLabel); bottom = new Panel(); conditionLabel = new Label(" ( ^ ^ ) "); weightLabel = new Label("weight : "); ageLabel = new Label("age : "); bottom.setLayout(new FlowLayout(FlowLayout.CENTER)); bottom.add(conditionLabel); //ラベルをパネルに貼り付ける bottom.add(weightLabel); bottom.add(ageLabel); setLayout(new BorderLayout()); add("North", top); //ボタンを貼り付けたパネルをアプレット上部に配置 add("South", bottom); //ラベルを貼り付けたパネルをアプレット下部に配置 mucks = new Vector(); foods = new Vector(); medaka = new Medaka(100,75, this); plant = new Plant(appletSize.width/3, appletSize, this); medakaTime = new VirtualTime(true, 1000); } public void start(){ if (m_Thread == null){ m_Thread = new Thread(this); m_Thread.start(); //スレッドを実行させる } } public void run(){ //スレッドの処理内容 while (true){ //ずっと繰り返す time++; medaka.action(appletSize); medakaTime.forward(); labelChange(); newLife(); terminate(); repaint(); pause(); } } //食べ過ぎるとブタメダカに変身、もう元の姿にはもどれない(-_-#) public void newLife(){ if(medaka.getWeight() == 80){ medaka = new PigFaceMedaka(medaka.x, medaka.y ,this); } } //死んじゃうよ〜(;;) public void terminate(){ if( (time == medaka.getLifeSpan()) ||(medaka.getWeight() == 3) ||(mucks.size() > 50)){ medaka = new DeadMedaka(medaka.x, medaka.y, this); } } private void pause(){ try{ Thread.sleep(200); }catch (InterruptedException e){} } public void stop(){ if (m_Thread != null){ m_Thread.stop(); //スレッドを止める m_Thread =null; } } public void update(Graphics g){ paint(g); } private void flush(){//水槽の掃除をする時に使う offGraphics.setColor(Color.cyan); offGraphics.fillRect(0, 0, appletSize.width, appletSize.height); } public void paint(Graphics g){ offGraphics.setColor(Color.cyan); offGraphics.fillRect(0, 0, appletSize.width, appletSize.height); //描画用領域offScreenに対して描画を行う plant.draw(offGraphics); medaka.draw(offGraphics); //餌 for(int i = 0; i < foods.size(); i++){ getFood(i).foodMove(appletSize); } for(int i = 0; i < foods.size(); i++){ getFood(i).draw(offGraphics); } //糞 for(int i = 0; i < mucks.size(); i++){ getMuck(i).muckMove(appletSize); } for(int i = 0; i < mucks.size(); i++){ getMuck(i).draw(offGraphics); } //画面へと転送する g.drawImage(offScreen, 0, 0, this); } public Muck getMuck(int number){ return(Muck)mucks.elementAt(number); } public Food getFood(int number){ return(Food)foods.elementAt(number); } //メダカが餌を食べたらめだかから呼ばれて姿を消す public void removeFood(){ foods.removeElementAt(0); } //ラベルの表示文字を書き換える private void labelChange(){ weightLabel.setText("weight : " + medaka.getWeight() + "g"); medakaWTimeLabel.setText("Date : " + medakaTime.toGMTString()); ageLabel.setText("age : " + (medakaTime.getCurrentValue() / MILLI_SEC_PER_DAY)); //メダカ年齢はメダカ時間の1日に1歳づつふえる if(foods.size() > 5){ conditionLabel.setText("I'M FULL!"); } if(mucks.size() > 30){ conditionLabel.setText("WATER IS DIRTY!"); } } //ボタンのイベント処理 public boolean action(Event v, Object o){ if (v.target == foodButton){ //ボタンがfoodButtonであれば foods.addElement(new Food(appletSize)); //餌が落とされる conditionLabel.setText("Yum-Yum"); } else if (v.target == cleanButton){//水槽の掃除 conditionLabel.setText("( ^_^ )"); foods.removeAllElements(); mucks.removeAllElements(); flush(); } return true; } } //************** 水草クラス **************** class Plant{ private Image plantIm[]; //水草(30*50)の絵を入れる変数 private int plantH = 50; //水草の高さ private int plant_x, plant_y; private Dimension dimension; private int time; public Plant(int x,Dimension dimension, Applet a){ this.plant_x = x; this.dimension = dimension; plantIm = new Image[2]; plantIm[0] = a.getImage(a.getDocumentBase(), "plant1.gif"); plantIm[1] = a.getImage(a.getDocumentBase(), "plant2.gif"); plant_y = dimension.height - plantH - MedakaApplet.MARGIN_H; } public void draw(Graphics g){ time++; g.drawImage(plantIm[(time/4)%2], plant_x, plant_y, null); } } //************** 糞クラス ****************** class Muck{ private Dimension dimension; private int muck_x, muck_y; //在る位置 private int ownW = 10; private int ownH = 0; private String shape = "*"; //糞の形 private Color color = Color.black; private int move_y = 3; public Muck(int x, int y){ this.muck_x = x; this.muck_y = y; } public void muckMove(Dimension dimension){ this.dimension = dimension; if(dimension.height - (muck_y + ownH) < MedakaApplet.MARGIN_H){ move_y = 0; } muck_y += move_y; } public void draw(Graphics g){ g.setColor(color); g.drawString(shape, muck_x,muck_y); } } //************** 餌クラス **************** class Food{//Foodボタンを押すと中央から落とされる private Dimension dimension; int food_x, food_y; //在る位置 private int ownW = 10; private int ownH = 10; private Color color = Color.magenta; private int move_y = 1; public Food(Dimension dimension){ this.dimension = dimension; food_x = dimension.width/2; food_y = MedakaApplet.MARGIN_H; } public Rectangle getRectangle(){ return new Rectangle(food_x, food_y, ownW, ownH); } public void foodMove(Dimension dimension){ this.dimension = dimension; if(dimension.height - (food_y + ownH) < MedakaApplet.MARGIN_H){ move_y = 0; } food_y += move_y; } public void draw(Graphics g){ g.setColor(color); g.fillOval(food_x, food_y , ownW, ownH); } } ---------------------------------------------- MedakaApplet.java と 三浦さんの時計クラス(4/30)にメソッド public long getCurrentValue() { return getTime() - startTime; } を追加したものを使わせて頂いています。
めだかの学校
教室
教員に対するご意見はこちらへ:(Mail to :
cbu-staff@psn.or.jp)
用務員:臼井義美 (Mail to : yosimi-u@is.aist-nara.ac.jp)