用Java写一个入门游戏——坦克大战!
源代码!!!复制可以直接用!!!
文章最后还有飞机大战代码!!!
本代码写的较为入门,有需要的铁铁们可以去看看!!!
在往期我们讲解了窗口、循环、数组和继承的一些知识之后我们将这些知识整理起来便可以自己来写一个java的小游戏;
(ps:新来的铁铁们可以去看看我往期的内容)
好啦那么我们就直接进入正题了哈!
步骤1
首先就需要用到我们昨天学到的知识——java的继承,我们先去写一个父类用来把坦克大战想去表述的功能全部都写进去~
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.URL;
public class TankClient extends Frame{ //界面大小
public static final int GAME_WIDTH=800;
public static final int GAME_HEIGHT=600;
//Image belmg=GameUtil.getImage("D:\\1"+".jpg");
Tank myTank =new Tank(800,290,true,Tank.Direction.STOP,this);//坦克出生位置
jia j1=new jia(750,260,60,10,this),j2=new jia(750,320,60,10,this),j3=new jia(740,260,10,70,this); //定义家
Wall w1=new Wall(300,200,20,200,this),w2=new Wall(500,100,150,20,this),/*w3=new Wall(750,270,50,10,this),w4=new Wall(750,310,50,10,this),*/
w5=new Wall(500,400,10,90,this),w6=new Wall(85,100,60,9,this);//定义墙
cao c1=new cao(150,100,50,50,this), c2=new cao(600,500,50,50,this); //定义草丛
List<Explode>explodes=new ArrayList<Explode>();
List<Missile>missiles=new ArrayList<Missile>();
List<Tank> tanks=new ArrayList<Tank>();
Image offScreenImage=null;
Blood b=new Blood(); //新建血类
Blood1 b1=new Blood1();
Blood2 b2=new Blood2();
public void paint(Graphics g){ //显示参数
g.drawString("有效子弹数量:"+missiles.size(),10,50);
g.drawString("爆炸数量:"+explodes.size(),10,65);
g.drawString("敌军数量:"+tanks.size(),10,85);
g.drawString("剩余血量:"+myTank.getLife(),10,100);
g.drawString("家",750,285);
g.drawString("草丛",205,155);
g.drawString("草丛",605,490);
//g.drawString(bglmg,0,0,null);
if(tanks.size() ==6){
for(int i=0;i<18;i++){ //第一次敌人数量
tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));
}
}
if(tanks.size() ==4){
for(int i=0;i<13;i++){ //第二次敌人数量
tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));
}
}
if(tanks.size() ==2){
for(int i=0;i<11;i++){ //第三次敌人数量
tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));
}
}
if(tanks.size() ==1){
for(int i=0;i<18;i++){ //第四次敌人数量
tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));
}
}
if(tanks.size() ==0){
for(int i=0;i<30;i++){ //第五次敌人数量
tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));
}
}
for(int i=0;i<missiles.size();i++){ //防止子弹穿墙
Missile m=missiles.get(i);
m.hitTanks(tanks);
m.hitTank(myTank);
m.hitWall(w1);
m.hitWall(w2);
m.hitjia(j1);
m.hitjia(j2);
m.hitjia(j3);
m.hitWall(w5);
m.hitWall(w6);
m.hitcao(c1);
m.hitcao(c2);
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.collidesWithWall(w1);
t.collidesWithWall(w2);
t.collidesWithjia(j1);
t.collidesWithjia(j2);
t.collidesWithjia(j3);
t.collidesWithWall(w5);
t.collidesWithWall(w6);
t.collidesWithTanks(tanks);
t.draw(g);
}
//我军坦克撞墙
myTank.draw(g);
myTank.eat(b);
myTank.eat(b1);
myTank.eat(b2);
myTank.collidesWithWall(w1);
myTank.collidesWithWall(w2);
myTank.collidesWithWall(w5);
myTank.collidesWithWall(w6);
w1.draw(g);
w2.draw(g);
j1.draw(g);
j2.draw(g);
j3.draw(g);
w5.draw(g);
w6.draw(g);
c1.draw(g);
c2.draw(g);
b.draw(g);
b1.draw(g);
}
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.WHITE);
gOffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage,0,0,null);
}
public void lauchFrame(){
for(int i=0;i<10;i++){ //初始敌人数量
tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));//敌人大小
}
//this.setLocation(400,300);
this.setSize(GAME_WIDTH,GAME_HEIGHT);
this.setTitle("坦克战争"); //游戏命名
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
this.setResizable(false);
this.setBackground(Color.WHITE);
this.addKeyListener(new KeyMonitor());
setVisible(true);
new Thread(new PaintThread()).start();
}
public static void main(String[] args) {
try{URL url = new File("D:\\java\\DAA.wav").toURI().toURL();//找到背景音乐所在文件
AudioClip audioClip = new Applet().newAudioClip(url);
audioClip.loop();
}//循环播放
catch(Exception e){ }
TankClient tc=new TankClient();
tc.lauchFrame();
}
private class PaintThread implements Runnable{
public void run(){
while(true){
repaint();
try{
Thread.sleep(100);//频率
}catch (InterruptedException e){
e.printStackTrace();}
}
}
}
//按键处理
public class KeyMonitor extends KeyAdapter{
public void keyReleased(KeyEvent e){
myTank.keyReleased(e);
}
public void keyPressed(KeyEvent e){
myTank.keyPressed(e);
}
}
}
步骤2:
下面我们来写一下坦克这个类:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Tank{
public static final int XSPEED=10; // 坦克速度
public static final int YSPEED=10;
public static final int WIDTH=35; //子弹速度
public static final int HEIGHT=35;
private boolean live=true;
private int life=100; //坦克生命值
private BloodBar bb =new BloodBar();
TankClient tc;
private boolean good;
private int x,y; //位置
private int oldX,oldY; //原来位置
private static Random r=new Random();
private boolean bL=false,bU=false,bR=false,bD=false;
enum Direction{L,LU,U,RU,R,RD,D,LD,STOP};
private Direction dir=Direction.STOP;
private Direction ptDir=Direction.D;
private int step =r.nextInt(20)+8;//敌人坦克炮弹频率
public Tank(int x,int y,boolean good){
this.x=x;
this.y=y;
this.oldX=x;
this.oldY=y;
this.good=good;
}
public Tank(int x,int y,boolean good,Direction dir,TankClient tc){
this (x,y,good);
this.dir=dir;
this.tc=tc;
}
public void draw(Graphics g){
if(!live){
if(!good)tc.tanks.remove(this);
else return;
}
Color c=g.getColor();
if(good)
g.setColor(Color.BLUE); //我方坦克颜色
else g.setColor(Color.CYAN);//敌军坦克颜色
g.fillOval(x,y,WIDTH,HEIGHT);
g.setColor(c);
if(good) bb.draw(g);//画出血条
switch (ptDir){ //写出炮管
case L:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y+Tank.HEIGHT/2);
break;
case LU:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y);
break;
case U:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH/2,y);
break;
case RU:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH,y);
break;
case R:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH,y+Tank.HEIGHT/2);
break;
case RD:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH,y+Tank.HEIGHT);
break;
case D:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH/2,y+Tank.HEIGHT);
break;
case LD:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y+Tank.HEIGHT);
break;
}
move();
}
void move(){ //移动
this.oldX=x;
this.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<30)y=30;
if(x+Tank.WIDTH>TankClient.GAME_WIDTH)x=TankClient.GAME_WIDTH-Tank.WIDTH;
if(y+Tank.HEIGHT>TankClient.GAME_HEIGHT)y=TankClient.GAME_HEIGHT-Tank.HEIGHT;
if(!good){
Direction[] dirs=Direction.values();
if(step ==0){
step=r.nextInt(15)+5;
int rn=r.nextInt(dirs.length);
dir=dirs[rn];
}
step--;
if(r.nextInt(40)>38) this.fire();//敌军炮弹速度
}
}
private void stay() {
x=oldX;
y=oldY;
}
public void keyPressed(KeyEvent e){
int key=e.getKeyCode(); //按键处理
switch(key){
case KeyEvent.VK_K:
if(!this.live){ //复活
this.live =true;
this.life=100;
}
break;
case KeyEvent.VK_CONTROL:
fire();
break;
case KeyEvent.VK_LEFT:
bL=true;
break;
case KeyEvent.VK_UP:
bU=true;
break;
case KeyEvent.VK_RIGHT:
bR=true;
break;
case KeyEvent.VK_DOWN:
bD=true;
break;
case KeyEvent.VK_ENTER:
superFire();
break;
}
locateDirection();
}
void locateDirection(){
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 void keyReleased(KeyEvent e){
int key=e.getKeyCode();
switch(key){
case KeyEvent.VK_LEFT:
bL=false;
break;
case KeyEvent.VK_UP:
bU=false;
break;
case KeyEvent.VK_RIGHT:
bR=false;
break;
case KeyEvent.VK_DOWN:
bD=false;
break;
}
locateDirection();
}
public Missile fire(){
if(!live) return null;
int x=this.x+Tank.WIDTH/2 - Missile.WIDTH/2;
int y=this.y+Tank.HEIGHT/2 - Missile.HEIGHT/2;
Missile m= new Missile(x,y,good,ptDir,this.tc);
tc.missiles.add(m);
return m;
}
public Missile fire(Direction dir){
if(!live) return null;
int x=this.x+Tank.WIDTH/2 - Missile.WIDTH/2;
int y=this.y+Tank.HEIGHT/2 - Missile.HEIGHT/2;
Missile m= new Missile(x,y,good,dir,this.tc);
tc.missiles.add(m);
return m;
}
public Rectangle getRect(){
return new Rectangle(x,y,WIDTH,HEIGHT);
}
public boolean isLive(){
return live;
}
public void setLive(boolean live){
this.live=live;
}
public boolean isGood(){
return good;
}
// 坦克撞墙
public boolean collidesWithWall(Wall w){
if(this.live && this.getRect().intersects(w.getRect())){
this.stay();
return true;
}
return false;
}
//撞草丛
public boolean collidesWithcao(cao w){
if(this.live && this.getRect().intersects(w.getRect())){
this.stay();
return true;
}
return false;
}
//撞房子
public boolean collidesWithjia(jia w){
if(this.live && this.getRect().intersects(w.getRect())){
this.stay();
return true;
}
return false;
}
public boolean collidesWithTanks(java.util.List<Tank>tanks){ //防止坦克相撞
for(int i=0;i<tanks.size();i++){
Tank t=tanks.get(i);
if(this !=t){
if(this.live && t.isLive() && this.getRect().intersects(t.getRect())){
this.stay();
t.stay();
return true;
}
}
}
return false;
}
private void superFire(){ //超级炮弹
Direction[] dirs=Direction.values();
for(int i=0;i<8;i++){
tc.missiles.add(fire(dirs[i]));
}
}
public void setLife(int life){
this.life=life;
}
public int getLife(){
return life;
}
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);
g.setColor(c);
}
}
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 boolean eat(Blood1 b1){
if(this.live && b1.isLive()&& this.getRect().intersects(b1.getRect())){
this.life=20;
b1.setLive(false);
return true;
}
return false;
}
public boolean eat(Blood2 b2){
if(this.live && this.getRect().intersects(b2.getRect())){
this.life=100;
return true;
}
return false;
}
}
步骤3:
下面来写一下子弹这个类!
import java.awt.*;
import java.util.List;
public class Missile {
public static final int XSPEED=10;
public static final int YSPEED=10;
public static final int WIDTH=10;
public static final int HEIGHT=10;
int x,y;
Tank.Direction dir;
private boolean good;
private boolean live= true;
public TankClient 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,TankClient tc){
this(x,y,dir);
this.good=good;
this.tc=tc;
}
public void draw(Graphics g){
if(!live){
tc.missiles.remove(this);
return;
}
Color c=g.getColor();
g.setColor(Color.BLACK);
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>TankClient.GAME_WIDTH||y>TankClient.GAME_HEIGHT){
live=false;
tc.missiles.remove(this);
}
}
public boolean isLive(){
return live;
}
public Rectangle getRect(){ //碰见
return new Rectangle(x,y,WIDTH,HEIGHT);
}
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;
}
public boolean hitTanks(List<Tank> tanks){
for (int i=0;i<tanks.size();i++){
if(hitTank(tanks.get(i))){
return true;
}
}
return false;
}
public boolean hitWall(Wall w){ //模拟子弹撞墙
if(this.live && this.getRect().intersects(w.getRect())){
this.live=false;
return true;
}
return false;
}
public boolean hitcao(cao w){ //模拟草丛隐身
if(this.live && this.getRect().intersects(w.getRect())){
this.live=false;
return true;
}
return false;
}
public boolean hitjia(jia w){ //模拟家
if(this.live && this.getRect().intersects(w.getRect())){
this.live=false;
return true;
}
return false;
}
}
步骤4:
下面来写一下子弹命中坦克产生爆炸这个类:
import java.awt.*;
public class Explode {
int x,y;
private boolean live =true;
private TankClient tc;
int[ ] diameter ={4,7,12,18,26,32,49,30,14,6}; //爆炸范围
int step=0;
public Explode(int x,int y,TankClient tc){
this.x=x;
this.y=y;
this.tc=tc;
}
public void draw(Graphics g){
if(!live){
tc.explodes.remove(this);
return;}
if(step==diameter.length){
live=false;
step=0;
return ;
}
Color c=g.getColor();
g.setColor(Color.ORANGE); //爆炸颜色
g.fillOval(x,y,diameter[step],diameter[step]);
g.setColor(c);
step ++;
}
}
步骤5:
下面来写一下游戏中障碍物这个类:
import java.awt.*;
public class Wall {
private TankClient tc;
int x,y,w,h;
public Wall (int x,int y, int w, int h,TankClient tc){
this.x=x;
this.y=y;
this.h=h;
this.w=w;
this.tc=tc;
}
public void draw(Graphics g){
Color c=g.getColor();//设置颜色
g.setColor(Color.MAGENTA);
g.fillRect(x,y,w,h);//写出墙类
g.setColor(c);
}
public Rectangle getRect(){
return new Rectangle (x,y,w,h);
}
}
import java.awt.*;
public class cao {
private TankClient tc;
int x,y,w,h;
public cao (int x,int y, int w, int h,TankClient tc){
this.x=x;
this.y=y;
this.h=h;
this.w=w;
this.tc=tc;
}
public void draw(Graphics g){
Color c=g.getColor();//设置颜色
g.setColor(Color.GREEN);
g.fillRect(x,y,w,h);//写出草丛类
g.setColor(c);
}
public Rectangle getRect(){
return new Rectangle (x,y,w,h);
}
}
步骤6:
下面来写一下游戏中坦克回血的设定:
import java.awt.*;
public class Blood{
int x,y,w,h;
TankClient tc;
int step = 0;
private boolean live = true;
private int[][]pos={ //血块运动轨迹
{80,70},
{80,100},
{90,120},
{100,100},
{100,130},
{180,90},
{110,92},
{155,55},
{80,60}
};
public Blood(){
x=pos[0][0];
y=pos[0][1];
w=h=15;
}
public void draw(Graphics g){
if(!live)
return ;
Color c=g.getColor();
g.setColor(Color.PINK);
g.fillRect(x,y,w,h);
g.setColor(c);
move();
}
private void move(){
step++;
if(step ==pos.length){
step=0;
}
x=pos[step][0];
y=pos[step][1];
}
public Rectangle getRect(){
return new Rectangle(x,y,w,h);
}
public boolean isLive(){
return live;
}
public void setLive(boolean live){
this.live=live;
}
}
步骤7:
下面来写一下游戏中陷阱类!
import java.awt.*;
public class Blood1{ //地雷类
int x,y,w,h;
TankClient tc;
int step = 0;
private boolean live = true;
private int[][]pos={
{200,300},{200,310},{200,330} //地雷轨迹
};
public Blood1(){
x=pos[0][0];
y=pos[0][1];
w=20;
h=10;
}
public void draw(Graphics g){
if(!live)
return ;
Color c=g.getColor();
g.setColor(Color.WHITE); //设置颜色
g.fillOval(x,y,w,h);
g.setColor(c);
move();
}
private void move(){
step++;
if(step ==pos.length){
step=0;
}
x=pos[step][0];
y=pos[step][1];
}
public Rectangle getRect(){
return new Rectangle(x,y,w,h);
}
public boolean isLive(){
return live;
}
public void setLive(boolean live){
this.live=live;
}
}
步骤8:
下面我们来给坦克大战设置一个“泉水”吧!
import java.awt.*;
public class Blood2{ //家回血
int x,y,w,h;
TankClient tc;
int step = 0;
private boolean live = true;
private int[][]pos={
{760,285} //位置设置
};
public Blood2(){
x=pos[0][0];
y=pos[0][1];
w=20;
h=20;
}
public void draw(Graphics g){
Color c=g.getColor();
g.setColor(Color.WHITE); //颜色设置
g.fillRect(x,y,w,h);
g.setColor(c);
move();
}
private void move(){
step++;
if(step ==pos.length){
step=0;
}
x=pos[step][0];
y=pos[step][1];
}
public Rectangle getRect(){
return new Rectangle(x,y,w,h);
}
}
运行效果:
D:\Java>javac TankClient.java
D:\Java>java TankClient
D:\Java>
注意铁铁们!!!
大家可以打开声音,会有背景音乐的!!!
下面我把创建图形界面、背景音乐和另外一个小游戏(飞机大战)的教程放在下面链接中,铁铁们有需要可以去看看哈!
链接:https://pan.baidu.com/s/14BO6bN0iWyl1HIlsguCMyw
提取码:0136
———————————————————手动分割——————————————————————
好啦!
本期的内容到这里就结束了!
要是有疑问铁铁们可以直接评论区或者私信问我哈!
明天我会有点事;
但是日更不断!
明天我会给大家分享一写学习java的文件~~
(ps:主要不麻烦,哈哈哈)
那么我们明天见铁铁们!