Java自学之路
java基础之坦克大战极简版
分析:
Class Tank:实现功能——区分敌方坦克和我方坦克,按键上下左右控制我方坦克朝八个方向移动,敌方坦克随机移动,按键A发射子弹,按键Q朝八个方向开火,按键F2复活;
首先控制移动:`
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.Random;
public class Tank {
int x,y;
private boolean bl =false,bu = false, br = false, bd = false;
enum Direction{L,LU,U,UR,R,RD,D,LD,STOP};
private Direction dir = Direction.STOP;
private Direction ptdir = Direction.D;
private static final int XSPEED = 5;
private static final int YSPEED = 5;
private static final int WIDTH = 30;
private static final int HIGHT = 30;
private static final int FULLBLOOD = 100;
TankClient tc;
private boolean good ;
Blood b = new Blood();
private int oldX,oldY;
private int life = 100;
public int getLife() {
return life;
}
public void setLife(int life) {
this.life = life;
}
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
private int step = r.nextInt(12)+3;
private boolean live= true;
private static Random r = new Random();
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public void draw(Graphics g) {
if(!live) {
if(good)
return;
tc.robots.remove(this);
}
Color c = g.getColor();
if(good) g.setColor(Color.red);
else g.setColor(Color.blue);
g.fillOval(x, y, WIDTH, HIGHT);
g.setColor(c);
if(good) b.draw(g);
switch(ptdir) {
case L:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x, y+HIGHT/2);
break;
case LU:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x, y);
break;
case U:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x+WIDTH/2, y);
break;
case UR:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x+WIDTH, y);
break;
case R:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x+WIDTH, y+HIGHT/2);
break;
case RD:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x+WIDTH, y+HIGHT);
break;
case D:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x+WIDTH/2, y+HIGHT);
break;
case LD:
g.drawLine(x+WIDTH/2, y+HIGHT/2, x, y+HIGHT);
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 UR:
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(x >TankClient.GAME_WIDTH - this.WIDTH) {
x = TankClient.GAME_WIDTH-this.WIDTH;
}
if(y<this.WIDTH) {
y=this.WIDTH;
}
if(y >TankClient.GAME_HEIGHT - this.HIGHT) {
y = TankClient.GAME_HEIGHT-this.HIGHT;
}
if(!good) {
Direction[] dirs = Direction.values();
if(step == 0) {
step = r.nextInt(12)+3;
int rn = r.nextInt(dirs.length);
dir = dirs[rn];
}
step --;
if(r.nextInt(40)>38)this.fire();
}
}
public void stay() {
x = this.oldX;
y = this.oldY;
}
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.UR;
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 keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_F2:
if(!this.isLive()) {
this.setLive(true);
this.setLife(FULLBLOOD);
}
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;
}
locateDirection();
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_A:
fire();
break;
case KeyEvent.VK_Q:
superFire();
break;
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 Shot fire() {
if(!live)return null;
int x= this.x + Tank.WIDTH/2 -Shot.WIDTH/2;
int y= this.y + Tank.HIGHT/2 -Shot.HIGHT/2;
Shot s = new Shot(ptdir,x,y,this.tc,good);
tc.shots.add(s);
return s;
}
public Shot fire(Direction dir) {
if(!live)return null;
int x= this.x + Tank.WIDTH/2 -Shot.WIDTH/2;
int y= this.y + Tank.HIGHT/2 -Shot.HIGHT/2;
Shot s = new Shot(dir,x,y,this.tc,good);
tc.shots.add(s);
return s;
}
public void superFire() {
for(int i=0;i<8;i++) {
Direction[] dirs = Direction.values();
fire(dirs[i]);
}
}
public boolean hitWall(Wall w) {
if(this.getRect().intersects(w.getRect())) {
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;
}
public Tank(int x, int y, TankClient tc) {
this(x,y);
this.tc = tc;
}
public Tank(int x, int y,TankClient tc, boolean good) {
this(x,y,tc);
this.good = good;
}
public Rectangle getRect() {
return new Rectangle(x,y,WIDTH,HIGHT);
}
public Tank(int x, int y,TankClient tc, boolean good,Direction dir) {
this(x,y,tc,good);
this.dir = dir;
}
private class Blood{
public void draw(Graphics g) {
Color c = g.getColor();
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(AddBlood ab) {
if(this.live && ab.isLive() && this.getRect().intersects(ab.getRect())) {
this.life = FULLBLOOD;
ab.setLive(false);
return true;
}
return false;
}
}
Class Shot:实现功能——攻击坦克,区分敌方子弹与我方子弹,子弹不能穿墙;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.List;
public class Shot {
private static final int XSPEED=10;
private static final int YSPEED=10;
public static final int WIDTH = 10;
public static final int HIGHT = 10;
Tank.Direction dir;
public boolean live =true;
private boolean good;
int x,y;
private TankClient tc;
public Shot(Tank.Direction dir, int x, int y) {
this.dir = dir;
this.x = x;
this.y = y;
}
public Shot(Tank.Direction dir, int x, int y,TankClient tc,boolean good) {
this(dir,x,y);
this.tc = tc;
this.good = good;
}
public boolean isLive() {
return live;
}
public void draw(Graphics g) {
if(!live) {
tc.shots.remove(this);
}
Color c = g.getColor();
if(good)
g.setColor(Color.RED);
else g.setColor(Color.BLACK);
g.fillOval(x, y, WIDTH, HIGHT);
g.setColor(c);
move();
}
private void move() {
// TODO Auto-generated method stub
switch(dir) {
case L:
x -=XSPEED;
break;
case LU:
x -=XSPEED;
y -=YSPEED;
break;
case U:
y -=YSPEED;
break;
case UR:
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;
}
}
public boolean hitTank(Tank t) {
if(this.getRect().intersects(t.getRect()) && t.isLive() && this.good!=t.isGood()) {
if(t.isGood()) {
t.setLife(t.getLife()-20);
if(t.getLife() <=0) {
t.setLive(false);
}
}else t.setLive(false);
this.live=false;
Boom b = new Boom(x,y,tc);
tc.booms.add(b);
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())) {
live = false;
return true;
}
return false;
}
public Rectangle getRect() {
return new Rectangle(x,y,WIDTH,HIGHT);
}
}
Class Boom:实现功能——子弹击中坦克时产生爆炸;
import java.awt.Color;
import java.awt.Graphics;
public class Boom {
private int x,y;
private int []diameter = {4,8,15,20,25,30,40,50,35,24,16,6};
private boolean live = true;
private TankClient tc;
private int step;
public Boom(int x, int y,TankClient tc) {
this.x = x;
this.y = y;
this.tc = tc;
}
public void draw(Graphics g) {
if(!live) tc.booms.remove(this);
if(step == diameter.length) {
live = false;
step=0;
}
Color c = g.getColor();
g.setColor(Color.ORANGE);
g.fillOval(x,y, diameter[step], diameter[step]);
step++;
g.setColor(c);
}
}
Class Wall:实现功能——子弹和坦克都不能穿墙;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class Wall {
int x,y,width,height;
TankClient tc;
public void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.gray);
g.fillRect(x, y, width, height);
g.setColor(c);
}
public Rectangle getRect() {
return new Rectangle(x,y,width,height);
}
public Wall(int x, int y, int width, int height, TankClient tc) {
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.tc = tc;
}
}
Class AddBlood:实现功能——当坦克吃到血块是满血;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class AddBlood {
int x,y,w,h;
TankClient 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,450},{410,444},{405,440},{423,312},{323,313},{132,312},{312,433},{312,411},{133,132}
};
public AddBlood() {
x = pos[0][0];
y = pos[0][1];
w = h = 20;
}
public void draw(Graphics g) {
if(!live) return;
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillRect(x, y, w, h);
g.setColor(c);
move();
}
private void move() {
step ++;
if(step == pos.length)step=0;
if(live) {
x = pos[step][0];
y = pos[step][1];
}
}
public Rectangle getRect() {
return new Rectangle(x,y,w,h);
}
}
主程序:
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
public class TankClient extends Frame {
Tank myTank = new Tank(50,50,this,true);
Wall wall1 = new Wall(500,300,10,200,this);
Wall wall2 = new Wall(200,300,200,20,this);
AddBlood ab = new AddBlood();
//Tank robot = new Tank(100,100,this,false);
//Boom boom = new Boom(80,80,this);
List<Boom> booms = new ArrayList<Boom>();
List<Shot> shots = new ArrayList<Shot>();
List<Tank> robots = new ArrayList<Tank>();
public static final int GAME_WIDTH =800;
public static final int GAME_HEIGHT =600;
Image offScreenImage = null;
public void lunchJFrame() {
for(int i=0;i<10;i++) {
robots.add(new Tank(50+40*(i+1),50,this,false,Tank.Direction.D));
}
setLocation(300,100);
setSize(GAME_WIDTH, GAME_HEIGHT);
setTitle("TankWar");
this.setBackground(Color.GREEN);
//setDefaultCloseOperation(EXIT_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setResizable(false);
this.addKeyListener(new KeyMonitor());
setVisible(true);
new Thread(new RepaintThread()).start();
}
public TankClient() {
// TODO Auto-generated constructor stub
}
@Override
public void paint(Graphics g) {
g.drawString("shouts count:" + shots.size(), 50, 50);
g.drawString("booms count:" + booms.size(), 50, 70);
g.drawString("robots count:" + robots.size(), 50, 90);
g.drawString("maTank life:" + myTank.getLife(), 50, 110);
// TODO Auto-generated method stub
myTank.draw(g);
myTank.hitWall(wall1);
myTank.hitWall(wall2);
myTank.collidesWithTanks(robots);
wall1.draw(g);
wall2.draw(g);
ab.draw(g);
myTank.eat(ab);
for(int i=0;i<shots.size();i++) {
Shot s = shots.get(i);
s.draw(g);
s.hitTanks(robots);
s.hitTank(myTank);
s.hitWall(wall1);
s.hitWall(wall2);
}
for(int i=0;i<booms.size();i++) {
Boom b = booms.get(i);
b.draw(g);
}
for(int i=0;i<robots.size();i++) {
Tank t = robots.get(i);
t.draw(g);
t.hitWall(wall1);
t.hitWall(wall2);
t.collidesWithTanks(robots);
}
if(robots.size()<=0) {
for(int i=0;i<10;i++) {
robots.add(new Tank(50+40*(i+1),50,this,false,Tank.Direction.D));
}
}
}
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.GREEN);
gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
TankClient tc = new TankClient();
tc.lunchJFrame();
}
private class RepaintThread implements Runnable{
@Override
public void run() {
while(true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private class KeyMonitor extends KeyAdapter{
@Override
public void keyReleased(KeyEvent e) {
myTank.keyReleased(e);
}
@Override
public void keyPressed(KeyEvent e) {
myTank.keyPressed(e);
}
}
}
运行结果:
`