//Boat.java
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class Boat
{
/*Boat的默认值*/
private static final int DEFAULT_SPEED=15;
/*尺寸*/
private static final int WIDTH=65;
private static final int THICKNESS=3;
/*Boat的活动范围*/
private int minX;
private int maxX;
/*Boat矩形的左上角坐标*/
private int X;
private int Y;
/*船的默认速度*/
private int speed=DEFAULT_SPEED;
/*船颜色*/
private Color color=Color.BLUE;
/*天空下边界*/
private int skyDown;
/*构造方法,参数定义了范围*/
public Boat(int left,int down,int screenWidth)
{
minX=left;
maxX=minX+screenWidth-WIDTH;
this.skyDown=down;
}
public void initBoat()
{
X=(minX+maxX)/2;
Y=skyDown-THICKNESS;
}
//Boat向左移动
public synchronized void left()
{
X-=speed;
/*检查边界*/
if(X<minX)
{
X=minX;
}
}
//Boat向右移动
public synchronized void right()
{
X+=speed;
/*检查边界*/
if(X<maxX)
{
X=maxX;
}
}
//设置船速
public void setSpeed(int speed)
{
this.speed=speed*5;
}
//画Boat
public synchronized void paint(Graphics g)
{
g.setColor(color);
g.fillRect(X,Y,WIDTH,THICKNESS);
}
//对类成员的访问封装
public int getX()
{
return X;
}
public int getY()
{
return Y;
}
public int getRightX()
{
return X+WIDTH;
}
public int getWaterLine()
{
return Y+THICKNESS;
}
public void moveUp()
{
Y-=1;
}
}//end class
//Rain.java
import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
public class Rain extends Applet implements ActionListener,ItemListener{
/**游戏画面屏幕*/
private Screen screen;
/**控制面板*/
private Panel ctrlPanel;
/*"雨速" "船速"下拉框 "左"/"右"/"开始/重玩" "帮助"按钮,分数标签*/
private Choice rainSpeedCHIC=new Choice();
private Choice boatSpeedCHIC=new Choice();
private Button leftBTN=new Button("<");
private Button rightBTN=new Button(">");
private Button playBTN=new Button("开始");
private Label scoreLBL=new Label("得分:0");
/**初始化控制面板,并创建Screen实例*/
public void init()
{
setLayout(new BorderLayout());
/*该应用是为了screen通知ctrlPanel上的界面变化
* 1.得分的改变
* 2.开始/重玩 显示 的切换*/
screen=new Screen(this);
add("Center",screen);
ctrlPanel=new Panel();
add("South",ctrlPanel);
//初始化交互组件
boatSpeedCHIC.addItem("船速");
boatSpeedCHIC.addItem("1");
boatSpeedCHIC.addItem("2");
boatSpeedCHIC.addItem("3");
boatSpeedCHIC.addItem("4");
boatSpeedCHIC.addItem("5");
//在ctrlPanel上加入交互组件
ctrlPanel.add(boatSpeedCHIC);
ctrlPanel.add(leftBTN);
ctrlPanel.add(rightBTN);
ctrlPanel.add(playBTN);
ctrlPanel.add(scoreLBL);
//加入事件监听,由本类监听
boatSpeedCHIC.addItemListener(this);
leftBTN.addActionListener(this);
rightBTN.addActionListener(this);
playBTN.addActionListener(this);
}//end init()
public void initGame()
{
playBTN.setLabel("开始");
scoreLBL.setText("得分:0");
screen.initGame();
}
public void start()
{
//启动Screen,但不代表开始游戏(要等按"开始"play())
screen.start();
}
// 出来按键
public void actionPerformed(ActionEvent e)
{
Object src=e.getSource();
if(src==leftBTN)
{
screen.boatMoveLeft();
return;
}
if(src==rightBTN)
{
screen.boatMoveRight();
return;
}
if(src==playBTN)
{
//开始游戏,如果在游戏中,也会重新启动游戏
if(playBTN.getLabel().equals("重玩"))
initGame();
else //"开始"
screen.play();
return;
}
}//end actionPerformed()
//处理下拉框
public void itemStateChanged(ItemEvent e)
{
Object src=e.getSource();
String item=(String)(e.getItem());
if(src==boatSpeedCHIC)
{
if(item.equals("船速"))
{
item="1";
}
int id=Integer.parseInt(item);
screen.setBoatSpeed(id);
return;
}
}//end itemStateChanged()
public void setScore(int score)
{
scoreLBL.setText("得分:"+score);
}
public void changePlayBTNDisplay()
{
playBTN.setLabel("重玩");
}
public void stop()
{
screen.stop();
}
public String getAppletInfo()
{
return "Rain";
}
public void destroy()
{
remove(screen);
remove(ctrlPanel);
}
}//end class
//Raindrop.java
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
class Raindrop
{
/*随机数产生器*/
private static Random random=new Random();
/*产生雨点的范围*/
private int minGX;
private int maxGX;
private int minGY;
private int maxGY;
/*雨点的位置,圆的正外切正方形的左上角坐标*/
private int X;
private int Y;
/*尺寸,半径,直径*/
private static final int MIN_RADIUS=2;
private static final int MAX_RADIUS=4;
private int radius;
/*雨点下落速度*/
private static final int MIN_SPEED=2;
private static final int MAX_SPEED=5;
private int speed;
/*雨点颜色*/
private Color color;
/*接住该雨点得到的分数*/
private int score;
/*Boat*/
private Boat boat;
private int deadLine;
//建立雨点实例,参数传入范围
public Raindrop(Boat boat,int left,int top,int skyWidth,int skyThickness)
{
this.boat=boat;
/*设置雨点产生的范围*/
minGX=left;
minGY=top+skyThickness/2;
maxGX=minGX+skyWidth-MAX_RADIUS*2;
maxGY=minGY+skyThickness-MAX_RADIUS*2;
deadLine=top+skyThickness;
}
//随机产生初始雨点信息
public void initDrop()
{
X=((random.nextInt()>>>1)%(maxGX-minGX))+minGX;
Y=((random.nextInt()>>>1)%(deadLine-minGY))+minGY;
speed=((random.nextInt()>>>1)%(MAX_SPEED-MIN_SPEED))+MIN_SPEED;
radius=((random.nextInt()>>>1)%(MAX_RADIUS-MIN_RADIUS))+MIN_RADIUS;
color=new Color((random.nextInt()>>>1)%0xffffff);
//分值为半径加速度
score=radius+speed;
}
/*雨点下落一次
* @return 0:没达到 1:接着了 2:没接着*/
public int fall()
{
Y+=speed;
/*检查是否到达检查线(船的上位置)*/
if((Y+radius)<boat.getY())
return 0;
/*判断是否落在船上*/
int dropRightX=X+radius*2;
boolean isHit=(X>boat.getRightX())||(dropRightX<boat.getX());
//让该雨点重新从上面掉,并重新计算雨点信息
initDrop();
return isHit? 2:1;
}//end fall()
//画雨点
void paint(Graphics g)
{
g.setColor(color);
g.fillArc(X,Y,radius*2,radius*2,0,360);
}
public int getScore()
{
return score;
}
}//end class
//Screen.java
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import java.net.MalformedURLException;
class Screen extends Panel implements Runnable{
//代表本线程
private Thread me;
//引用Rain实例
private Rain rain;
//重画间隔时间
private static final int SPEED_TEPAINT=70;
//雨点的个数
private static final int DROP_NUM=9;
//游戏状态标识
private static final int STATUS_INIT=1;
private static final int STATUS_PLAYING=2;
private static final int STATUS_DEAD=3;
private int status;
//总分数
private int score;
//船引用
private Boat boat;
/*雨点数组*/
private Raindrop[] dropArr=new Raindrop[DROP_NUM];
/*屏幕尺寸*/
private int X=0;
private int Y=0;
private int W;
private int H;
/*颜色*/
private Color bgColor=Color.white;
private Color borderColor=Color.black;
private Color deadLineColor=Color.blue;
private Color waterColor=Color.red;
private Color textColor=Color.black;
//死亡线
private int deadLine;
//显示消息的坐标
private int msgX;
private int msgY;
//雨点计数,为了画水
private int waterCount;
//主路径,为了播放音乐
private URL base;
//是否刚开始游戏,用于第一次擦除屏幕
private boolean isFirst;
//构造方法
public Screen(Rain rain)
{
super();
this.base=rain.getCodeBase();
this.rain=rain;
}
//第一次启动
public void start()
{
// 计算 Screen的各种初值(***)
countSize();
initGame();
me=new Thread(this);
me.start();//进入run()
}
public void initGame()
{
status=STATUS_INIT;
isFirst=true;
//初始化船位置,雨点数组
boat.initBoat();
for(int i=0;i<dropArr.length;i++)
dropArr[i].initDrop();
score=0;
repaint();
}
public void countSize()
{
W=getSize().width;
H=getSize().height;
boat=new Boat(X,H,W);
deadLine=H/4;
msgX=X+15;
msgY=Y+15;
for(int i=0;i<dropArr.length;i++)
dropArr[i]=new Raindrop(boat,X,Y,W,deadLine);
setBackground(bgColor);
}
public void play()
{
status=STATUS_PLAYING;
rain.changePlayBTNDisplay();
repaint();
}
//主要执行方法
public void run()
{
while(true)
{
try
{
Thread.sleep(SPEED_TEPAINT);
}
catch(InterruptedException e){}
//如果死亡/等待,则继续循环
if((STATUS_INIT==status)||(STATUS_DEAD==status))
continue;
//移动所以雨点
waterCount=0;
for(int i=0;i<dropArr.length;i++)
{
int rtn=dropArr[i].fall();
if(0==rtn)
continue;
if(1==rtn)
{
//接着了
score+=dropArr[i].getScore();
rain.setScore(score);
//播放音效
rain.play(base,"au/ok.au");
continue;
}
//播放音效
rain.play(base,"au/ng.au");
//没接着
boat.moveUp();
waterCount++;
if(boat.getY()<deadLine)
{
status=STATUS_DEAD;
rain.changePlayBTNDisplay();
}
}
//更新画面
repaint();
}
}//end run()
public synchronized void update(Graphics g)
{
int waterLine=boat.getWaterLine();
//清除
g.setColor(bgColor);
if(isFirst)
{
g.fillRect(0,0,W,H);
isFirst=false;
}
else
g.fillRect(1,deadLine/2,W-2,waterLine-deadLine/2);
//画边界和deadline
g.setColor(borderColor);
g.drawRect(X,Y,W-1,H-1);
g.setColor(deadLineColor);
g.drawLine(X,deadLine,W,deadLine);
//画水
if(waterCount!=0)
{
g.setColor(waterColor);
g.fillRect(X,waterLine,W,waterCount);
}
//如果船移动,则重画
boat.paint(g);
//画移动的雨点的新值
for(int i=0;i<dropArr.length;i++)
dropArr[i].paint(g);
if(status==STATUS_DEAD)
{
g.setColor(textColor);
g.drawString("你被淹死了,游戏结束.",msgX+30,msgY);
}
else
{
g.setColor(waterColor);
g.drawString("雨",msgX,msgY);
}
}//end update()
public void boatMoveLeft()
{
boat.left();
repaint();
}
public void boatMoveRight()
{
boat.right();
repaint();
}
public void setBoatSpeed(int speed)
{
boat.setSpeed(speed);
}
public void stop()
{
me=null;
}
}//end class