JavaApplet开发大鱼吃小鱼游戏
Java Applet 开发大鱼吃小鱼游戏
江洪
摘 要 , 利 用 成 功开发的大鱼吃小鱼的游戏 , 对 其 开 发 思 路 , 以及对网页使 用 Java applet Java
语言编程技巧进行了描述 , 具有一定的知识性和趣味 性 。
关键词 , JavaApple t, 网页, 大鱼吃小鱼
1 前言 3 开发技巧
用 Java语言进行程序开 发 , , 尤 其 在 目 前 十 分 流 行 Java Applet 是 一 种 嵌 入 html 文件中的小程序 , 在 包 含 该 上 , 经 常 可 以 看 到 语 言 写 的 程 序 。 可 以 将 Internet Java Java 程 序 的 html 文件中要有如下声明 , 代
2 概述
code=FishEat.class指明经过 编译的 Java 类文件,codebase=. “ 大 鱼 吃 小 鱼 , 小 鱼 吃 虾 米 ” 是 海洋世界中的基本规指明该类文件所在路径 ,width =640 height =480 指 明 Java 律 。游戏的主角是海洋中的霸 主 -大 鲨 鱼 , 可以自由 控制 大 鲨 Applet 的显示大小。
鱼 的 移 动 , 吃掉所有的小 鱼 。 但 是 , 在吃小鱼的同 时 , 大 鲨 鱼 后面字符串在浏览器不支持 运行时显示。alt=Java Applet
都 需 要 从 类 中 派 生 类 。 类 中 有 如每 个 Java Applet Applet 仍 然 要 躲开危险的气泡 , 否 则 会 损 失 生 命 值 。 每 吃 一 条 小 鱼 ,
下 重 要 方 法 , 如 表 1 所 示 。 会 得 到 一 定 的 分 值 ,从 1 分 到 8 分 不 等 ,,同 时 增加相同数
表 1 Java Applet 中 重 要 方 法 值的生 命 值 。 游戏的目标是得到尽 可 能 多 的 分 数 。 下面是本游
戏运行 的 界 面 如 图 1 所 示 。
游戏中的每种鱼都对 应 一 个 图 形 文 件 。 鱼 的 图 形 从gif
Internet 上 下 载 得 到 , 并 且 经 过 PhotoShop处 理 , 使 其 背 景 能 够
透 明 显 示 , 这 样 , 鱼的图形便 能 与蓝色背景相融合 。 所 有 鱼 的
图片都有正向和 反 向两个文件 。 用 getImage函 数 装 载 图 片 , 用
drawImage函 数 显 示 图 片 。
为了消除图片显示闪烁 , 可 以创建一个后台图形对象 , 将 游 戏 运 行 界 面图 1 所有要显示的东西先向这 个 后台对象 写 入 , 然后再一次性地将
try 段时间要按一定规则更改 小 鱼的 坐 标 。 这样周而复始地改变小
{ 鱼的坐标并显示 , 实际效果就是小鱼在不停地游 动 。 // 让线程睡Thread.currentThread().sleep(500); 大鲨鱼和小鱼图片相重 叠 时 , 程序中会有一个判 断 , 从 而 } 增加分数和生命值 , 并 暂 停 该 小 鱼 的 显 示 , 实际效果就是小 鱼 catch(InterruptedExceptione) 被 吃 掉 了 。 {
, 程序也会进行判断 同 样 , 大鲨鱼图片和气泡相重叠 时 , }
//更新小鱼 1 的当前坐标 从而减少生命值 。
if(showfish1==1) 程序代码if(fishpos[0][0]%50==0) 4
{ import java.awt.*; fishpos[0][0]=fishpos[0][0]+50; import java.awt.event.*;
if(fishpos[0][0]>540) import java.applet.Applet;
{ /* 从 Applet 中派生类,同时加入鼠标处理、线程处理 */ fishpos[0][0]=536; public class FishEatextends Applet implements } MouseMotionListener,Runnable } {
else public Image offScreenImage; //后台画布
public GraphicsoffScreen; //后台图形对象 {
public int mousex,mousey,lastmousex,lastmousey; fishpos[0][0]=fishpos[0][0]-50; //表示鼠标的当前坐标和上一次的坐标 if(fishpos[0][0]<0) public int direction=1; { //表示大鲨鱼的前进方向,1 为正向,0 为反向fishpos[0][0]=0; public Threadtimer; //时间线程 } public int[][] fishpos; //
小鱼的当前坐标 } public int[][] bubblepos; //记录气泡的当前坐标 //以下省略其余 7 种小鱼的更新坐标代码 public int showfish1,showfish2,showfish3,showfish4, …showfish5,showfish6,showfish7,showfish8; //更新气泡的当前坐标 //用于表示画面上是否显示小鱼,1 为显示,0 为不显示 bubblepos[0][1]=bubblepos[0][1]-50; /* 表示各种小鱼的图形对象,分为正向和反向两种,共有 8 种 if(bubblepos[0][1]<0) 小鱼 */ bubblepos[0][1]=450; public Image image0z,image0f; bubblepos[1][1]=bubblepos[1][1]-50; … //以下省略 8 种小鱼图片if(bubblepos[1][1]<0) public int score=0; //用于记录得分 bubblepos[1][1]=400; public int life=100; //用于记录生命值 bubblepos[2][1]=bubblepos[2][1]-50; public long starttime; //表示游戏开始运行时间
if(bubblepos[2][1]<0) public void start()
bubblepos[2][1]=350; {
timer=new Thread(this); //重绘画面 repaint(); timer.start(); } } } public void stop() public void init() { { timer=null; setBackground(Color.blue); 设置背景为蓝色// } addMouseMotionListener(this); //增加对鼠标的 public void run() //线程运行 /* 装载小鱼的图形文件 */ { image0z=getImage(getCodeBase(),"fish0z.gif"); Threadme=Thread.currentThread(); image0f=getImage(getCodeBase(),"fish0f.gif");
//省略装载小鱼代码 while(timer==me) …
//确定小鱼的初始坐标 else
fishpos=new int[8][2]; offScreen.drawImage(image0f,mousex,mousey,this);
//显示所有的小鱼图形 fishpos[0][0]=0;
if(showfish1==1) fishpos[0][1]=40;
if(fishpos[0][0]%50==0) //省略设置其他小鱼初始坐标代码
offScreen.drawImage(image1z,fishpos[0][0],fishpos[0][1], …
this); showfish1=1;
else showfish2=1;
offScreen.drawImage (image1f,fishpo [0]s [0],fishpos [0] showfish3=1;
[1],this); showfish4=1;
//省略其他小鱼显示代码 showfish5=1;
…showfish6=1; //吃到小鱼 1,计算得分及生命值 if(showfish1==1) if showfish7=1; (mousex +70 >=fishpos [0] [0]&&mousex +70 <=fishpos [0] showfish8=1; [0]+104&& //确定气泡的初始坐标 mousey+32>=fishpos [0][1]&&mousey+32<=fishpos[0] bubblepos=new int[3][2]; [1]+57) bubblepos[0][0]=100; { bubblepos[0][1]=450; life=life+6; bubblepos[1][0]=300; if(life>100) bubblepos[1][1]=400; life=100; bubblepos[2][0]=500; score=score+6; bubblepos[2][1]=350; fishpos[0][0]=0; starttime=System.currentTimeMillis(); fishpos[0][1]=40; //记录游戏开始毫秒数 showfish1=0; this.setCursor(new Cursor(Cursor.MOVE_CURSOR)); } //设置鼠标形状为移动式 //省略吃其他小鱼代码 } …public void update(Graphicsg) /* 根据大鲨鱼的坐标,决定是否显示小鱼 */ { if(mousey>300) paint(g); showfish1=1; } //省略其他小鱼是否显示代码 public void paint(Graphicsg) …{ //显示得分及时间 /* 创建后台图形对象 */ offScreen.setFont(new Font("Dialog",Font.PLAIN,28)); offScreenImage=createImage(640,480); offScreen.setColor(Color.yellow); offScreen=offScreenImage.getGraphics(); offScreen.drawString("得分:"+score,20,20); if(life<0) //生命值小于 0 则结束游戏 offScreen.drawString( { " 时 间 :" +(System.currentTimeMillis () -starttime)/ offScreen.setFont(new Font("Dialog",Font.PLAIN,28)); 1000,250,20);
offScreen.setColor(Color.yellow); //显示气泡 offScreen.setColor(Color.white);
offScreen.drawString("得分:"+score,20,20); offScreen.fillOval(bubblepos[0][0],bubblepos[0][1],30,30);
offScreen.setFont(new Font("Dialog",Font.PLAIN,60)); offScreen.fillOval(bubblepos[1][0],bubblepos[1][1],30,30);
offScreen.setColor(Color.red); offScreen.fillOval(bubblepos[2][0],bubblepos[2][1],30,30); offScreen.drawString("游戏结束",200,250); /* 吃到气泡,减少生命值,并重新计算气泡位置 */g.drawImage(offScreenImage,0,0,this); if (bubblepos [0][0]+15>=mousex&&bubblepos [0][0]+15<= return; mousex+139&&
} bubblepos[0][1]+15>=mousey&&bubblepos[0][1]+15<=//显示大鲨鱼图形
if(direction==1)
offScreen.drawImage(image0z,mousex,mousey,this);
{ }
life=life-30; public void mouseMoved(MouseEvent e) //计算 bubblepos[0][0]=100; {
bubblepos[0][1]=450; if((int)e.getX()>lastmousex)
direction=1; if (bubblepos [1] [0] +15 >=mousex&&bubblepos [1] [0] + }
else 15<=mousex+139&&
bubblepos[1][1]+15>=mousey&&bubblepos[1][1]+15<= direction=0;
mousey+64) lastmousex=mousex; { lastmousey=mousey; life=life-30; mousex=(int)e.getX();
mousey=(int)e.getY(); bubblepos[1][0]=300;
bubblepos[1][1]=450; repaint();
} } if (bubblepos [2] [0] +15 >=mousex&&bubblepos [2] [0] +
15<=mousex+139&& }
bubblepos[2][1]+15>=mousey&&bubblepos[2][1]+15<= 5 结语 mousey+64)
{ 将 嵌 入 在 网 页 文 件 中 , 丰富超 文 本Java HTML life=life-30; 并可以轻松地开发出动画效 果 良 好 的 程 序 。 因 此 , bubblepos[2][0]=500; 发人机交互的游戏 。 希望大鱼吃小鱼游戏 的开发 bubblepos[2][1]=450; Java Applet 开 发 的读者有所帮助 。 }
//显示生命值
offScreen.setColor(Color.red); 参考文献 offScreen.fillRect(400,0,life*2,20); 朱 福 喜 , 尹 为 民 , 余 振 坤语言与面向对 象[1] . Java //显示后台的画面 武汉大学出版社 , 2002. g.drawImage(offScreenImage,0,0,this); (收 稿 日 期 , 2009 -5-19) }
public void mouseDragged(MouseEvente)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
,上 接 第 页 ,69 return true;
} (x + size) + m_Frustum[i][B] (y + if(m_Frustum[i][A] * * 这个函数明显要复杂 一 些 , 因为对于每一个边 size) + m_Frustum[i][C]* (z size) + m_Frustum[i][D] > 0) -
的 8 个顶点都需要测试 。 如 果 包 围 盒 的 8 个顶点都 continue;
if(m_Frustum[i][A] * (x - size) + m_Frustum[i][B] * (y - 面 的 背 面 , 包围盒立即被剔 除 。 如果包围盒顶点 落 size) + m_Frustum[i][C]* (z + size) + m_Frustum[i][D] > 0) 的 边 界 面 背 面 ,它 潜 在 地 与 视 锥 相 交 。 如果包围 盒
continue; 在所有边界面 的 正面 , 那 么 包围盒全部包含在视锥 if(m_Frustum[i][A] * (x + size) + m_Frustum[i][B] * (y - 包围盒八个顶点中检测到任何两个顶 点落 在 某个 size) + m_Frustum[i][C]* (z + size) + m_Frustum[i][D] > 0) 侧 , 循 环 就 终 止 , 这时包围盒与视锥相 交 。 continue;
if(m_Frustum[i][A] * (x size) + m_Frustum[i][B] * (y + - 3 结语 size) + m_Frustum[i][C]* (z + size) + m_Frustum[i][D] > 0)
在计算机图形领域中 , 消稳问题是广泛存在 的 continue;
if(m_Frustum[i][A] * (x + size) + m_Frustum[i][B] * (y + 机图形学的不断发展 , 场 景 模 型越来越精细复杂 , size) + m_Frustum[i][C]* (z + size) + m_Frustum[i][D] > 0) 染质量与绘制速度这两者之间的矛盾是消 隐 问 题 的 continue; 文中阐述的视锥剔除算法 提高了渲染时的绘制速度 return false; 地 提 高 场 景 的 绘 制 效 率 。 }(收 稿 日 期 , 2009 -4-19)