![]()
はざまさんの作成された「めだかっち」の完成品です。 見せていただきましょう!
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)