您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

《Java小游戏实现》:坦克大战(续2)

2024/3/14 8:01:46发布27次查看
《java小游戏实现》:坦克大战
《java小游戏实现》:坦克大战(续一)
博文《java小游戏实现》:坦克大战(续1)中已经实现到了坦克可以发射一颗子弹了。这篇博文在此基础上继续实现更多的功能。
完成功能:坦克发射多颗子弹
有了坦克发射一颗子弹的基础,发射多颗子弹就相当简单的,只需要在tankclien类中加入一个容器来存放多枚子弹即可。由于容器的容量也是有限的,我们不能一直往里面装。因此,在子弹类中,我们为子弹对象引入了一个live属性,用来判断这个子弹是否还存活。判断子弹是否还存活是根据子弹的位置是否出界。
下面只贴出完成这个功能相关代码
tankclient.java
<code class="hljs cs"> private list<missile> missiles = new arraylist<missile> (); public list<missile> getmissiles() { return missiles; } @override public void paint(graphics g) { //直接调用坦克类的draw方法 tk.draw(g); //画子弹 for(int i=0;i<missiles.size();i++){ code="" missile="" ms="missiles.get(i);"></missiles.size();i++){></missile></missile></missile></code>
missile.java类
在move方法中根据子弹所在的位置判断子弹是否还存活。
<code class="hljs cs"><code class="hljs cs"> public class missile { private void move() { if(dir==direction.l){//l,lu,u,ru,r,rd,d,ld,stop x -= xspeed; } else if(dir==direction.lu){ x -= xspeed; y -= yspeed; } else if(dir==direction.u){ y -= yspeed; } else if(dir==direction.ru){ x += xspeed; y -= yspeed; } else if(dir==direction.r){ x += xspeed; } else if(dir==direction.rd){ x += xspeed; y += yspeed; } else if(dir==direction.d){ y += yspeed; } else if(dir==direction.ld){ x -= xspeed; y += yspeed; } //根据子弹所在的位置x,y来判断子弹是否还存活在 if(x<0||x>tankclient.game_width||y<0||y>tankclient.game_height){ live = false; } } public boolean islive() { return live; } } </code></code>
tank.java文件内容如下:
在坦克类中,在keypressed方法中,每按一次ctrl键,就发射一颗子弹。
<code class="hljs cs"><code class="hljs cs"> public class tank { //记录键盘的按键情况 public void keypressed(keyevent e){ int key=e.getkeycode(); //system.out.println(key); switch(key){ case 17: tc.getmissiles().add(fire()); break; case keyevent.vk_left: b_l=true; break; case keyevent.vk_up: b_u=true; break; case keyevent.vk_right: b_r=true; break; case keyevent.vk_down: b_d=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 movedirection(); } } </code></code>
完整代码下载链接:http://download.csdn.net/detail/u010412719/9555292
完成功能:解决坦克越界问题
坦克越界问题比较简单,只需要判断坦克所在的位置是否越界,如果越界,则将其位置设置为边界位置即可。
实现代码如下:
<code class="hljs cs"><code class="hljs cs"> /* * 函数功能:处理坦克越界问题 * */ private void dealtankborder() { if(x<0){ x = 0; } else if(x > tankclient.game_width-this.width){ x = tankclient.game_width-this.width ; } if(y<0){ y = 0; } else if(y>tankclient.game_width - this.height){ y = tankclient.game_width - this.height; } }</code></code>
上面函数在move()方法最后进行调用即可。
完成功能:加入敌人的坦克
前面实现的所用功能是自己一个坦克在界面上面运动呀、发子弹呀等等。
下面我们完成在界面上加入一个敌人坦克。
实现敌人坦克有两种方式
1、第一种是再新建一个enemytank类,
2、第二种是在原来的tank类中加入一个属性来表示此坦克的类型。
由于我们有一个坦克类了,为方便起见,这里采用第二种方式:在原来的tank类中加入一个属性来表示此坦克的类型。
tank.java中新增加的内容主要有
<code class="hljs cs"><code class="hljs java"> //添加一个属性,表示此坦克是好还是坏 private boolean good; //更改下构造方法 public tank(int x, int y,boolean good) { this.x = x; this.y = y; this.good = good; } public tank(int x, int y,boolean good, tankclient tc) { this(x,y,good); this.tc = tc; } //根据坦克的类型给出不同的颜色 public void draw(graphics g){ color c = g.getcolor(); if(good){ g.setcolor(color.red); } else{ g.setcolor(color.blue); } g.filloval(x, y, width, height); g.setcolor(c); //画一个炮筒 drawgunbarrel(g); move();//根据键盘按键的结果改变坦克所在的位置 }
missile类没有任何变动。
总管家tankclient.java中需要添加的内容有:
1、new 出两个坦克对象
<code class="hljs cs"><code class="hljs cs">private tank tk=new tank(50,50,true,this); private tank enemy = new tank(100,100,false,this);</code></code>
2、在paint方法中画出两个坦克
<code class="hljs cs"><code class="hljs cs"> @override public void paint(graphics g) { //直接调用坦克类的draw方法 tk.draw(g); enemy.draw(g); //画子弹 for(int i=0;i<missiles.size();i++){ code="" missile="" ms="missiles.get(i);"></missiles.size();i++){></code></code>
<喎�"/kf/ware/vc/" target="_blank" class="keylink">vcd4ncjxwpjxjb2rlignsyxnzpq=="hljs cs">以上就实现了添加敌对坦克这一功能,但是还没有对其添加随机运动。
完成的功能:子弹打死敌人坦克
经过上面的实现,我们有了一个不会动且不会发子弹的傻傻的敌对坦克,但是我们也不能打死它,下面我们就来实现打死坦克。哈哈,是不是稍微变得有趣一点了。
分析:
1、由于是子弹打死敌人坦克,根据面向对象的思想,在子弹类中,加入一个hittank方法
<code class="hljs cs"><code class="hljs cs"><code>public boolean hittank(tank t){ } </code></code></code>
2、那么hittank这个方法应该如何来判断是否子弹打中了该坦克呢??这就涉及到一个碰撞的问题。由于我们的子弹和坦克都是矩形,因此碰撞问题就得到了很好的简化,只是判断两个矩形是否有重叠的部分。如果有,则就判断发生了碰撞,子弹就打中了坦克。
因此,在missile类和tank类中,,均添加一个getrect()方法,返回子弹和坦克所在的矩形区域对象。
<code class="hljs cs"><code class="hljs cs"><code>public rectangle getrect(){ return new rectangle(x, y, width, height); } </code></code></code>
3、当子弹打中了坦克,则子弹和坦克就应该都消失。因此,在坦克中需要引入一个布尔变量来判断坦克是否存活
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> public boolean hittank(tank t){ //首先判断此坦克是否是存活的,如果是死的,就不打了 if(!t.islive()){ return false; } if(this.getrect().intersects(t.getrect())){//判断是否有碰撞 //碰撞之后,子弹和该坦克就应该都死了 this.live = false;//子弹死了 t.setlive(false);//坦克死了 return true; } else{ return false; } }</code></code></code>
无论是子弹消失,在前面的版本中有处理,但是本版本上的坦克消失,目前的处理方法就是不绘画出来,即在draw方法中,首先判断一下,看此对象是否存活,如果存活,则绘画出来。
代码如下:
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"> public void draw(graphics g){ if(!live){ //判断坦克是否存活,如果死了,则不绘画出来,直接返回 return ; } color c = g.getcolor(); if(good){ g.setcolor(color.red); } else{ g.setcolor(color.blue); } g.filloval(x, y, width, height); g.setcolor(c); //画一个炮筒 drawgunbarrel(g); move();//根据键盘按键的结果改变坦克所在的位置 } </code></code></code>
最后,贴下tank类、missile类、tankclient类的完整代码:
tank类
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> public class tank { //坦克所在的位置坐标 private int x; private int y; //坦克的高度和宽度 private static final int width = 30; private static final int height = 30; //定义两个常量,表示运动的速度 private static final int xspeed = 5; private static final int yspeed = 5; //定义四个布尔类型变量来记录按键的情况,默认状态下为false,表示没有键按下 private boolean b_l,b_u,b_r,b_d; //添加一个属性,表示此坦克是好还是坏 private boolean good; public boolean isgood() { return good; } //用来标识此坦克对象是否存活 private boolean live =true; public boolean islive() { return live; } public void setlive(boolean live) { this.live = live; } //定义一个枚举类型来表示运行的方向 public enum direction{ l,lu,u,ru,r,rd,d,ld,stop } //定义一个变量来表示坦克要运行的方向,初始状态为stop private direction dir = direction.stop; //炮筒方向 private direction ptdir = direction.d; private tankclient tc; public tank(int x, int y,boolean good) { this.x = x; this.y = y; this.good = good; } public tank(int x, int y,boolean good, tankclient tc) { this(x,y,good); this.tc = tc; } public void draw(graphics g){ if(!live){ //判断坦克是否存活,如果死了,则不绘画出来,直接返回 return ; } color c = g.getcolor(); if(good){ g.setcolor(color.red); } else{ g.setcolor(color.blue); } g.filloval(x, y, width, height); g.setcolor(c); //画一个炮筒 drawgunbarrel(g); move();//根据键盘按键的结果改变坦克所在的位置 } private void drawgunbarrel(graphics g) { int centerx = this.x + this.width/2; int centery = this.y + this.height/2; if(ptdir==direction.l){//l,lu,u,ru,r,rd,d,ld,stop g.drawline(centerx, centery, x, y + height/2); } else if(ptdir==direction.lu){ g.drawline(centerx, centery, x, y ); } else if(ptdir==direction.u){ g.drawline(centerx, centery, x+ width/2, y ); } else if(ptdir==direction.ru){ g.drawline(centerx, centery, x + width, y ); } else if(ptdir==direction.r){ g.drawline(centerx, centery, x+ width, y + height/2); } else if(ptdir==direction.rd){ g.drawline(centerx, centery, x+ width, y + height); } else if(ptdir==direction.d){ g.drawline(centerx, centery, x+ width/2, y + height); } else if(ptdir==direction.ld){ g.drawline(centerx, centery, x, y + height); } } //记录键盘的按键情况 public void keypressed(keyevent e){ int key=e.getkeycode(); //system.out.println(key); switch(key){ // case 17://避免因ctrl一直按下,一直发射子弹,因此将这一功能放入keyreleased方法中了 // tc.getmissiles().add(fire()); // break; case keyevent.vk_left: b_l=true; break; case keyevent.vk_up: b_u=true; break; case keyevent.vk_right: b_r=true; break; case keyevent.vk_down: b_d=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 movedirection(); } //键盘按键松下时,也要进行记录 public void keyreleased(keyevent e) { int key=e.getkeycode(); switch(key){ case 17: tc.getmissiles().add(fire()); break; case keyevent.vk_left: b_l=false; break; case keyevent.vk_up: b_u=false; break; case keyevent.vk_right: b_r=false; break; case keyevent.vk_down: b_d=false; break; } } //根据键盘的按键情况来确定坦克的运行方向 private void movedirection() {//l,lu,u,ru,r,rd,d,ld,stop if(b_l&&!b_u&&!b_r&&!b_d){ dir = direction.l; } else if(b_l&&b_u&&!b_r&&!b_d){ dir = direction.lu; } else if(!b_l&&b_u&&!b_r&&!b_d){ dir = direction.u; } else if(!b_l&&b_u&&b_r&&!b_d){ dir = direction.ru; } else if(!b_l&&!b_u&&b_r&&!b_d){ dir = direction.r; } else if(!b_l&&!b_u&&b_r&&b_d){ dir = direction.rd; } else if(!b_l&&!b_u&&!b_r&&b_d){ dir = direction.d; } else if(b_l&&!b_u&&!b_r&&b_d){ dir = direction.ld; } else{//其它所有情况,都是不动 dir = direction.stop; } //将坦克方向赋值给炮筒方向 if(dir!=direction.stop){ ptdir = dir; } } //上面有运行方向,但是还缺少具体的运行细节,例如:假设是按下了右键,则应该横坐标x+=xspeed; private void move(){ if(dir==direction.l){//l,lu,u,ru,r,rd,d,ld,stop x -= xspeed; } else if(dir==direction.lu){ x -= xspeed; y -= yspeed; } else if(dir==direction.u){ y -= yspeed; } else if(dir==direction.ru){ x += xspeed; y -= yspeed; } else if(dir==direction.r){ x += xspeed; } else if(dir==direction.rd){ x += xspeed; y += yspeed; } else if(dir==direction.d){ y += yspeed; } else if(dir==direction.ld){ x -= xspeed; y += yspeed; } else if(dir==direction.stop){ //... nothing } //处理坦克越界问题 dealtankborder(); } /* * 函数功能:处理坦克越界问题 * */ private void dealtankborder() { if(x<0){ x = 0; } else if(x > tankclient.game_width-this.width){ x = tankclient.game_width-this.width ; } if(y<0){ y = 0; } else if(y>tankclient.game_width - this.height){ y = tankclient.game_width - this.height; } } public missile fire(){ //计算子弹的位置,并利用炮筒的方向来new一个子弹对象 int x = this.x +(this.width)/2 - (missile.width)/2; int y = this.y + (this.height)/2 -(missile.height)/2; missile ms = new missile(x,y,this.ptdir); return ms; } /* * 函数功能:得到坦克所在位置的矩形框 * */ public rectangle getrect(){ return new rectangle(x, y, width, height); } }</code></code></code>
missile类
代码如下
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> public class missile { //定义两个常量,表示运动的速度 private static final int xspeed = 10; private static final int yspeed = 10; //子弹所在的位置 private int x; private int y; //坦克的高度和宽度 public static final int width = 10; public static final int height = 10; //子弹的运行方向 private direction dir; private boolean live = true; public missile(int x, int y, direction dir) { this.x = x; this.y = y; this.dir = dir; } public void draw(graphics g){ //如果该子弹不是存活的,则不进行绘图 if(!live){ return ; } color c = g.getcolor(); g.setcolor(color.yellow); g.filloval(x, y, width, height); g.setcolor(c); move(); } private void move() { if(dir==direction.l){//l,lu,u,ru,r,rd,d,ld,stop x -= xspeed; } else if(dir==direction.lu){ x -= xspeed; y -= yspeed; } else if(dir==direction.u){ y -= yspeed; } else if(dir==direction.ru){ x += xspeed; y -= yspeed; } else if(dir==direction.r){ x += xspeed; } else if(dir==direction.rd){ x += xspeed; y += yspeed; } else if(dir==direction.d){ y += yspeed; } else if(dir==direction.ld){ x -= xspeed; y += yspeed; } //根据子弹所在的位置x,y来判断子弹是否还存活在 if(x<0||x>tankclient.game_width||y<0||y>tankclient.game_height){ live = false; } } public boolean islive() { return live; } public rectangle getrect(){ return new rectangle(x, y, width, height); } public boolean hittank(tank t){ //首先判断此坦克是否是存活的,如果是死的,就不打了 if(!t.islive()){ return false; } if(this.getrect().intersects(t.getrect())){//判断是否有碰撞 //碰撞之后,子弹和该坦克就应该都死了 this.live = false;//子弹死了 t.setlive(false);//坦克死了 return true; } else{ return false; } } </code></code></code>
tankclient类代码如下:
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> /* * 此版本添加了子弹打死敌对坦克 * */ public class tankclient extends frame{ public final static int game_width=600; public final static int game_height=600; private tank tk=new tank(50,50,true,this); private tank enemy = new tank(100,100,false,this); private list<missile> missiles = new arraylist<missile> (); public list<missile> getmissiles() { return missiles; } private image offscreenimage = null; public static void main(string[] args) { new tankclient().launchframe(); } @override public void update(graphics g) { if (offscreenimage == null) { offscreenimage = this.createimage(game_width, game_height); } graphics goffscreen = offscreenimage.getgraphics();// 重新定义一个画虚拟桌布的画笔// color c = goffscreen.getcolor(); goffscreen.setcolor(color.darkgray); goffscreen.fillrect(0, 0, game_width, game_height); goffscreen.setcolor(c); paint(goffscreen); g.drawimage(offscreenimage, 0, 0, null); } @override public void paint(graphics g) { //直接调用坦克类的draw方法 tk.draw(g); enemy.draw(g); //画子弹 for(int i=0;i<missiles.size();i++){ catch="" code="" extends="" implements="" interruptedexception="" keyevent="" keymonitor="" missile="" ms="missiles.get(i);" myrepaint="" new="" override="" private="" public="" try="" void="" windowevent=""></missiles.size();i++){></missile></missile></missile></code></code></code>
以上就完成了坦克发射子弹可以击打敌对坦克的功能。
未完,剩余功能见下篇博文
以上就是《java小游戏实现》:坦克大战(续2)的内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product