源码:
Bullet类:
public class Bullet implements Runnable{ //多线程
private int speed=10;
private int dir;
boolean life=true;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getDir() {
return dir;
}
public void setDir(int dir) {
this.dir = dir;
}
public void run()//重写runnable 接口重点额run方法
{
while (true)//子弹一直飞
{
//JAVA特有异常抛出
switch (getDir())//子弹坐标改变(移动)
{
case 0:
setY(getY()-getSpeed());
break;
case 1:
setX(getX()-getSpeed());
break;
case 2:
setY(getY()+getSpeed());
break;
case 3:
setX(getX()+getSpeed());
break;
}
if(getX()<0||getY()<0||getX()>1200||getY()>1000)
{
life=false;
break;
}
//判断是否过边界如果过边界了那么子弹的生命就没了
try//程序正常时执行
{
Thread.sleep(50);//让程序暂停50ms
}
catch (Exception e)//非正常时执行
{
}
}
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
private int x;
private int y;
Bullet(int x,int y,int dir)//子弹需要构造函数直接给方向赋值
{
this.x=x;
this.y=y;
this.dir=dir;
}
}
2.EnemyTank类:
import java.util.Vector;
public class EnemyTank extends Tank implements Runnable {
EnemyTank(int x,int y)
{
super(x,y);
}
Vector<Bullet> bulletVector = new Vector<Bullet>();
Bullet bullet =null;
public void run()
{
int flag=1;
int flag2=1;
while (true)
{
flag++;
if(flag==15)
{
flag=0;
int dir1=(int)(Math.random()*4);
setDir(dir1);
}
flag2=(int)(Math.random()*20);
if(flag2%3==0)
{
fire();
}
switch (getDir())
{
case 0://上
if(!(getY()==550&&getX()<=330||getY()==550&&getX()>=430&&getX()<=730||getY()==550&&getX()>=830)&&getY()>=0)
setY(getY() - getSpeed());
System.out.println(getSpeed());
break;
case 1://左
if (!(getX()==330&&getY()>=420&&getY()<=550||getX()==730&&getY()>=420&&getY()<=550)&&getX()>=0)
setX(getX() - getSpeed());
break;
case 2:
if(!(getY()==420&&getX()<=330||getY()==420&&getX()>=430&&getX()<=730||getY()==420&&getX()>=830)&&getY()<=930)
setY(getY() + getSpeed());
break;
case 3:
if(!(getX()==400&&getY()>=420&&getY()<=550||getX()==800&&getY()>=420&&getY()<=550)&&getX()<=1170)
setX(getX() + getSpeed());
break;
}
try {
Thread.sleep(50);
}
catch (Exception e)
{
}
}
}
public void fire()//装弹
{
if(bulletVector.size()<7)
{
switch (this.getDir())
{
case 0:
bullet = new Bullet(this.getX()+8,this.getY()-7,0);
bulletVector.add(bullet);
break;
case 1:
bullet = new Bullet(this.getX()-7,this.getY()+8,1);
bulletVector.add(bullet);
break;
case 2:
bullet = new Bullet(this.getX()+8,this.getY()+30,2);
bulletVector.add(bullet);
break;
case 3:
bullet = new Bullet(this.getX()+30,this.getY()+8,3);
bulletVector.add(bullet);
break;
}
Thread thread = new Thread(bullet);
thread.start();
}
}
}
3.Main类:
import javax.swing.*;
public class Main extends JFrame {
MyPanel myPanel= new MyPanel();
Main()
{
this.add(myPanel);
this.addKeyListener(myPanel);
this.setSize(1200,1000);
this.setLocation(200,10);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Thread thread = new Thread(myPanel);
thread.start();
}
public static void main(String agrs[])
{
Main main =new Main();
}
}
4.MyPanel类
import javafx.scene.input.KeyCode;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.*;
import java.util.Vector;
public class MyPanel extends Panel implements KeyListener,Runnable {
MyTank myTank = null;
Vector<EnemyTank> enemyTanks = new Vector<EnemyTank>();//集合类
int enemynum = 12;//坦克数量
MyPanel() {
myTank = new MyTank(120, 220);//初始化我的坦克的初始坐标
myTank.setSpeed(5);
for (int i = 0; i < enemynum / 2; i++) {
EnemyTank enemyTank = new EnemyTank(i * (230 + 5), 0);//给上面的enemyTank初始化坐标
enemyTank.speed=4;
enemyTank.setDir(2);
Thread thread = new Thread(enemyTank);
thread.start();
enemyTanks.add(enemyTank);//向集合里面添加enemyTank
}
for (int i = 6; i < enemynum; i++) {
EnemyTank enemyTank = new EnemyTank((12 - i - 1) * (230 + 5), 930);//给下面的enemyTank初始化坐标
enemyTank.speed=4;
Thread thread = new Thread(enemyTank);
thread.start();
enemyTanks.add(enemyTank);
}
}
public void run()
{
while (true)
{
for(int i=0;i<enemyTanks.size();i++)
{
EnemyTank enemyTank = enemyTanks.get(i);
for(int j=0;j<enemyTank.bulletVector.size();j++)
{
judge1(myTank,enemyTank.bulletVector.get(j));
}
}
for(int i=0;i<enemyTanks.size();i++)
{
EnemyTank enemyTank = enemyTanks.get(i);
for(int j=0;j<myTank.bulletVector.size();j++)
{
Bullet bullet = myTank.bulletVector.get(j);
judge(enemyTank,bullet);
}
}
try
{
Thread.sleep(50);
}
catch (Exception e)
{
}
repaint();
}
}
public void paint(Graphics g) //重写paint方法
{
g.setColor(Color.black);//画笔着色
g.fillRect(0, 0, 1200, 1000);//面板
if (myTank.life) {
drawTank(myTank.getX(), myTank.getY(), myTank.getDir(), g, 0);//画我方坦克
}
for(int i=0;i<myTank.bulletVector.size();i++)//画我的坦克的子弹
{
Bullet bullet = myTank.bulletVector.get(i);
if(bullet.life&&myTank.life)
{
g.setColor(Color.white);
g.fill3DRect(bullet.getX(),bullet.getY(),3,3,false);
}
else
{
myTank.bulletVector.remove(bullet);
}
}
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if(enemyTank.life)
drawTank(enemyTank.getX(), enemyTank.getY(), enemyTank.getDir(), g, 1);//画敌方坦克
}
for(int i=0;i<enemyTanks.size();i++)//画敌方坦克子弹
{
EnemyTank enemyTank =enemyTanks.get(i);
for(int j=0;j<enemyTank.bulletVector.size();j++)
{
Bullet bullet = enemyTank.bulletVector.get(j);
if(bullet.life&&enemyTank.life)
{
g.setColor(Color.white);
g.fill3DRect(bullet.getX(),bullet.getY(),3,3,false);
}
else
{
enemyTank.bulletVector.remove(bullet);
}
}
}
}
public void drawTank(int x, int y, int dir, Graphics g, int type)//画坦克
{
//System.out.println(dir);
switch (type) {
case 0://我方
g.setColor(Color.red);
break;
case 1://敌方
g.setColor(Color.green);
break;
}
switch (dir) {
case 0://上
g.fill3DRect(x, y, 5, 30, false);//左腿
g.fill3DRect(x + 15, y, 5, 30, false);//右腿
g.fill3DRect(x + 5, y + 5, 10, 20, false);//中间
g.fillOval(x + 5, y + 10, 10, 10);//圆形
g.drawLine(x + 10, y + 15, x + 10, y - 3);//炮管
break;
case 1://左
g.fill3DRect(x, y, 30, 5, false);
g.fill3DRect(x, y + 15, 30, 5, false);
g.fill3DRect(x + 5, y + 5, 20, 10, false);
g.fillOval(x + 10, y + 5, 10, 10);
g.drawLine(x + 15, y + 10, x - 3, y + 10);
break;
case 2://下
g.fill3DRect(x, y, 5, 30, false);
g.fill3DRect(x + 15, y, 5, 30, false);
g.fill3DRect(x + 5, y + 5, 10, 20, false);
g.fillOval(x + 5, y + 10, 10, 10);
g.drawLine(x + 10, y + 15, x + 10, y + 33);
break;
case 3://右
g.fill3DRect(x, y, 30, 5, false);
g.fill3DRect(x, y + 15, 30, 5, false);
g.fill3DRect(x + 5, y + 5, 20, 10, false);
g.fillOval(x + 10, y + 5, 10, 10);
g.drawLine(x + 15, y + 10, x + 33, y + 10);
break;
}
}
public void keyReleased(KeyEvent e){};
public void keyTyped(KeyEvent e){};
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_W)
{
myTank.up();
myTank.setDir(0);
}
else if(e.getKeyCode()==KeyEvent.VK_S)
{
myTank.down();
myTank.setDir(2);
}
else if(e.getKeyCode()==KeyEvent.VK_A)
{
myTank.left();
myTank.setDir(1);
}
else if(e.getKeyCode()==KeyEvent.VK_D)
{
myTank.right();
myTank.setDir(3);
}
else if(e.getKeyCode()==KeyEvent.VK_SPACE)
{
myTank.fire();
}
this.repaint();
}
public void judge(EnemyTank enemyTank,Bullet bullet)//判断子弹与EnemyTank是否碰撞
{
switch (enemyTank.getDir())
{
case 0:
case 2:
if(bullet.getX()>enemyTank.getX()&&bullet.getX()<enemyTank.getX()+20&&bullet.getY()>enemyTank.getY()&&bullet.getY()<enemyTank.getY()+30)
{
bullet.life=false;
enemyTank.life=false;
}
break;
case 1:
case 3:
if(bullet.getX()>enemyTank.getX()&&bullet.getX()<enemyTank.getX()+30&&bullet.getY()>enemyTank.getY()&&bullet.getY()<enemyTank.getY()+20)
{
bullet.life=false;
enemyTank.life=false;
}
}
}
public void judge1(MyTank enemyTank,Bullet bullet)//判断子弹与MyTank是否碰撞
{
switch (enemyTank.getDir())
{
case 0:
case 2:
if(bullet.getX()>enemyTank.getX()&&bullet.getX()<enemyTank.getX()+20&&bullet.getY()>enemyTank.getY()&&bullet.getY()<enemyTank.getY()+30)
{
bullet.life=false;
enemyTank.life=false;
JOptionPane.showMessageDialog(null,"游戏结束!");
System.exit(1);
}
break;
case 1:
case 3:
if(bullet.getX()>enemyTank.getX()&&bullet.getX()<enemyTank.getX()+30&&bullet.getY()>enemyTank.getY()&&bullet.getY()<enemyTank.getY()+20)
{
bullet.life=false;
enemyTank.life=false;
JOptionPane.showMessageDialog(null,"游戏结束!");
System.exit(1);
}
}
}
}
5.MyTank类:
import java.util.Vector;
public class MyTank extends Tank {
Vector<Bullet> bulletVector = new Vector<Bullet>();
Bullet bullet = null;
MyTank(int x,int y)
{
super(x,y);
}
public void up()
{
setY(getY()-getSpeed());
}
public void down()
{
setY(getY()+getSpeed());
}
public void left()
{
setX(getX()-getSpeed());
}
public void right()
{
setX(getX()+getSpeed());
}
public void fire()//装弹
{
if(bulletVector.size()<7)
{
switch (this.getDir())
{
case 0:
bullet = new Bullet(this.getX()+8,this.getY()-7,0);
bulletVector.add(bullet);
break;
case 1:
bullet = new Bullet(this.getX()-7,this.getY()+8,1);
bulletVector.add(bullet);
break;
case 2:
bullet = new Bullet(this.getX()+8,this.getY()+30,2);
bulletVector.add(bullet);
break;
case 3:
bullet = new Bullet(this.getX()+30,this.getY()+8,3);
bulletVector.add(bullet);
break;
}
Thread thread = new Thread(bullet);
thread.start();
}
}
}
6.Tank类:
public class Tank {
int x;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getDir() {
return dir;
}
public void setDir(int dir) {
this.dir = dir;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
int y;
int dir;
int speed;
boolean life=true;
int type;
Tank(int x,int y)
{
this.x=x;
this.y=y;
}
}
个人总结:主要需要用到多线程,初次学JAVA比较难以理解,坦克大战需要用到多线程的地方有MyPanel类,Bullet类,EnemyTank类,一旦给类用了多线程,那么每次用类初始化一个对象那么这个对象就占用一个线程,可以在一个线程中使用这个类的方法,Buttle中的子弹移动是需要多个线程一起作用的(因为子弹的移动是互相独立的),EnemyTank的移动与子弹同理,MyPanel类需要多线程是因为MyTank的移动,发射子弹和EnemyTank的移动和子弹的发射,所需的Mypanel是互相独立的,所以需要线程(以上为个人理解,希望高手指正)。