用AWT实现简易版飞机大战
来源:互联网 发布:s26t潜艇数据参数 编辑:程序博客网 时间:2024/04/29 13:32
(如有问题欢迎指出,不想看我啰里啰唆一大堆的,可直接下拉有全部代码)
实现效果:
运行以后就是这个效果图,子弹设置的比较少
窗口右上角会有计时
飞机躲避子弹,被子弹击中后飞机爆炸爆炸,然后游戏结束
主要需要的类:(解释取自API 1.6)
1.Frame -java.awt.Frame 是带有标题和边框 的顶层窗口
2.Graphics-java.awt.Graphics 是所有图形上下文的抽象基类,允许应用程序在组件以及闭屏图像上进行绘制,通俗的说,就是Graphics类提供方法来画图片,线段,矩形,椭圆等等
3.Rectangle-java.awt.Rectangle 指定坐标空间中的一个区域(矩形类),通过坐标空间中 Rectangle 对象左上方的点 (x,y)、宽度和高度可以定义这个区域
4.Image-java.awt.Image 是以特定平台的方式获取图形
5.BufferedImage-java.awt.image.BufferedImage 是Image的子类,描述具有可访问图像数据缓冲区的Image
6.ImageIO-javax.imageio.ImageIO 该类包含一些用来查找 ImageReader 和 ImageWriter 以及执行简单编码和解码的静态便捷方法
7.WindowAdapter-java.awt.event.WindowAdapter 是抽象类,此类中的方法为空,此类存在的目的是方便创建侦听器对象
8.WindowEvent-java.awt.event.WindowEvent 是窗口状态改变的低级别事件,比如打开,关闭,激活,停用等
9.KeyAdapter-java.awt.event.KeyAdapter 抽象类,目的是方便创建侦听键盘对象,KeyAdapter 对象实现 KeyListener 接口
10.KeyEvent-java.awt.event.KeyEvent 表示组件中发生键击的事件,当按下、释放或键入某个键时,组件对象(如文本字段)将生成此低级别事件。该事件被传递给每一个 KeyListener 或 KeyAdapter 对象,这些对象使用组件的 addKeyListener 方法注册,以接收此类事件,发生事件时,所有此类侦听器对象都将获得此 KeyEvent
11.URL-java.net.URL 代表一个统一资源定位符,它是指向互联网“资源”的指针,资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,比如对数据库或者搜索引擎的查询
12.IOException-java.io.IOException 当发生某种 I/O 异常时,抛出此异常
13.Thread -java.lang.Thread 线程 是程序中的执行线程,Java 虚拟机允许应用程序并发地运行多个执行线程
代码实现分析:
模拟飞机大战,首先我们需要两个类,飞机类和子弹类,封装了各自对象的属性和方法
1.飞机类:作为一个飞机首先得有个形状,这里用一张图片实现,设置它的长宽,起始坐标,飞机要上下左右移动,其实就是操作它的坐标,用布尔值判断飞机飞向哪个方向,然后对坐标值进行增减,以及布尔值判断飞机生死
飞机类所要实现的方法,第一,需要在我们的窗口将它自己展现出来;第二,它移动时对坐标相应的操作;第三,我们需要实现的效果是按下键盘的上下左右键,飞机对应的上下左右移动,松开键盘,飞机就停止移动;第四,为了判断飞机的生死需要返回可容纳飞机的最小矩形,这里就是容纳飞机的最小矩形如果和子弹最小矩形有相交,则飞机死亡
public class Plane { Image img; double x,y; double width,height; boolean left,up,right,down;//飞机飞行方向 int speed=10;//飞机飞行的速度 boolean live=true; public Plane(String path,double x,double y,double width,double height){ super(); this.img=GameUtil.getImage(path);//GameUtil见下文 this.x=x; this.y=y; this.width=width; this.height=height; } public Plane(){ } /** * 画飞机 * @param g */ public void draw(Graphics g){ if(live){ g.drawImage(img, (int)x, (int)y, (int)width, (int)height, null); move(); } } /** * 飞机沿八个方向飞行 */ public void move(){ if(left){ x-=speed; } if(right){ x+=speed; } if(up){ y-=speed; } if(down){ y+=speed; } } /** * 按下键盘方向键,e.getKeyCode()会返回一个具体的数字,键盘上每一个按键都代表一个数字 * @param e */ public void addDirection(KeyEvent e){ switch (e.getKeyCode()) { case 37://左键 left=true; break; case 38://上键 up=true; break; case 39://右键 right=true; break; case 40://下键 down=true; break; default: break; } } /** * 放开键盘方向键 * @param e */ public void minusDirection(KeyEvent e){ switch (e.getKeyCode()) { case 37://左键 left=false; break; case 38://上键 up=false; break; case 39://右键 right=false; break; case 40://下键 down=false; break; default: break; } } /** * 返回一个刚好容纳飞机的矩形 * @return */ public Rectangle getRect(){ Rectangle r=new Rectangle((int)x,(int)y,(int)width,(int)height); return r; }}
2.子弹类: 类似于飞机类,子弹类也需要坐标控制它的飞行,子弹大小,由于子弹是无规则的在窗口随意运动,所以需要设置子弹的角度,子弹类要实现的方法比较简单,第一,画无规则从窗口中心散出的子弹;第二,返回最小矩形
public class Bullet { double x,y; double degree; int speed=10;//子弹速度 int width=10; int height=10; public Bullet() { super(); this.degree = Math.random()*Math.PI*2;//随机生成子弹运行角度(0-2PI) x=Constant.GAME_WIDTH/2;//关于Constant见下文 y=Constant.GAME_HEIGHT/2; } /** * 画子弹 * @param g */ public void draw(Graphics g){ Color c=g.getColor(); g.setColor(Color.yellow); g.fillOval((int)x, (int)y, width, height);//画圆点 x+=speed*Math.cos(degree); y+=speed*Math.sin(degree); //保证子弹不在窗口内移动,关于Constant见下文 if(x>Constant.GAME_WIDTH-60||x<0){ degree=Math.PI-degree; double tempX=x; double tempY=y; } if(y>Constant.GAME_HEIGHT||y<30){ degree=-degree; double tempY=y; } //保证使用完画笔以后,画笔颜色不变 g.setColor(c); } /** * 返回子弹的矩形 * @return */ public Rectangle getRect(){ Rectangle r=new Rectangle((int)x,(int)y,(int)width,(int)height); return r; }}
3.常量类: 封装了一些常量,便于修改,在飞机类和子弹类中也使用了该类
public class Constant { public static final int GAME_WIDTH=400;//窗口宽 public static final int GAME_HEIGHT=600;//窗口长}
4.工具类: 该工具类只封装了加载图片这个方法,为便于调用方法设置为静态
public class GameUtil { //传入图片的地址,加载图片,注意处理IO异常 public static Image getImage(String path){ URL u=GameUtil.class.getClassLoader().getResource(path); BufferedImage img=null; try { img=ImageIO.read(u); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return img; }}
5.飞机死亡爆炸类: 爆炸也需要爆炸地点即坐标,用一系列图片来实现爆炸,所以也需要设置图片的大小长度和宽度,以及存放这些图片的数组,还需要设置一个int变量来计数,确保你一系类图片加载结束以后就不再爆炸,不会炸个没完没了
public class Explode { double x,y; double width,height; int count=0; static Image[] imgs=new Image[10]; //使用静态块加载图片组,只加载一次,从属于类 static{ for(int i=0;i<imgs.length;i++){ imgs[i]=GameUtil.getImage("images/explode"+(i+1)+".jpg"); //通过调用这个方法,真实的把图片加载出来 imgs[i].getWidth(null); } } public Explode(double x,double y,double width,double height){ super(); this.x=x; this.y=y; this.width=width; this.height=height; } public void draw(Graphics g){ if(count<10){ g.drawImage(imgs[count],(int)x,(int)y,(int)width,(int)height, null); count++; } }}
到这一步,准备工作就做完了,接下来就要把创建窗口类来实现这个游戏,窗口类需要继承Frame类,这里多加了一部,把经常使用的关于窗口的方法包装成一个独立的MyFrame类,它继承Frame类,然后让游戏窗口类直接继承MyFrame类
6.MyFrame类:
第一,窗口的加载,那么就得先聊聊Frame类
Window 对象是一个没有边界和菜单栏的顶层窗口,Windows类提供了方法来设置窗口的大小,位置等信息
在我们加载这个窗口的时候就需要设置这些值,设置好以后就可以运行出一个空白的带框窗口了
第二,定义一个内部线程类,因为我们的飞机和子弹都是时刻在运动的,所以就需要不断的创建新的线程,使飞机和子弹动起来
class PaintThread extends Thread { public void run(){ while(true){ repaint(); try { //线程休眠,控制运动速度 Thread.sleep(40);//1s=100 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
第三,AWT存在闪烁问题,这里使用双缓冲技术消除闪烁,在spring中无需设置,会自动消除闪烁
private Image offScreenImage=null;public void update(Graphics g){ if(offScreenImage==null){ offScreenImage=this.createImage(Constant.GAME_WIDTH,Constant.GAME_HEIGHT); } Graphics gOff=offScreenImage.getGraphics(); paint(gOff); g.drawImage(offScreenImage,0,0,null);}
7.窗口类:
第一,重写父类的launchFrame方法,添加键盘的监听,以及子健的生成
public void launchFrame(){ //调用父类的launchFrame方法 super.launchFrame(); //增加键盘的监听 addKeyListener(new KeyMonitor()); //生成一堆子弹 for(int i=0;i<10;i++){ Bullet b=new Bullet(); bulletList.add(b); } startTime=new Date();}//定义为内部类,可以方便的使用外部类的普通属性class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { plane.addDirection(e); } @Override public void keyReleased(KeyEvent e) { plane.minusDirection(e); }}
第二,往窗口里画东西,飞机,子弹,右上角的计时器
画飞机的首要条件就是飞机还是存活的,直接调用飞机对象的draw方法,
画子弹的时候,因为子弹数目比较多,所以这里需要用到集合的知识,把子弹放在一个List中(这里没有使用泛型,一般建议使用),每创建一个子弹,都要检测它是否与飞机碰撞,若是,则飞机死亡爆炸
画计时器,通过Date类不断创建新的时间对象,startTime在上文中加载窗口方法中就已经计算出确切的时间值了
游戏结束时,显示游戏时间以及Gameover,GameOver比较简单,就是在窗口固定坐标输出一行字,为了方便,我们将在窗口输出文字封装成一个方法pringInfo,显示游戏时间,就是endTime-startTime
关于pringLevel这个方法,是打印输出一些自定义的等级评语,我设置低于20分是**评语,然后30分40分不同的等级评语
Image bg=GameUtil.getImage("images/bg.jpg");//背景图片Date startTime=null;//游戏开始时间Date endTime=null;//游戏结束时间Plane plane=new Plane("images/plane.jpg", 20, 20, 60, 60);//飞机对象ArrayList bulletList=new ArrayList();//容纳子弹的ListExplode boom;//爆炸对象public void paint(Graphics g){ //窗口背景 g.drawImage(bg, 0, 0, 400, 600, null); //画飞机 plane.draw(g); //在飞机存活的情况下 显示飞机存活时间 while(plane.live){ Date newTime=new Date(); int period2=(int)(newTime.getTime()-startTime.getTime())/1000; pringInfo(g, "时间:"+period2+"秒", 30,Color.blue,Constant.GAME_WIDTH-150,60); break; } //画子弹 for(int i=0;i<bulletList.size();i++){ Bullet b=(Bullet)bulletList.get(i); b.draw(g); //检测子弹和飞机的碰撞 boolean peng=b.getRect().intersects(plane.getRect()); if(peng){ //飞机死掉 plane.live=false; //飞机爆炸 if(boom==null){ boom=new Explode(plane.x, plane.y, plane.width+10, plane.height+10); endTime=new Date();//停止计时 } boom.draw(g); } } //游戏结束 if(!plane.live){ pringInfo(g, "GAME OVER", 50,Color.RED,80,Constant.GAME_HEIGHT/2); //计算生存时间 int period=(int)(endTime.getTime()-startTime.getTime())/1000; pringLevel(period, g); pringInfo(g, "生存时间:"+period+"秒", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+30); }}//在窗口打印文字,参数分别代表,画笔,文字,大小,颜色,坐标x,坐标ypublic void pringInfo(Graphics g,String str,int size,Color color,int x,int y){ Color c=g.getColor(); Font f=new Font("宋体",Font.BOLD,size); g.setColor(color); g.setFont(f); g.drawString(str,x,y); g.setColor(c);}//打印等级评语(忽视评语 = = )public void pringLevel(int period,Graphics g){ switch (period/10){ case 0: case 1: pringInfo(g, "菜鸟!妈的智障", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 2: pringInfo(g, "你还只是个小白", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 3: pringInfo(g, "有前途的年轻人", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 4: pringInfo(g, "前排的观众在为你欢呼", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 5: pringInfo(g, "志玲姐姐要给你生猴子", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; default: break; }}
这是跟着尚学堂高淇老师做的小游戏项目,java300集第一季中的课程,大家有兴趣可以去看看老高讲的,这个游戏对于飞机大战这个称号还是相差甚远,首先飞机不能反击,只能躲避,再者,飞机可以跑到窗口外面,想呆多久呆多久,反正子弹是困在窗口里出不去,所以需要人为的控制不让飞机出去,不然这个游戏就完全没意义了,关于这个等级,好的效果应该是,达到一定的成绩飞机可以升级成更高级的飞机,就是换个更漂亮的图片,飞机反击是个比较难做的事情,它坐标控制设置得合情合理,不能飞机左右移动一下所有子弹都同时水平和它移动过去,得有个逐渐的效果出来,如果要换子弹还需要在子弹类添加样式图片,飞机升级对应的子弹也升级,我们就省去那些吃了道具以后飞机变强的高级要求了,游戏还有待加强,当然这些也只是没有实践过的纸上谈兵,可能真的实现起来就会跑出各种问题了
这个游戏项目很好的加强了对于类的封装,继承这两个概念,尤其封装,把打印文字封装为一个方法,调用起来就会很方便,常量类里面虽然只有两个量,看起来很寒酸,但是你想修改窗口大小的时候,只需要该两个地方就好了,不用满世界的找着该,项目大了,就可以体会到常量类的好处了,还有飞机类,子弹类,把关于他们的方法全部封装在类里,调用起来就很方便,代码可读性高,看起来也很简洁
这个游戏还是接触到了很多不太熟悉的层面,下面列举一下:
1.键盘的监控,按下和释放
2.内部类设置监听器,这里用到了监听器
3.ImageIO,加载图片
4.Graphics g画笔
5.控制子弹不出窗口,设置坐标角度,个人觉得也比较棘手
6.飞机子弹相撞就是判断两个矩形有没有相交,这个概念也是全新的
7.利用双缓冲技术消除闪烁
8.重画窗口的线程内部类
9.实现点叉关闭窗口(匿名内部类),涉及到Windows类
全部代码:
package cn.wwy.util;/** * 游戏中用到的常量 * @author wwyDEPP * */public class Constant { public static final int GAME_WIDTH=400; public static final int GAME_HEIGHT=600;}
package cn.wwy.util;import java.awt.Image;import java.awt.image.BufferedImage;import java.io.IOException;import java.net.URL;import javax.imageio.ImageIO;/** * 游戏开发中常用的工具类(如:加载图片) * @author wwyDEPP */public class GameUtil { public static Image getImage(String path){ URL u=GameUtil.class.getClassLoader().getResource(path); BufferedImage img=null; try { img=ImageIO.read(u); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return img; }}
package cn.wwy.util;import java.awt.Frame;import java.awt.Graphics;import java.awt.Image;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;/** * 封装了窗口的实现方法 * @author wwyDEPP * */public class MyFrame extends Frame{ /** * 加载窗口 */ public void launchFrame(){ setSize(Constant.GAME_WIDTH,Constant.GAME_HEIGHT); setLocation(100,100); setVisible(true); new PaintThread().start(); //实现点叉关闭窗口(匿名内部类) addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } /** * 利用双缓冲技术消除闪烁 * 这里用的是AWT,用Spring它就会自动处理闪烁 */ private Image offScreenImage=null; public void update(Graphics g){ if(offScreenImage==null){ offScreenImage=this.createImage(Constant.GAME_WIDTH,Constant.GAME_HEIGHT); } Graphics gOff=offScreenImage.getGraphics(); paint(gOff); g.drawImage(offScreenImage,0,0,null); } /** * 定义一个重画窗口的线程类,是一个内部类 * @author wwyDEPP */ class PaintThread extends Thread { public void run(){ while(true){ repaint(); try { Thread.sleep(40);//1s=100 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}
package cn.wwy.plane;/** * 飞机类 * @author wwyDEPP */import java.awt.Graphics;import java.awt.Image;import java.awt.Rectangle;import java.awt.event.KeyEvent;import cn.wwy.util.GameUtil;public class Plane { Image img; double x,y; double width,height; boolean left,up,right,down; int speed=10; boolean live=true; public Plane(String path,double x,double y,double width,double height){ super(); this.img=GameUtil.getImage(path); this.x=x; this.y=y; this.width=width; this.height=height; } public Plane(){ } /** * 画飞机 * @param g */ public void draw(Graphics g){ if(live){ g.drawImage(img, (int)x, (int)y, (int)width, (int)height, null); move(); } } /** * 飞机沿八个方向飞行 */ public void move(){ if(left){ x-=speed; } if(right){ x+=speed; } if(up){ y-=speed; } if(down){ y+=speed; } } /** * 按下键盘方向键 * @param e */ public void addDirection(KeyEvent e){ switch (e.getKeyCode()) { case 37://左键 left=true; break; case 38://上键 up=true; break; case 39://右键 right=true; break; case 40://下键 down=true; break; default: break; } } /** * 放开键盘方向键 * @param e */ public void minusDirection(KeyEvent e){ switch (e.getKeyCode()) { case 37://左键 left=false; break; case 38://上键 up=false; break; case 39://右键 right=false; break; case 40://下键 down=false; break; default: break; } } /** * 返回一个刚好容纳飞机的矩形 * @return */ public Rectangle getRect(){ Rectangle r=new Rectangle((int)x,(int)y,(int)width,(int)height); return r; }}
package cn.wwy.plane;import java.awt.Color;import java.awt.Graphics;import java.awt.Rectangle;import cn.wwy.util.Constant;/** * 子弹类 * @author wwyDEPP * */public class Bullet { double x,y; double degree; int speed=10; int width=10; int height=10; public Bullet() { super(); this.degree = Math.random()*Math.PI*2; x=Constant.GAME_WIDTH/2; y=Constant.GAME_HEIGHT/2; } /** * * @param g */ public void draw(Graphics g){ Color c=g.getColor(); g.setColor(Color.yellow); g.fillOval((int)x, (int)y, width, height); x+=speed*Math.cos(degree); y+=speed*Math.sin(degree); if(x>Constant.GAME_WIDTH-60||x<0){ degree=Math.PI-degree; double tempX=x; double tempY=y; } if(y>Constant.GAME_HEIGHT||y<30){ degree=-degree; double tempY=y; } g.setColor(c); } /** * 返回子弹的矩形 * @return */ public Rectangle getRect(){ Rectangle r=new Rectangle((int)x,(int)y,(int)width,(int)height); return r; }}
package cn.wwy.plane;import java.awt.Graphics;import java.awt.Image;import cn.wwy.util.GameUtil;/** * 爆炸类 * 数组图片的切换 * @author wwyDEPP * */public class Explode { double x,y; double width,height; int count=0; static Image[] imgs=new Image[10]; static{ for(int i=0;i<imgs.length;i++){ imgs[i]=GameUtil.getImage("images/explode"+(i+1)+".jpg"); //通过调用这个方法,真实的把图片加载出来 imgs[i].getWidth(null); System.out.println("aaa"); } } public Explode(double x,double y,double width,double height){ this.x=x; this.y=y; this.width=width; this.height=height; } public void draw(Graphics g){ if(count<10){ g.drawImage(imgs[count],(int)x,(int)y,(int)width,(int)height, null); count++; System.out.println("sasasa"+count); } }}
package cn.wwy.plane;/** * 游戏窗口类 * @author wwyDEPP * */import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Image;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.util.ArrayList;import java.util.Date;import cn.wwy.util.Constant;import cn.wwy.util.GameUtil;import cn.wwy.util.MyFrame;public class PlaneGameFrame extends MyFrame{ Date startTime=null; Date endTime=null; //为了使飞机死掉以后停止计时 Image bg=GameUtil.getImage("images/bg.jpg"); Plane plane=new Plane("images/plane.jpg", 20, 20, 60, 60); ArrayList bulletList=new ArrayList(); Explode boom; /** * 在游戏窗口上画东西 */ public void paint(Graphics g){ g.drawImage(bg, 0, 0, 400, 600, null); plane.draw(g); while(plane.live){ Date newTime=new Date(); int period2=(int)(newTime.getTime()-startTime.getTime())/1000; pringInfo(g, "时间:"+period2+"秒", 30,Color.blue,Constant.GAME_WIDTH-150,60); break; } for(int i=0;i<bulletList.size();i++){ Bullet b=(Bullet)bulletList.get(i); b.draw(g); //检测子弹和飞机的碰撞 boolean peng=b.getRect().intersects(plane.getRect()); if(peng){ //飞机死掉 plane.live=false; //飞机爆炸 if(boom==null){ boom=new Explode(plane.x, plane.y, plane.width+10, plane.height+10); endTime=new Date(); } boom.draw(g); } } if(!plane.live){ pringInfo(g, "GAME OVER", 50,Color.RED,80,Constant.GAME_HEIGHT/2); //计算生存时间 int period=(int)(endTime.getTime()-startTime.getTime())/1000; pringLevel(period, g); pringInfo(g, "生存时间:"+period+"秒", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+30); } } /** * 在父类基础上添加键盘的监听 * 以及子弹的生成 */ public void launchFrame(){ //调用父类的launchFrame方法 super.launchFrame(); //增加键盘的监听 addKeyListener(new KeyMonitor()); //生成一堆子弹 for(int i=0;i<10;i++){ Bullet b=new Bullet(); bulletList.add(b); } startTime=new Date(); } /** * 在窗口打印信息 * @param g * @param str * @param size */ public void pringInfo(Graphics g,String str,int size,Color color,int x,int y){ Color c=g.getColor(); Font f=new Font("宋体",Font.BOLD,size); g.setColor(color); g.setFont(f); g.drawString(str,x,y); g.setColor(c); } public void pringLevel(int period,Graphics g){ switch (period/10){ case 0: case 1: pringInfo(g, "菜鸟!妈的智障", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 2: pringInfo(g, "你还只是个小白", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 3: pringInfo(g, "有前途的年轻人", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 4: pringInfo(g, "前排的观众在为你欢呼", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; case 5: pringInfo(g, "志玲姐姐要给你生猴子", 30,Color.WHITE,35,Constant.GAME_HEIGHT/2+70); break; default: break; } } public static void main(String[] args) { PlaneGameFrame pgf=new PlaneGameFrame(); pgf.launchFrame(); } //定义为内部类,可以方便的使用外部类的普通属性 class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { plane.addDirection(e); } @Override public void keyReleased(KeyEvent e) { plane.minusDirection(e); } }}
- 用AWT实现简易版飞机大战
- 简易版飞机大战源码下载
- Python:用Pygame实现飞机大战小游戏
- Phaser实现飞机大战
- JavaSwing实现飞机大战
- 飞机大战游戏实现
- Unity_简易飞机大战制作(一)
- JavaScript版飞机大战
- Python版飞机大战
- cocos2dx飞机大战Cocos2d-x飞机实现
- 飞机大战-MyPlane自己飞机的实现
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 04.游戏界面 主角飞机的添加
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 05.游戏界面 主角飞机的移动
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 06.游戏界面 主角飞机产生子弹
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战02 主界面创建
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 09.游戏界面 道具
- [cocos2d-x][游戏开发]通过cocos2d-x实现简易飞机大战 10.游戏界面 特效
- Javascript实现飞机大战小游戏
- Python暗通道图像去雾
- 判断指针是否有效
- 【慕课笔记】1-1 网络基础知识-网络基础简介
- Python基础——学习笔记
- 汇编学习4:寄存器之CPU工作原理
- 用AWT实现简易版飞机大战
- SQL中,where 与 having 的性能比较
- 交换排序之快速排序
- 低级鼠标钩子WH_MOUSE_LL
- 设计模式系列之十:命令模式
- A very Nice Linux System, its name is Korora
- Guava之ListenableFuture(链式回调)
- Java的JAR包, EAR包 ,WAR包内部结构
- 设计模式系列之十一:装饰者模式