基本思想是利用多线程,画板是多线程每100ms更新一次
子弹是一个多线程50ms更新一次
坦克是一个多线程50ms更新一次
自己的坦克的方向变换是根据键盘监听响应的,速度可以设置。
敌人的坦克的方向变换是每个一定时间随机变换的,在其run函数中实现
每个坦克有一个子弹,是一一对应关系,
还有一些基本的判断,敌人坦克碰到墙壁必须超反方向运动,
我的子弹碰到敌人坦克,敌人坦克就消失,加分
敌人的坦克打到我,我就消失,GameOver
另外游戏开始时载入了音乐,套用相应的声音类就行了
package com.test1;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.sound.sampled.*;
public class Test extends JFrame implements ActionListener{
MyPanel mp=null;
MyStartPanel msp=null;
JMenuBar jmb=null;
JMenu jm1=null;
JMenuItem jmi1=null; //1.start new game
JMenuItem jmi2=null; //2.exit
JMenuItem jmi3=null; //3.save and exit
JMenuItem jmi4=null; //4.continue previous game
public static void main(String[] args)
{
Test test=new Test();
}
public Test()
{
jmb=new JMenuBar();
jm1=new JMenu("Game(G)");
jm1.setMnemonic('G');
jmi1=new JMenuItem("start new game");
jmi2=new JMenuItem("exit");
jmi3=new JMenuItem("save and exit");
jmi4=new JMenuItem("continue previous game");
jmi1.addActionListener(this);
jmi2.addActionListener(this);
jmi3.addActionListener(this);
jmi4.addActionListener(this);
jm1.add(jmi1);
jm1.add(jmi2);
jm1.add(jmi3);
jm1.add(jmi4);
jmb.add(jm1);
msp=new MyStartPanel();
Thread t=new Thread(msp);
t.start();
this.setJMenuBar(jmb);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(msp);
this.setSize(600,500);
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
if(e.getSource()==jmi1)
{
System.out.printf("hello");
mp=new MyPanel(); //build game panel
Thread t=new Thread(mp);
t.start();
this.remove(msp);
this.add(mp);
this.addKeyListener(mp);
this.setVisible(true);
}else if(e.getSource()==jmi2)
{
}else if(e.getSource()==jmi3)
{
}else if(e.getSource()==jmi4)
{
}
}
}
class MyStartPanel extends JPanel implements Runnable
{
int times=0; //set time
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(0,0,600,500);
if(times%2==0) //every other one second flash once
{
g.setColor(Color.yellow);
Font myFont=new Font("华文新魏",Font.BOLD,60);
g.setFont(myFont);
g.drawString("Tank Game",150,150);
}
}
@Override
public void run() {
// TODO 自动生成的方法存根
while(true)
{
//sleep
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
times++;
this.repaint();
}
}
}
class MyPanel extends JPanel implements KeyListener,Runnable
{
Tank tank=null;
Bullet bullet=null;
Vector<Bullet> bullets=new Vector<Bullet>();
//define a Enemy tank group
Vector<EnemyTank> enemyTankg=new Vector<EnemyTank>();
int enSize=10;
int scores=0;
public MyPanel()
{
tank=new Tank(100,100);
tank.setSpeed(10);
for(int i=0;i<enSize;i++)
{
EnemyTank et=new EnemyTank((i+1)*50,0);
et.setColor(0);
et.setDirect(1);
Thread t=new Thread(et);
t.start();
enemyTankg.add(et);
}
//初始化子弹
for(int i=0;i<enSize;i++)
{
Bullet bullet=new Bullet(0,0,1);
Thread t=new Thread(bullet);
t.start();
bullets.add(bullet);
}
bullet=new Bullet(0,0,1);
Thread t1=new Thread(bullet);
t1.start();
AePlayWave apw=new AePlayWave("./112.wav");
apw.start();
}
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(0,0,600,500); //draw background
g.setColor(Color.yellow); //draw information
g.drawString("score:"+String.valueOf(scores), 500, 450);
if(tank.isLive==false)
{
g.setColor(Color.blue);
Font myFont=new Font("华文新魏",Font.BOLD,60);
g.setFont(myFont);
g.drawString("Game Over",150,150);
}
//draw my tank
if(tank.isLive)
{
this.drawTank(g,tank.getX(), tank.getY(),tank.direct, 0);
}
//draw the enemytank
for(int i=0;i<enSize;i++)
{
if(enemyTankg.get(i).isLive)
{
this.drawTank(g, enemyTankg.get(i).getX(), enemyTankg.get(i).getY(),
enemyTankg.get(i).getDirect(), 1);
}
}
//draw my bullet
if(bullet.isLive)
{
g.fillOval(bullet.getX(), bullet.getY(), 10, 10);
}
//draw the enemy bullet
for(int j=0;j<enSize;j++)
{
if(bullets.get(j).isLive)
{
g.fillOval(bullets.get(j).getX(), bullets.get(j).getY(), 10, 10);
}
}
}
public void showInfo(Graphics g)
{
g.drawString("Score:",20,20);
}
public void drawTank(Graphics g,int x,int y,int direct,int type)
{
//judge which kind of tank,whether enemy or me
switch(type)
{
case 0:
g.setColor(Color.cyan);
break;
case 1:
g.setColor(Color.yellow);
break;
}
//judge which direct the tank is
switch(direct)
{
// up
case 0:
g.fill3DRect(x, y, 30, 40, false);
g.fill3DRect(x+10, y-10, 10, 20, true);
break;
//down
case 1:
g.fill3DRect(x, y, 30, 40, false);
g.fill3DRect(x+10, y+30, 10, 20, true);
break;
//left
case 2:
g.fill3DRect(x, y, 40, 30, false);
g.fill3DRect(x-10, y+10, 20, 10, true);
break;
//right
case 3:
g.fill3DRect(x, y, 40, 30, false);
g.fill3DRect(x+30, y+10, 20, 10, true);
break;
}
}
@Override
public void run() {
// TODO 自动生成的方法存根
int times=0;
while(true)
{
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
this.repaint();
for(int i=0;i<enSize;i++)
{
int x1=enemyTankg.get(i).getX();
int x2=bullet.getX();
int y1=enemyTankg.get(i).getY();
int y2=bullet.getY();
int x3=bullets.get(i).getX();
int y3=bullets.get(i).getY();
int x4=tank.getX();
int y4=tank.getY();
// judge whether the enemy alive
if(x2>x1 && x2<x1+40 && y2>y1 && y2<y1+40)
{
scores++;
bullet.isLive=false;
enemyTankg.get(i).isLive=false;
}
//judge whether myself is alive
if(x3>x4 && x3<x4+40 && y3>y4 && y3<y4+40)
{
tank.isLive=false;
System.out.println("Gamve over");
}
}
//every other 50 times shoot one bullet
if(times%50==0)
{
for(int i=0;i<enSize;i++)
{
int x=enemyTankg.get(i).getX();
int y=enemyTankg.get(i).getY();
bullets.get(i).isLive=true;
bullets.get(i).setDirect(enemyTankg.get(i).getDirect());
switch(tank.getDirect())
{
case 0:
bullets.get(i).setX(x+10);
bullets.get(i).setY(y-20);
break;
case 1:
bullets.get(i).setX(x+10);
bullets.get(i).setY(y+40);
break;
case 2:
bullets.get(i).setX(x-20);
bullets.get(i).setY(y+10);
break;
case 3:
bullets.get(i).setX(x+40);
bullets.get(i).setY(y+10);
break;
}//switch
}//for
}//if
times++;
}//while
}//run
@Override
public void keyTyped(KeyEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void keyPressed(KeyEvent e) {
// TODO 自动生成的方法存根
if(e.getKeyCode()==KeyEvent.VK_W)
{
this.tank.setDirect(0);
this.tank.MoveUp();
}else if(e.getKeyCode()==KeyEvent.VK_S)
{
this.tank.setDirect(1);
this.tank.MoveDown();
}else if(e.getKeyCode()==KeyEvent.VK_A)
{
this.tank.setDirect(2);
this.tank.MoveLeft();
}else if(e.getKeyCode()==KeyEvent.VK_D)
{
this.tank.setDirect(3);
this.tank.MoveRight();
}else if(e.getKeyCode()==KeyEvent.VK_J)
{
bullet.isLive=true;
switch(tank.getDirect())
{
case 0:bullet.setX(tank.getX()+10);bullet.setY(tank.getY()-20);break;
case 1:bullet.setY(tank.getY()+40);bullet.setX(tank.getX()+10);break;
case 2:bullet.setX(tank.getX()-20);bullet.setY(tank.getY()+10);break;
case 3:bullet.setY(tank.getY()+10);bullet.setX(tank.getX()+40);break;
}
bullet.setDirect(tank.getDirect());
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO 自动生成的方法存根
}
}
// play sound class
class AePlayWave extends Thread{
private String filename;
public AePlayWave(String wavfile){
filename=wavfile;
}
public void run(){
File soundFile=new File(filename);
AudioInputStream audioInputStream=null;
try {
audioInputStream=AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return;
}
AudioFormat format=audioInputStream.getFormat();
SourceDataLine auline=null;
DataLine.Info info=new DataLine.Info(SourceDataLine.class, format);
try {
auline=(SourceDataLine)AudioSystem.getLine(info);
auline.open(format);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return;
}
auline.start();
int nBytesRead=0;
byte[] abdata=new byte[512];
try{
while(nBytesRead!=-1){
nBytesRead=audioInputStream.read(abdata,0,abdata.length);
if(nBytesRead>=0)
auline.write(abdata, 0, nBytesRead);
}
}catch(IOException e){
e.printStackTrace();return;
}finally{
auline.drain();auline.close();
}
}
}
class Bomb
{
int x,y; //define Bullet location
int life=9; //lifetime
boolean isLive=true;
public Bomb(int x,int y)
{
this.x=x;
this.y=y;
}
//cutdonw lifetime
public void lifeDown()
{
if(life>0)
{
life--;
}else{
this.isLive=false;
}
}
}
class Bullet implements Runnable{
int x;
int y;
int direct;
int speed=3;
boolean isLive=false;
public Bullet(int x, int y,int direct)
{
this.x=x;
this.y=y;
this.direct=direct;
}
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 getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
@Override
public void run() {
while(true)
{
// TODO 自动生成的方法存根
try {
Thread.sleep(50);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
switch(direct)
{
case 0:y-=speed;break;
case 1:y+=speed;break;
case 2:x-=speed;break;
case 3:x+=speed;break;
}
// judfe whether bullet get to the boder
if(x<0 || x>600 ||y<0 ||y>500)
{
this.isLive=false;
}
}
}
}
class Tank
{
int x=0;
int y=0;
int direct=0; //0up 1:down 2:left 3:right
int color;
boolean isLive=true;
int speed=3;
public Tank(int x,int y)
{
this.x=x;
this.y=y;
}
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 getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
void MoveUp()
{
this.y-=speed;
}
void MoveDown()
{
this.y+=speed;
}
void MoveLeft()
{
this.x-=speed;
}
void MoveRight()
{
this.x+=speed;
}
}
class EnemyTank extends Tank implements Runnable
{
public EnemyTank(int x, int y) {
super(x, y);
// TODO 自动生成的构造函数存根
}
@Override
public void run() {
int times=0;
while(true)
{
times++;
// TODO 自动生成的方法存根
try {
Thread.sleep(50);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
switch(direct)
{
case 0:y-=speed;if(y<0)direct=1;break;
case 1:y+=speed;if(y>500)direct=0;break;
case 2:x-=speed;if(x<0)direct=3;break;
case 3:x+=speed;if(x>600)direct=2;break;
}
//every other 18 times change a random direct
if(times%18==0) direct=(int)(Math.random()*4 ); }
}
}