java制作简单的坦克大战
程序员文章站
2024-03-02 16:52:28
详情请参照注释,这里就不多废话了,实现一下儿时的经典而已。
blood.java
package com.hkm.tankwar;
import java.a...
详情请参照注释,这里就不多废话了,实现一下儿时的经典而已。
blood.java
package com.hkm.tankwar; import java.awt.*; /** * 血块类,我方坦克吃了可回血; * @author hekangmin * */ public class blood { private int x,y,w,h;//血块的位置和宽度高度; private tankwarclient tc; private int step=0;//纪录血块移动的步数; private boolean live=true; public boolean islive() { return live; } public void setlive(boolean live) { this.live = live; } /** * 纪录血块的位置; */ private int[][] pos={{400,300},{400,320},{420,320},{440,300},{440,330},{480,400},{520,400},{540,400}}; public blood() { x=pos[0][0]; y=pos[0][1]; w=h=18; } public void draw(graphics g) { if(!live) return; color c=g.getcolor(); g.setcolor(color.cyan); g.filloval(x, y, w, h); g.setcolor(c); move(); } /** * 移动血块 */ public void move() { step++; if(step>=pos.length) step=0; else{ x=pos[step][0]; y=pos[step][1]; } } public rectangle getrect() { return new rectangle(x,y,w,h); } }
explode.java
package com.hkm.tankwar; import java.awt.*; /** * 爆炸类 * @author hekangmin * */ public class explode { private int x,y;//爆炸发生的位置 private boolean live=true; int dia[]={4,8,12,16,32,40,20,14,4};//用园模拟,代表圆的直径; int step=0;//区别移到第几个直径 private tankwarclient tc;//持有引用 public explode(int x,int y,tankwarclient tc) { this.x=x; this.y=y; this.tc=tc; } public void draw(graphics g) { if(!live) { tc.explodes.remove(this); return; } if(step==dia.length)//如果到了最后一个直径爆炸死亡; { live=false; step=0; return; } color c=g.getcolor(); g.setcolor(color.yellow); g.filloval(x, y, dia[step], dia[step]); g.setcolor(c); step++; } }
missile.java
package com.hkm.tankwar; import java.awt.*; import java.awt.event.*; import java.awt.event.keyevent; import java.util.list; /** * 子弹类 * @author hekangmin * */ public class missile { private int x,y;//子弹的位置 private tank.direction dir;//坦克方向 private static final int xspeed=10;//坦克x方向的移动速度, private static final int yspeed=10;//坦克y方向的移动速度, public static final int width=10; public static final int height=10; private boolean live=true;//判断子弹是否活着 private boolean good;//区分敌军子弹和我军子弹 private tankwarclient tc; public missile(int x, int y, tank.direction dir) { this.x = x; this.y = y; this.dir = dir; } public missile(int x,int y,boolean good,tank.direction dir,tankwarclient tc) { this(x,y,dir); this.good=good;//将坦克好坏的属性与子弹还坏属性设为相同; this.tc=tc; } /** * 画出子弹 * @param g为画笔 */ public void draw(graphics g) { if(!live) { tc.missiles.remove(this); return; } color c=g.getcolor(); if(good) { g.setcolor(color.blue); } else g.setcolor(color.orange); g.filloval(x, y, width, height); g.setcolor(c); move(); } /** * 根据坦克的方向让子弹移动 */ private void move() { switch(dir) { case l: x-=xspeed; break; case lu: x-=xspeed; y-=yspeed; break; case u: y-=yspeed; break; case ru: x+=xspeed; y-=yspeed; break; case r: x+=xspeed; break; case rd: x+=xspeed; y+=yspeed; break; case d: y+=yspeed; break; case ld: x-=xspeed; y+=yspeed; break; } if(x<0||y<0||x>tankwarclient.game_width||y>tankwarclient.game_height)//子弹越界则让其死亡; { live=false; } } public boolean islive() { return live; } public rectangle getrect()//获取子弹的矩形区域; { return new rectangle(this.x,this.y,this.width,this.height); } /** * 判断子弹与坦克碰撞; * @param t为坦克 * @return返回true则表示发生碰撞,否则没有碰撞; */ public boolean hittank(tank t) { if(this.live&&this.getrect().intersects(t.getrect())&&t.islive()&&this.good!=t.isgood()) { if(t.isgood()) { t.setlife(t.getlife()-10); if(t.getlife()<=0) t.setlive(false); }else{ t.setlive(false); } this.live=false;///将子弹设为死亡; explode e=new explode(x,y,tc);//发生爆炸; tc.explodes.add(e); return true; } return false; } /** * 判断子弹与敌军坦克相撞; * @param tanks敌军坦克 * @returntrue表示相撞,false没有相撞; */ public boolean hittanks(list<tank> tanks) { for(int i=0;i<tanks.size();i++) { if(hittank(tc.tanks.get(i))) { return true; } } return false; } /** * 判断子弹是否撞墙 * @param w墙 * @returntrue,撞上,false,未撞上; */ public boolean hitswall(wall w) { if(this.live&&this.getrect().intersects(w.getrect())) { live=false; return true; } return false; } }
tank.java
package com.hkm.tankwar; import java.awt.*; import java.awt.event.keyevent; import java.util.*; /** * 坦克类 * @author hekangmin * */ public class tank { public static final int xspeed=5;//坦克x方向速度 public static final int yspeed=5; public static final int width=30; public static final int height=30; private bloodbar bb=new bloodbar();//血条 private int life=100; public int getlife() { return life; } public void setlife(int life) { this.life = life; } private static random r=new random(); private static int step=r.nextint(12)+3;//定义一个数表示敌军坦克随机东的步数; private boolean bl=false,bu=false,br=false,bd=false; enum direction{l,lu,u,ru,r,rd,d,ld,stop};//利用枚举类型定义坦克方向; private int x,y; private int oldx,oldy;//纪录上一步坦克的位置; private boolean live=true;//判断是否活着 public boolean islive() { return live; } public void setlive(boolean live) { this.live = live; } private boolean good;//坦克是好是坏 public boolean isgood() { return good; } private direction ptdir=direction.d;//新增炮筒的方向; tankwarclient tc;//为了持有对方的引用以可以方便访问其成员变量; direction dir=direction.stop;//一开始将坦克方向设为stop; public tank(int x,int y,boolean good,direction dir,tankwarclient tc) { this.x=x; this.y=y; this.oldx=x; this.oldy=y; this.good=good; this.dir=dir; this.tc=tc;//持有对方的引用; } public void draw(graphics g) { if(!live)//如果死亡则不再draw; { if(!good) { tc.tanks.remove(this); if(tc.tanks.size()<5)//少于5辆坦克时添加坦克; { for(int i=0;i<10;i++) { int posx=r.nextint(800); int posy=r.nextint(600); tc.tanks.add(new tank(posx,posy,false,direction.d,tc));//使得坦克出现的位置随机 } } } return; } color c=g.getcolor(); if(good) { g.setcolor(color.red); bb.draw(g); } else g.setcolor(color.black); g.filloval(x, y, width, height); g.setcolor(c); switch(ptdir)//画出炮筒的方向; { case l: g.drawline(x+tank.width/2, y+tank.height/2, x-10, y+tank.height/2);//画出炮筒,画一条直线代替; break; case lu: g.drawline(x+tank.width/2, y+tank.height/2, x-7, y-7); break; case u: g.drawline(x+tank.width/2, y+tank.height/2, x+tank.width/2, y-10); break; case ru: g.drawline(x+tank.width/2, y+tank.height/2, x+tank.width+7, y-7); break; case r: g.drawline(x+tank.width/2, y+tank.height/2, x+tank.width+10, y+tank.height/2); break; case rd: g.drawline(x+tank.width/2, y+tank.height/2, x+tank.width+7, y+tank.height+7); break; case d: g.drawline(x+tank.width/2, y+tank.height/2, x+tank.width/2, y+tank.height+10); break; case ld: g.drawline(x+tank.width/2, y+tank.height/2, x-7, y+height+7); break; } move(); } public void move() { oldx=x;//纪录坦克上一步的位置 oldy=y; switch(dir) { case l: x-=xspeed; break; case lu: x-=xspeed; y-=yspeed; break; case u: y-=yspeed; break; case ru: x+=xspeed; y-=yspeed; break; case r: x+=xspeed; break; case rd: x+=xspeed; y+=yspeed; break; case d: y+=yspeed; break; case ld: x-=xspeed; y+=yspeed; break; case stop: break; } if(this.dir!=direction.stop) this.ptdir=this.dir; /** * 防止坦克越界; */ if(x<0) x=0; if(y<25) y=25; if(x+tank.width>tankwarclient.game_width) x=tankwarclient.game_width-30; if(y+tank.height>tankwarclient.game_height) y=tankwarclient.game_height-30; if(!good) { direction[] dirs=direction.values();//将枚举类型转化成数组; if(step==0) { step=r.nextint(12)+3; int rn=r.nextint(dirs.length);//产生length以内随机的整数; dir=dirs[rn]; } step--; if(r.nextint(40)>20) this.fire();//使敌军坦克发射子弹; } } /** * 处理按键 * @param e键盘事件; */ public void keypressed(keyevent e) { int key=e.getkeycode(); switch(key) { case keyevent.vk_left: bl=true; break; case keyevent.vk_right: br=true; break; case keyevent.vk_up: bu=true; break; case keyevent.vk_down: bd=true; break; } locationdir(); } public void keyreleased(keyevent e) { int key=e.getkeycode(); switch(key) { case keyevent.vk_control: fire(); break; case keyevent.vk_left: bl=false; break; case keyevent.vk_right: br=false; break; case keyevent.vk_up: bu=false; break; case keyevent.vk_down: bd=false; break; case keyevent.vk_a: superfire(); break; case keyevent.vk_f2: reborn(); break; } locationdir(); } /** * 发射子弹 * @return返回子弹类型 */ public missile fire() { if(!live) return null; int mx=this.x+tank.width/2-missile.width/2;//计算子弹发射的位置; int my=this.y+tank.height/2-missile.height/2; missile m=new missile(mx,my,good,ptdir,this.tc);////根据炮筒方向发射子弹 tc.missiles.add(m); return m; } public missile fire(direction dir) { if(!live) return null; int mx=this.x+tank.width/2-missile.width/2; int my=this.y+tank.height/2-missile.height/2; missile m=new missile(mx,my,good,dir,this.tc);//根据坦克的方向发射子弹; tc.missiles.add(m); return m; } public void superfire() { direction[] dirs=direction.values(); for(int i=0;i<8;i++) { fire(dirs[i]); } } public void locationdir() { if(bl&&!bu&&!br&&!bd) dir=direction.l; else if(bl&&bu&&!br&&!bd) dir=direction.lu; else if(!bl&&bu&&!br&&!bd) dir=direction.u; else if(!bl&&bu&&br&&!bd) dir=direction.ru; else if(!bl&&!bu&&br&&!bd) dir=direction.r; else if(!bl&&!bu&&br&&bd) dir=direction.rd; else if(!bl&&!bu&&!br&&bd) dir=direction.d; else if(bl&&!bu&&!br&&bd) dir=direction.ld; else if(!bl&&!bu&&!br&&!bd) dir=direction.stop; } public rectangle getrect()//获取tank的矩形区域 { return new rectangle(this.x,this.y,this.width,this.height); } /** * 坦克撞墙 * @param w墙 * @returntrue撞上,false未撞上; */ public boolean colliedswithwall(wall w) { if(this.live&&this.getrect().intersects(w.getrect())) { this.stay(); return true; } return false; } /** * 处理坦克与坦克相撞,防止其互相穿越; * @param tanks敌军坦克; * @return true撞上,false未撞上; */ public boolean colliedswithtanks(java.util.list<tank> tanks) { for(int i=0;i<tanks.size();i++) { tank t=tanks.get(i); if(this!=t) { if(this.live&&this.islive()&&this.getrect().intersects(t.getrect())) { this.stay();//返回上一步的位置; t.stay();////返回上一步的位置 return true; } } } return false; } private void stay() { x=oldx; y=oldy; } /** * 为tank的内部类;血条,显示在我方坦克的头顶上; * @author hekangmin * */ private class bloodbar { public void draw(graphics g) { color c=g.getcolor(); g.setcolor(color.red); g.drawrect(x,y-10,width,10); int w=width*life/100; g.fillrect(x,y-10,w,10); } } /** * 吃到血块加血; * @param b血块 * @returntrue吃到,false未吃到; */ public boolean eat(blood b) { if(this.live&&b.islive()&&this.getrect().intersects(b.getrect())) { this.life=100; b.setlive(false); return true; } return false; } /** * 我军坦克死后复活; */ public void reborn() { if(this.isgood()&&!this.islive()) { this.setlive(true); this.setlife(100); } } }
tankwarclient.java
package com.hkm.tankwar; import java.awt.*; import java.awt.event.*; import java.util.list; import java.util.arraylist; /** * 这个是游戏的运行窗口; * @author hekangmin * */ public class tankwarclient extends frame{ /** * 游戏窗口的宽度; */ public static final int game_width=800; /** * 游戏窗口的高度; */ public static final int game_height=600; tank mytank=new tank(700,400,true,tank.direction.stop,this); list<tank> tanks=new arraylist<tank>(); list<explode> explodes=new arraylist<explode>(); list<missile> missiles=new arraylist<missile>(); wall w1=new wall(300,200,20,200,this); wall w2=new wall(600,300,30,150,this); blood b=new blood(); /** * 画一张虚拟图片; */ image offscreenimage=null; public tankwarclient(string name)//设置文字 { super(name); } /** * 运行窗口; */ public void launchframe() { for(int i=0;i<10;i++)//添加十辆敌军坦克 { tanks.add(new tank(50+40*(i+1),50,false,tank.direction.d,this)); } this.setbounds(200,100,game_width,game_height); this.setbackground(color.green); this.addwindowlistener(new windowadapter()//匿名类 { public void windowclosing(windowevent e) { system.exit(0); } }); this.addkeylistener(new keymonitor());//加入键盘监听器; this.setresizable(false);//不可改变窗口的大小; this.setvisible(true); new thread(new paintthread()).start();//新建一个线程; } public void paint(graphics g) { g.drawstring("missile count: "+missiles.size(), 10, 50);//显示字符串; g.drawstring("explodes count: "+explodes.size(),10,70); g.drawstring("tanks count: "+tanks.size(),10,90); g.drawstring("mytank life: "+mytank.getlife(),10,110); /** * 画出墙; */ w1.draw(g); w2.draw(g); /** * 检测子弹与各类的事情; */ for(int i=0;i<missiles.size();i++) { missile m=missiles.get(i); m.hitswall(w1); m.hitswall(w2); m.hittanks(tanks); m.hittank(mytank); m.draw(g); //if(!m.islive()) //missiles.remove(m); //else m.draw(g); } /** * 画出爆炸; */ for(int i=0;i<explodes.size();i++) { explode e=explodes.get(i); e.draw(g); } for(int i=0;i<tanks.size();i++) { tank t=tanks.get(i); t.colliedswithwall(w1); t.colliedswithwall(w2); t.colliedswithtanks(tanks); t.draw(g); } b.draw(g); mytank.eat(b); mytank.draw(g); } /** * 利用双缓冲技术消除坦克闪烁的现象; */ public void update(graphics g) //g为画在屏幕上的画笔; { if(offscreenimage==null) offscreenimage=this.createimage(game_width, game_height); graphics goffscreen=offscreenimage.getgraphics();//goffscreen是offscreenimage的画笔; color c=goffscreen.getcolor(); goffscreen.setcolor(color.green); goffscreen.fillrect(0, 0, game_width, game_height); goffscreen.setcolor(c); paint(goffscreen);//画在虚拟图片上; g.drawimage(offscreenimage,0,0,null);//用g画笔将虚拟图片上的东西画在屏幕上 } private class paintthread implements runnable{ public void run() { while(true) { repaint();//这里的repaint方法是frame类的 try{ thread.sleep(100); }catch(interruptedexception e){ e.printstacktrace(); } } } } private class keymonitor extends keyadapter { public void keyreleased(keyevent e) { mytank.keyreleased(e); } public void keypressed(keyevent e) { mytank.keypressed(e); } } public static void main(string[] args) { new tankwarclient("my tank world").launchframe(); } }
wall.java
package com.hkm.tankwar; import java.awt.*; /** * 生成阻碍物墙这个类; * @author hekangmin * */ public class wall { /** * x,y为墙的位置,w,h为宽度高度; */ int x,y,w,h; /** * 持有引用 */ tankwarclient tc; public wall(int x, int y, int w, int h, tankwarclient tc) { this.x = x; this.y = y; this.w = w; this.h = h; this.tc = tc; } public void draw(graphics g) { color c=g.getcolor(); g.setcolor(color.gray); g.fillrect(x,y,w,h); g.setcolor(c); } /** * 得到墙的矩形区域; * @return */ public rectangle getrect() { return new rectangle(x,y,w,h); } }
以上所述就是本文的全部内容了,希望大家能够喜欢。
下一篇: React的setState理解