您的位置:首页 > 编程语言 > Java开发

Java编写大嘴怪游戏--原创

2013-08-24 17:47 393 查看
第一步:大嘴鱼类

package fish;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
/**
*
*@author huyongjian Oracle(Compus Solution Group)
* @Date  2013-7-24
* @version 2.0
* @since JDK1.6(建议)
Copy Right Information    COMPUS SOLUTION GROUP
IDE:Eclipse
class:
* 大嘴鱼类<br>
* 此类继承AcitonListener,实现AcitonPerformed方法,练习ActionListener的另一种实现方法<br>
* 此类还练习定时器Timer的使用<br>
* 此类还练习图形类Graphics的使用<br>
*/
public class BigMouthFish implements ActionListener{

/** 大嘴鱼嘴的方向:0-上 */
public static int UP = 0;
/** 大嘴鱼嘴的方向:1-右 */
public static int RIGHT = 1;
/** 大嘴鱼嘴的方向:2-下 */
public static int DOWN = 2;
/** 大嘴鱼嘴的方向:3-左 */
public static int LEFT = 3;

/** 大嘴鱼的身体大小,以size为半径画圆 */
public int size = 50;
/** 大嘴鱼现在的方向(以嘴的方向为基准) */
public int direction = RIGHT;
/** 大嘴鱼身体的颜色 */
private Color color = Color.CYAN;
/** 大嘴鱼的位置x */
public int posx = 80;
/** 大嘴鱼的位置y */
public int posy = 80;
/** 大嘴鱼的速度,鱼每次前进的像素 */
public int speed = 4;
/** 大嘴鱼眼睛的大小 */
private int eyesize = size/5;
/** 大嘴鱼眼睛的位置x */
private int eyeposx = posx+size/2;
/** 大嘴鱼眼睛的位置y */
private int eyeposy = posy+size/5;
/** 大嘴鱼眼睛的颜色 */
private Color eyecolor = Color.RED;
/** 大嘴鱼嘴的最大角度的一半 */
private int maxMonth = 30;
/** 大嘴鱼现在嘴角的角度 */
private int monthsize = 30;

/** 大嘴鱼的嘴是否张开 */
private boolean isOpen = true;

private Timer time = null;

/**
* 大嘴鱼缺省构造函数.<br>
* 创建一个位置为(200,200),大小为50,方向为右,颜色为Color.CYAN,速度为10的大嘴鱼
*/
public BigMouthFish() {
//this的使用。
this(200,200,50,RIGHT,Color.CYAN,4);
}

/**
* 根据位置、大小、方向、颜色、速度构造一个大嘴鱼。
* @param posx 大嘴鱼的位置x。
* @param posy 大嘴鱼的位置y。
* @param size 大嘴鱼的大小。
* @param direction 大嘴鱼的方向:0-上;1-右;2-下;3-左。出入错误时,默认改为1。
* @param color 大嘴鱼的颜色。
* @param speed 大嘴鱼的速度。
*/
public BigMouthFish(int posx,int posy,int size,int direction,Color color,int speed) {
this.posx = posx;
this.posy = posy;
this.size = size;
if(direction==1 || direction==2 || direction==3 || direction==4)
this.direction = direction;
this.color = color;
this.speed = speed;
eyesize = size/7;
initEye();

time = new Timer(FishPool.reTime,this);
time.start();
}

/**
* 大嘴鱼移动。根据鱼的方向移动鱼。
*/
public void move(){
switch (direction) {
case 0:
posy--;
break;
case 1:
posx++;
break;
case 2:
posy++;
break;
case 3:
posx--;
break;
default:
break;
}
}

/**
* 改变大嘴鱼身体的颜色。
* @param color 欲改变大嘴鱼身体的颜色
*/
public void changeColor(Color color){
this.color = color;
}

/**
* 改变大嘴鱼的方向
* @param direction 欲改变大嘴鱼的方向
*/
public void changeDir(int direction){
this.direction = direction;
}

/**
* 使用画笔绘画大嘴鱼.大嘴鱼的头像:一个扇形的是鱼脸,上面有一个小圆是眼睛<br>
* 1.保存画笔颜色<br>
* 2.绘制大嘴鱼的脸<br>
* 3.绘制大嘴鱼的眼睛<br>
* 4.恢复画笔颜色<br>
* @param g 画笔
*/
public void paint(Graphics g){
//保存画笔的颜色
Color c = g.getColor();
//绘制鱼脸
g.setColor(color);
//从(posx,posy)点开始,绘制宽为size,高为size,开始角度为(direction%2==0?(direction+1):(direction-1))*90+monthsize,弧度为360-2*maxMonth的弧形
g.fillArc(posx, posy, size, size, (direction%2==0?(direction+1):(direction-1))*90+monthsize, 360-2*monthsize);
//绘制鱼眼
initEye();
g.setColor(eyecolor);
g.fillOval(eyeposx, eyeposy, eyesize, eyesize);
//恢复画笔颜色
g.setColor(c);
}

/**
* 大嘴鱼张嘴闭嘴事件<br>
* 此处只负责鱼的角度的变化,不负责鱼的重绘。
* 重绘在鱼池中实现。<br>
* 这样的好处:保证鱼的绘制和步伐分开。显示层和逻辑层单独处理。(面向对象的责任问题)。
* @param e 事件对象
*/
public void actionPerformed(ActionEvent e) {
if(isOpen){
monthsize -= 2;
if(monthsize<=0)
isOpen = false;
}else{
monthsize += 2;
if(monthsize>=maxMonth)
isOpen = true;
}
}

/**
* 方向改变时,眼睛的改变。
*/
private void initEye(){
switch (direction) {
case 0:
eyeposx = posx+size/7;
eyeposy = posy+size/2-eyesize;
break;
case 1:
eyeposx = posx+size/2;
eyeposy = posy+size/7;
break;
case 2:
eyeposx = posx+size*5/7;
eyeposy = posy+size/2;
break;
case 3:
eyeposx = posx+size/2-eyesize;
eyeposy = posy+size/7;
break;
default:
break;
}
}
}


第二步:豆豆类

package fish;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
/**
*
*@author huyongjian Oracle(Compus Solution Group)
* @Date  2013-7-24
* @version 2.0
* @since JDK1.6(建议)
Copy Right Information    COMPUS SOLUTION GROUP
IDE:Eclipse
class:
豆豆类
*/
public class FishBean implements ActionListener{
/** 小鱼的位置x */
public int posx = 190;
/** 小鱼的位置y */
public int posy = 190;
/** 小鱼的大小,以size为半径画豆豆(圆)。 */
public int size = 10;
/** 小鱼的当前颜色 */
private Color color = Color.MAGENTA;

/** 小鱼的新颜色 */
private Color newColor = Color.MAGENTA;
/** 小鱼的旧颜色 */
private Color oldColor = Color.GRAY;

/** 小鱼消失时的闪烁时间 */
public static int flickerTime = 350;
/** 小鱼消失时的闪烁次数 */
public static int filckerNum = 8;
private int hasFileckedNum = 0;
/** 小鱼消失时闪烁的定时器 */
private Timer timer = null;

/**
* 缺省构造函数。按位置(40,40),大小15,颜色Color.MAGENTA构造一个豆豆。
*/
public FishBean() {
this(190,190,10,Color.MAGENTA,Color.GRAY);
}

/**
* 按照位置、大小、颜色构造一个豆豆类。
* @param posx 豆豆的水平坐标x。
* @param posy 豆豆的垂直坐标y。
* @param size 豆豆的大小。
* @param newColor 豆豆的颜色。
* @param oldColor 豆豆的旧颜色
*/
public FishBean(int posx,int posy,int size,Color newColor,Color oldColor) {
this.posx = posx;
this.posy = posy;
this.size = size;
this.newColor = newColor;
this.oldColor = oldColor;
this.color = newColor;
timer = new Timer(flickerTime,this);
}

/**
* 移动豆豆到新的位置。
* @param posx 豆豆的新水平坐标x。
* @param posy 豆豆的新垂直坐标y。
*/
public void newPos(int posx,int posy){
this.posx = posx;
this.posy = posy;
}

/**
* 绘制豆豆。
* @param g 画笔
*/
public void paint(Graphics g){
Color c = g.getColor();
g.setColor(color);
g.fillOval(posx, posy, size, size);
g.setColor(c);
}

/**
* 停止Timer。
*/
public void stopTimer(){
color = newColor;
timer.stop();
hasFileckedNum = 0;
}

/**
* 启动Timer。
*/
public void runTimer(){
timer.start();
}

/**
* 定时器事件。
*/
public void actionPerformed(ActionEvent e) {
hasFileckedNum++;
if(color.equals(newColor) || color==newColor)
color = oldColor;
else
color = newColor;
//定时器运行的次数完成时,停止定时器。
if(hasFileckedNum==filckerNum && timer.isRunning()){
stopTimer();
}
}

/**
* Timer定时器是否运行中。
* @return 返回Timer是否运行中。
*/
public boolean timerIsRunning(){
return timer.isRunning();
}
}


第三部:鱼池类

package fish;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import main.BigMouthFishFrame;
import tools.FishUtilities;
import tools.RandomUtil;
/**
*
*@author huyongjian Oracle(Compus Solution Group)
* @Date  2013-7-24
* @version 2.0
* @since JDK1.6(建议)
Copy Right Information    COMPUS SOLUTION GROUP
IDE:Eclipse
class:
* 鱼池类。<br>
* 大鱼和小鱼放到此鱼池中,当大嘴鱼每吃10条小鱼的时候,鱼的size加1,速度加2。<br>
* 每条小鱼默认存在的时间是15秒钟。10秒后自动消失。<br>
* 此类练习if、for、Timer、内部类等的使用。<br>
* 更重要的是,希望学员做这个的游戏时候能做好严谨的逻辑考虑后,再动手。<br>
* 难点:大嘴鱼在鱼池边界的处理、大嘴鱼升级时的相关问题的处理。<br>
*/
public class FishPool extends JLabel{

private BigMouthFish fish = null;
private FishBean bean = null;

/** 小鱼存在的时间长短,单位:毫秒 */
private int timeLegth = 20*1000;
/** 重绘时间长短,单位:毫秒 */
public static int reTime = 100;

/** 鱼池重绘定时器 */
private Timer timer = null;
/** 小鱼生成定时器 */
private Timer time = null;

/** 大嘴鱼每升级1次属性增加:大小加1 */
private int sizeAdd = 1;
/** 大嘴鱼每升级1次属性增加:速度加2 */
private int speedAdd = 2;
/** 大嘴鱼每吃1条小鱼属性增加:分数加1 */
private int scoreAdd = 1;

/** 大嘴鱼现在的分数 */
private int score = 0;
/** 大嘴鱼升级的速度:每吃10条小鱼升级1次 */
private int upgradeNum = 10;
/** 大嘴鱼已吃小鱼的数量,每吃upgradeNum个,变为0 */
private int eatNum = 0;

/** 大嘴鱼的水平最小边界 */
private int min_x = 0;
/** 大嘴鱼的水平最大边界 */
private int max_x = 0;
/** 大嘴鱼的垂直最小边界 */
private int min_y = 0;
/** 大嘴鱼的垂直最大边界 */
private int max_y = 0;

public FishPool() {
setSize(BigMouthFishFrame.width,BigMouthFishFrame.height);
setLocation(10, 10);

fish = new BigMouthFish();
initFishBean();

//此处加3、减3是为了大嘴鱼不直接接触鱼池边界。
min_x = 3;
max_x = BigMouthFishFrame.width-fish.size-3;
min_y = 3;
max_y = BigMouthFishFrame.height-fish.size-3;

//注册向上键
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0),"UpPress");
getActionMap().put("UpPress", new UpListenerImpl());
//注册向右键
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0),"RightPress");
getActionMap().put("RightPress", new RightListenerImpl());
//注册向下建
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0),"DownPress");
getActionMap().put("DownPress", new DownListenerImpl());
//注册向左键
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0),"LeftPress");
getActionMap().put("LeftPress", new LeftListenerImpl());

timer = new Timer(reTime,new TimerListenerImpl());
timer.start();

time = new Timer(timeLegth-FishBean.flickerTime*FishBean.filckerNum,new ActionListener(){
public void actionPerformed(ActionEvent e) {
//先停止本身定时器。
time.stop();
//启动小鱼的闪烁定时器。
bean.runTimer();
//检测小鱼是否已经闪烁完毕。
new Thread(){
public void run() {
while (true) {
//小鱼闪烁完毕后,移动大嘴鱼。
//重新启动本身定时器。
if(!bean.timerIsRunning()){
beanNewPos();
time.restart();
break;
}
}
}
}.start();
}
});
time.start();
}
/**
* 初始化小鱼。<br>
* 保证小鱼生成的位置与大嘴鱼的位置不重叠。
*/
private void initFishBean(){
int size = 15;
int posx = 0;
int posy = 0;
do{
posx = RandomUtil.randomInt(BigMouthFishFrame.width-size);
posy = RandomUtil.randomInt(BigMouthFishFrame.height-size);
//System.out.println("posx:"+posx);
//System.out.println("posy:"+posy);
}while (posx>=fish.posx && posx<=fish.posx+fish.size && posy>=fish.posy && posy<=fish.posy+fish.size &&
posx+size>=fish.posx && posx+size<=fish.posx+fish.size && posy+size>=fish.posy && posy+size<=fish.posy+fish.size);
bean = new FishBean(posx,posy,size,Color.BLUE,getBackground());
}

/**
* 小鱼重新生成新位置。<br>
* 保证小鱼生成的位置与大嘴鱼的位置不重叠。
*/
private void beanNewPos(){
int size = 15;
int posx = 0;
int posy = 0;
do{
posx = RandomUtil.randomInt(2*size, BigMouthFishFrame.width-2*size);
posy = RandomUtil.randomInt(2*size,BigMouthFishFrame.height-2*size);
}while (posx>=fish.posx && posx<=fish.posx+fish.size && posy>=fish.posy && posy<=fish.posy+fish.size &&
posx+size>=fish.posx && posx+size<=fish.posx+fish.size && posy+size>=fish.posy && posy+size<=fish.posy+fish.size);
bean.newPos(posx, posy);
}

/**
* 覆盖JLabel的paint事件。
* @param g 画笔。
*/
@Override
public void paint(Graphics g) {
super.paint(g);
fish.paint(g);
bean.paint(g);
}
/**
* 大嘴鱼的移动。<br>
* 根据大嘴鱼嘴的方向,判断其是否到了鱼池边界。<br>
* @param direction 大嘴鱼移动的方向
*/
private void bigFishMove(int direction){
MOVE:
for(int i=0;i<fish.speed;i++){
fish.changeDir(direction);
//大嘴鱼到池边,不可在移动
switch(direction){
case 0:
if(fish.posy>=min_y+1)
if(isTouched()) break MOVE;
break;
case 1:
if(fish.posx<=max_x-1)
if(isTouched()) break MOVE;
break;
case 2:
if(fish.posy<=max_y-1)
if(isTouched()) break MOVE;
break;
case 3:
if(fish.posx>=min_x+1)
if(isTouched()) break MOVE;
break;
}
}
}
/**
* 检测大嘴鱼是否吃到了小鱼。
* @return 吃到小鱼就重新生成小鱼。
*/
private boolean isTouched(){
fish.move();
boolean b = FishUtilities.isInteraction(fish, bean);
if(b){
//鱼的升级
eatNum++;
score += scoreAdd;
BigMouthFishFrame.lblScore.setText(score+"");
if(eatNum==upgradeNum){
eatNum = 0;
fish.size += sizeAdd;
fish.speed += speedAdd;

BigMouthFishFrame.lblSize.setText(fish.size+"");
BigMouthFishFrame.lblSpeed.setText(fish.speed+"");

//下面的这段代码是发现游戏bug后增加的代码
//bug:如果大嘴鱼在鱼池边界处恰好升级,将使鱼出界。
if(fish.posx==max_x || fish.posy==max_y){
fish.posx -= sizeAdd;
fish.posy -= sizeAdd;
}
}
//下面的这段代码是发现游戏bug后增加的代码。
//bug:如果大嘴鱼在小鱼闪烁时吃到小鱼。小鱼将触发新位置,而又将使小鱼继续闪烁。
//停止小鱼闪烁的定时器,更改颜色为原来的颜色。已经闪烁次数为0。
if(bean.timerIsRunning()){
bean.stopTimer();
}

beanNewPos();
time.restart();
}
return b;
}

/**
* 内部类 - 向上按键事件。
* 2013-7-24
* @author      Oracle
* @version 2.0
* @since       JDK1.6(建议)
* @author      小夜的传说
*/
private class UpListenerImpl extends AbstractAction{
public void actionPerformed(ActionEvent e) {
bigFishMove(0);
}
}

/**
* 内部类 - 向右按键事件。
* 2013-7-24
* @author      Oracle
* @version 2.0
* @since       JDK1.6(建议)
* @author      小夜的传说
*/
private class RightListenerImpl extends AbstractAction{
public void actionPerformed(ActionEvent e) {
bigFishMove(1);
}
}

/**
* 内部类 - 向下按键事件。
* 2013-7-24
* @author      Oracle
* @version 2.0
* @since       JDK1.6(建议)
* @author      小夜的传说
*/
private class DownListenerImpl extends AbstractAction{
public void actionPerformed(ActionEvent e) {
bigFishMove(2);
}
}

/**
* 内部类 - 向左按键事件。
* 2013-7-24
* @author      Oracle
* @version 2.0
* @since       JDK1.6(建议)
* @author      小夜的传说
*/
private class LeftListenerImpl extends AbstractAction{
public void actionPerformed(ActionEvent e) {
bigFishMove(3);
}
}

/**
* 内部类 - 图形重回事件.<br>
* 2013-7-24
* @author      Oracle
* @version 2.0
* @since       JDK1.6(建议)
* @author      小夜的传说
*/
private class TimerListenerImpl implements ActionListener{
public void actionPerformed(ActionEvent e) {
repaint();
}
}
}


第四步:随机生成类

package tools;
import java.util.Random;
/**
*
*@author huyongjian Oracle(Compus Solution Group)
* @Date  2013-7-24
* @version 2.0
* @since JDK1.6(建议)
Copy Right Information    COMPUS SOLUTION GROUP
IDE:Eclipse
class:
* 数学类-随机数生成类
*/
public class RandomUtil {
/**
* 生成a-b的随机数
* @param a 整数a
* @param b 整数b
* @return a-b的随机数
*/
public static int randomInt(int a,int b){
int t,n=0;
if(a>b)
{
t=a;a=b;b=t;
}
t=(int)(Math.ceil(Math.log10(b)));//对b向上取整
while(true)
{
n=(int)(Math.random()*Math.pow(10,t));//随机数*10的t次方
if(n>=a && n<=b)
break;
}
//System.out.println("生成的随机数如下:"+n);
return n;
}

/**
* 返回0-a的随机数。
* @param a 整数a。
* @return 返回0-a的随机数。
*/
public static int randomInt(int a){
return new Random().nextInt(a);
}
}


第五步:检测大嘴怪吃豆豆类

package tools;
import fish.BigMouthFish;
import fish.FishBean;
/**
*
*@author huyongjian Oracle(Compus Solution Group)
* @Date  2013-7-24
* @version 2.0
* @since JDK1.6(建议)
Copy Right Information    COMPUS SOLUTION GROUP
IDE:Eclipse
class:
* 检测大嘴鱼和小鱼碰撞类。<br>
* 此类练习Math的静态函数的使用。
*/
public class FishUtilities {
/**
* 返回大嘴鱼是否吃掉了小鱼。<br>
* 方式:检测2鱼(圆)之间是否相切或相交。<br>
* 判断2圆心之间的距离小于2圆半径之和。此处判断小于大嘴鱼的半径即可。让大嘴鱼可以吃掉小鱼。
* @param fish
* @param bean
* @return 返回大鱼是否吃掉小鱼。
*/
public static boolean isInteraction(BigMouthFish fish,FishBean bean){
return Math.pow(fish.posx+fish.size/2-bean.posx-bean.size/2,2)+Math.pow(fish.posy+fish.size/2-bean.posy-bean.size/2, 2)<=Math.pow(fish.size/2, 2);
}
}
第六步:面板函数

package main;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import fish.FishPool;
/**
*
*@author huyongjian Oracle(Compus Solution Group)
* @Date  2013-7-24
* @version 2.0
* @since JDK1.6(建议)
Copy Right Information    COMPUS SOLUTION GROUP
IDE:Eclipse
class:
大嘴鱼洁面类。完成大嘴鱼的界面的绘制。
*/
public class BigMouthFishFrame extends JFrame{
private FishPool pool = null;

public static int width = 800;
public static int height = 600;

private JLabel lblInfo = new JLabel("欢迎进入大嘴鱼!V2.0");

private JLabel lblFishSize = new JLabel("鱼 的 大 小:");
private JLabel lblFishSpeed = new JLabel("鱼 的 速 度:");
private JLabel lblFishScore = new JLabel("现 在 得  分:");

public static JLabel lblSize = new JLabel("50");
public static JLabel lblSpeed = new JLabel("4");
public static JLabel lblScore = new JLabel("0");

private JTextArea txtInfo = new JTextArea();

public BigMouthFishFrame() {
pool = new FishPool();
pool.setBorder(new EtchedBorder(EtchedBorder.RAISED));

setTitle("大嘴鱼游戏");
setSize(width+180,height+50);
setResizable(false);
Toolkit tk=Toolkit.getDefaultToolkit();
setLocation((tk.getScreenSize().width-getSize().width)/2,(tk.getScreenSize().height-getSize().height)/2);

lblInfo.setSize(150,20);
lblInfo.setLocation(width+25,240);

String str = "    大嘴鱼游戏的简单使用说明:使用键盘上的上、下、左、右控制大嘴鱼的方向,每吃1条小鱼,得分加1分。每吃10条小鱼,大嘴鱼将升级:大小加1,速度加2。\n\n";
str += "研发部总监:小胡\n分 析 设 计 :小夜的传说\n程 序 编 写 :小夜的传说";

txtInfo.append(str);
txtInfo.setBackground(getBackground());
txtInfo.setEditable(false);
txtInfo.setLineWrap(true);
txtInfo.setSize(150,240);
txtInfo.setLocation(width+15,370);
txtInfo.setBorder(new TitledBorder(new LineBorder(Color.GRAY),"游戏说明"));

JPanel pan = new JPanel();
pan.setSize(150,100);
pan.setLocation(width+15,265);
pan.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
pan.setBorder(new TitledBorder(new LineBorder(Color.GRAY),"游戏积分"));
pan.add(lblFishSize);
pan.add(lblSize);
pan.add(lblFishSpeed);
pan.add(lblSpeed);
pan.add(lblFishScore);
pan.add(lblScore);

setLayout(null);
add(pool);
add(lblInfo);
add(pan);
add(txtInfo);

setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
/**
* @param args
*/
public static void main(String[] args) {
new BigMouthFishFrame();
}
}


Java程序猿联盟:160243674 欢迎大家的加入!




附件:http://down.51cto.com/data/2363385
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息