parent
d7c520268a
commit
bcbf04312b
Binary file not shown.
@ -0,0 +1,129 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.enums.Direction;
|
||||||
|
import com.demo.tank.enums.Group;
|
||||||
|
import com.demo.tank.util.ResourceManager;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class Bullet extends GameObject {
|
||||||
|
private Direction direction;
|
||||||
|
private static final int SPEED = 10;
|
||||||
|
public static final int WIDTH = ResourceManager.bulletD.getWidth();
|
||||||
|
public static final int HEIGHT = ResourceManager.bulletD.getHeight();
|
||||||
|
private boolean live = true;
|
||||||
|
private Group group = Group.BAD;
|
||||||
|
Rectangle rect = new Rectangle();
|
||||||
|
|
||||||
|
public Bullet(int x, int y, Direction direction, Group group) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.direction = direction;
|
||||||
|
this.group = group;
|
||||||
|
|
||||||
|
rect.x = this.x;
|
||||||
|
rect.y = this.y;
|
||||||
|
rect.width = Bullet.WIDTH;
|
||||||
|
rect.height = Bullet.HEIGHT;
|
||||||
|
GameModel.getInstance().add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
if (!live) {
|
||||||
|
GameModel.getInstance().remove(this);
|
||||||
|
}
|
||||||
|
switch (direction) {
|
||||||
|
case UP:
|
||||||
|
g.drawImage(ResourceManager.bulletU, x, y, null);
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
g.drawImage(ResourceManager.bulletD, x, y, null);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
g.drawImage(ResourceManager.bulletL, x, y, null);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
g.drawImage(ResourceManager.bulletR, x, y, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
move();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void move() {
|
||||||
|
switch (direction) {
|
||||||
|
case UP:
|
||||||
|
y -= SPEED;
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
y += SPEED;
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
x -= SPEED;
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
x += SPEED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (x < 0 || y < 0 || x > TankFrameV14.GAME_WIDTH || y > TankFrameV14.GAME_HEIGHT) {
|
||||||
|
live = false;
|
||||||
|
}
|
||||||
|
rect.x = this.x;
|
||||||
|
rect.y = this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void die() {
|
||||||
|
this.live = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Direction getDirection() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirection(Direction direction) {
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLive() {
|
||||||
|
return live;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLive(boolean live) {
|
||||||
|
this.live = live;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Group getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(Group group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth() {
|
||||||
|
return WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
public class BulletTankCollider implements Collider {
|
||||||
|
@Override
|
||||||
|
public void collide(GameObject g1, GameObject g2) {
|
||||||
|
if (g1 instanceof Bullet && g2 instanceof Tank) {
|
||||||
|
Bullet b = (Bullet) g1;
|
||||||
|
Tank t = (Tank) g2;
|
||||||
|
//关闭队友伤害
|
||||||
|
if (b.getGroup() == t.getGroup()) return;
|
||||||
|
if (b.rect.intersects(t.rect)) {
|
||||||
|
t.die();
|
||||||
|
b.die();
|
||||||
|
//爆炸
|
||||||
|
int ex = t.getX() + Tank.WIDTH / 2 - Explode.WIDTH / 2;
|
||||||
|
int ey = t.getY() + Tank.HEIGHT / 2 - Explode.HEIGHT / 2;
|
||||||
|
GameModel.getInstance().add(new Explode(ex, ey));
|
||||||
|
}
|
||||||
|
} else if (g1 instanceof Tank && g2 instanceof Bullet) {
|
||||||
|
collide(g2, g1);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
public class BulletWallCollider implements Collider {
|
||||||
|
@Override
|
||||||
|
public void collide(GameObject g1, GameObject g2) {
|
||||||
|
if (g1 instanceof Bullet && g2 instanceof Wall) {
|
||||||
|
Bullet b = (Bullet) g1;
|
||||||
|
Wall w = (Wall) g2;
|
||||||
|
if (b.rect.intersects(w.rect)) {
|
||||||
|
b.die();
|
||||||
|
}
|
||||||
|
} else if (g1 instanceof Wall && g2 instanceof Bullet) {
|
||||||
|
collide(g2, g1);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
public interface Collider {
|
||||||
|
void collide(GameObject g1, GameObject g2);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ColliderChain {
|
||||||
|
private List<Collider> colliders = new LinkedList<>();
|
||||||
|
|
||||||
|
public ColliderChain() {
|
||||||
|
add(new BulletTankCollider());
|
||||||
|
add(new TankTankCollider());
|
||||||
|
add(new BulletWallCollider());
|
||||||
|
add(new TankWallCollider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Collider collider) {
|
||||||
|
colliders.add(collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collide(GameObject g1, GameObject g2) {
|
||||||
|
for (Collider c : colliders) {
|
||||||
|
c.collide(g1, g2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.enums.Group;
|
||||||
|
import com.demo.tank.util.Audio;
|
||||||
|
|
||||||
|
public class DefaultFireStrategy implements FireStrategy {
|
||||||
|
@Override
|
||||||
|
public void fire(Tank tank) {
|
||||||
|
int bx = tank.getX() + Tank.WIDTH / 2 - Bullet.WIDTH / 2;
|
||||||
|
int by = tank.getY() + Tank.HEIGHT / 2 - Bullet.HEIGHT / 2;
|
||||||
|
new Bullet(bx, by, tank.getDir(), tank.getGroup());
|
||||||
|
// GameModel.getInstance().add(new RectDecorator(new Bullet(bx, by, tank.getDir(), tank.getGroup())));
|
||||||
|
// GameModel.getInstance().add(new RectDecorator(
|
||||||
|
// new TailDecorator(
|
||||||
|
// new Bullet(bx, by, tank.getDir(), tank.getGroup())
|
||||||
|
// )
|
||||||
|
// ));
|
||||||
|
if (tank.getGroup() == Group.GOOD) new Thread(() -> new Audio("audio/tank_fire.wav").play()).start();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.util.Audio;
|
||||||
|
import com.demo.tank.util.ResourceManager;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class Explode extends GameObject {
|
||||||
|
public static final int WIDTH = ResourceManager.explodes[0].getWidth();
|
||||||
|
public static final int HEIGHT = ResourceManager.explodes[0].getHeight();
|
||||||
|
|
||||||
|
private int step = 0;
|
||||||
|
|
||||||
|
public Explode(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
new Thread(() -> new Audio("audio/explode.wav").play()).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
g.drawImage(ResourceManager.explodes[step++], x, y, null);
|
||||||
|
if (step >= ResourceManager.explodes.length) {
|
||||||
|
//播放完爆炸效果图片, remove
|
||||||
|
GameModel.getInstance().remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 getWidth() {
|
||||||
|
return WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public interface FireStrategy extends Serializable {
|
||||||
|
void fire(Tank tank);
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.enums.Direction;
|
||||||
|
import com.demo.tank.enums.Group;
|
||||||
|
import com.demo.tank.util.Audio;
|
||||||
|
|
||||||
|
public class FourDirectionFireStrategy implements FireStrategy {
|
||||||
|
@Override
|
||||||
|
public void fire(Tank tank) {
|
||||||
|
int bx = tank.getX() + Tank.WIDTH / 2 - Bullet.WIDTH / 2;
|
||||||
|
int by = tank.getY() + Tank.HEIGHT / 2 - Bullet.HEIGHT / 2;
|
||||||
|
for (Direction direction : Direction.values()) {
|
||||||
|
new Bullet(bx, by, direction, tank.getGroup());
|
||||||
|
}
|
||||||
|
if (tank.getGroup() == Group.GOOD) new Thread(() -> new Audio("audio/tank_fire.wav").play()).start();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public abstract class GODecorator extends GameObject {
|
||||||
|
GameObject go;
|
||||||
|
|
||||||
|
public GODecorator(GameObject go) {
|
||||||
|
this.go = go;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void paint(Graphics g);
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.enums.Direction;
|
||||||
|
import com.demo.tank.enums.Group;
|
||||||
|
import com.demo.tank.util.PropertyManager;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GameModel {
|
||||||
|
private static final GameModel GM = new GameModel();
|
||||||
|
|
||||||
|
static {
|
||||||
|
GM.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GameObject> gameObjects = new ArrayList<>();
|
||||||
|
|
||||||
|
// Collider collider = new BulletTankCollider();
|
||||||
|
// Collider collider2 = new TankTankCollider();
|
||||||
|
ColliderChain chain = new ColliderChain();
|
||||||
|
Tank tank;
|
||||||
|
|
||||||
|
private GameModel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
tank = new Tank(380, 660, Direction.UP, Group.GOOD);
|
||||||
|
int enemyTankNum = PropertyManager.getInt("enemy.tank.number");
|
||||||
|
for (int i = 0; i < enemyTankNum; i++) {
|
||||||
|
add(new Tank(50 + i * 80, 200, Direction.DOWN, Group.BAD));
|
||||||
|
}
|
||||||
|
add(new Wall(150, 150, 200, 50));
|
||||||
|
add(new Wall(550, 150, 200, 50));
|
||||||
|
add(new Wall(300, 300, 50, 200));
|
||||||
|
add(new Wall(550, 300, 50, 200));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameModel getInstance() {
|
||||||
|
return GM;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(GameObject go) {
|
||||||
|
gameObjects.add(go);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(GameObject go) {
|
||||||
|
gameObjects.remove(go);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
tank.paint(g);
|
||||||
|
|
||||||
|
for (int i = 0; i < gameObjects.size(); i++) {
|
||||||
|
gameObjects.get(i).paint(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
//碰撞检测
|
||||||
|
for (int i = 0; i < gameObjects.size(); i++) {
|
||||||
|
for (int j = i + 1; j < gameObjects.size(); j++) {
|
||||||
|
GameObject g1 = gameObjects.get(i);
|
||||||
|
GameObject g2 = gameObjects.get(j);
|
||||||
|
chain.collide(g1, g2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(){
|
||||||
|
File file = new File("D:\\workspace\\tank\\src\\com\\demo\\tank\\course14\\tank.data");
|
||||||
|
ObjectOutputStream oos = null;
|
||||||
|
try {
|
||||||
|
oos = new ObjectOutputStream(new FileOutputStream(file));
|
||||||
|
oos.writeObject(tank);
|
||||||
|
oos.writeObject(gameObjects);
|
||||||
|
System.out.println("game saved...");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}finally {
|
||||||
|
try {
|
||||||
|
if(oos != null){
|
||||||
|
oos.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(){
|
||||||
|
File file = new File("D:\\workspace\\tank\\src\\com\\demo\\tank\\course14\\tank.data");
|
||||||
|
ObjectInputStream ois = null;
|
||||||
|
try {
|
||||||
|
ois = new ObjectInputStream(new FileInputStream(file));
|
||||||
|
tank = (Tank)ois.readObject();
|
||||||
|
gameObjects = (List)ois.readObject();
|
||||||
|
System.out.println("game load...");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}finally {
|
||||||
|
try {
|
||||||
|
if(ois != null){
|
||||||
|
ois.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public abstract class GameObject implements Serializable {
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
public abstract void paint(Graphics g);
|
||||||
|
|
||||||
|
public abstract int getWidth();
|
||||||
|
|
||||||
|
public abstract int getHeight();
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class MainV14 {
|
||||||
|
public static void main(String[] args) throws InterruptedException, IOException {
|
||||||
|
TankFrameV14 tf = new TankFrameV14();
|
||||||
|
|
||||||
|
// new Thread(() -> new Audio("audio/war1.wav").loop()).start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
tf.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class RectDecorator extends GODecorator {
|
||||||
|
|
||||||
|
public RectDecorator(GameObject go) {
|
||||||
|
super(go);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
//decorator x,y 也要跟随游戏物体 变化
|
||||||
|
this.x = go.x;
|
||||||
|
this.y = go.y;
|
||||||
|
go.paint(g);
|
||||||
|
Color c = g.getColor();
|
||||||
|
g.setColor(Color.MAGENTA);
|
||||||
|
g.drawRect(go.x, go.y, getWidth(), getHeight());
|
||||||
|
g.setColor(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth() {
|
||||||
|
return super.go.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return super.go.getHeight();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class TailDecorator extends GODecorator {
|
||||||
|
|
||||||
|
public TailDecorator(GameObject go) {
|
||||||
|
super(go);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
go.paint(g);
|
||||||
|
this.x = go.x;
|
||||||
|
this.y = go.y;
|
||||||
|
Color c = g.getColor();
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
g.drawLine(go.x, go.y, go.x + getWidth(), go.y + getHeight());
|
||||||
|
g.setColor(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth() {
|
||||||
|
return super.go.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return super.go.getHeight();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,206 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.enums.Direction;
|
||||||
|
import com.demo.tank.enums.Group;
|
||||||
|
import com.demo.tank.util.ResourceManager;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Tank extends GameObject {
|
||||||
|
int oldX, oldY;
|
||||||
|
private Direction dir;
|
||||||
|
private static final int SPEED = 8;
|
||||||
|
private boolean moving = true;
|
||||||
|
private boolean living = true;
|
||||||
|
private Group group = Group.BAD;
|
||||||
|
public static final int WIDTH = ResourceManager.tankD.getWidth();
|
||||||
|
public static final int HEIGHT = ResourceManager.tankD.getHeight();
|
||||||
|
private Random random = new Random();
|
||||||
|
Rectangle rect = new Rectangle();
|
||||||
|
FireStrategy fireStrategy;
|
||||||
|
|
||||||
|
|
||||||
|
public Tank(int x, int y, Direction dir, Group group) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.dir = dir;
|
||||||
|
this.group = group;
|
||||||
|
|
||||||
|
rect.x = this.x;
|
||||||
|
rect.y = this.y;
|
||||||
|
rect.width = Tank.WIDTH;
|
||||||
|
rect.height = Tank.HEIGHT;
|
||||||
|
|
||||||
|
if (this.group == Group.GOOD) {
|
||||||
|
// String className = PropertyManager.getString("good.tank.fire.strategy");
|
||||||
|
try {
|
||||||
|
fireStrategy = (FireStrategy) Class.forName("com.demo.tank.course14.FourDirectionFireStrategy").newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else if (this.group == Group.BAD) fireStrategy = new DefaultFireStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
if (!living) GameModel.getInstance().remove(this);
|
||||||
|
//根据方向绘制坦克
|
||||||
|
switch (dir) {
|
||||||
|
case UP:
|
||||||
|
g.drawImage(this.group == Group.GOOD ? ResourceManager.tankU : ResourceManager.badTankU, x, y, null);
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
g.drawImage(this.group == Group.GOOD ? ResourceManager.tankD : ResourceManager.badTankD, x, y, null);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
g.drawImage(this.group == Group.GOOD ? ResourceManager.tankL : ResourceManager.badTankL, x, y, null);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
g.drawImage(this.group == Group.GOOD ? ResourceManager.tankR : ResourceManager.badTankR, x, y, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
move();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move() {
|
||||||
|
oldX = x;
|
||||||
|
oldY = y;
|
||||||
|
//如果没有移动 return
|
||||||
|
if (!moving) return;
|
||||||
|
switch (dir) {
|
||||||
|
case UP:
|
||||||
|
y -= SPEED;
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
y += SPEED;
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
x -= SPEED;
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
x += SPEED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (this.group == Group.BAD) {
|
||||||
|
if (random.nextInt(10) == 5) {
|
||||||
|
this.fire();
|
||||||
|
}
|
||||||
|
if (random.nextInt(100) > 95) {
|
||||||
|
this.randomDirection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//边界检测
|
||||||
|
boundsCheck();
|
||||||
|
|
||||||
|
rect.x = this.x;
|
||||||
|
rect.y = this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void back() {
|
||||||
|
this.x = oldX;
|
||||||
|
this.y = oldY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void boundsCheck() {
|
||||||
|
if (x < 0) x = 0;
|
||||||
|
if (x > TankFrameV14.GAME_WIDTH - Tank.WIDTH) x = TankFrameV14.GAME_WIDTH - Tank.WIDTH;
|
||||||
|
if (y < 30) y = 30; //算上菜单条
|
||||||
|
if (y > TankFrameV14.GAME_HEIGHT - Tank.HEIGHT) y = TankFrameV14.GAME_HEIGHT - Tank.HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void randomDirection() {
|
||||||
|
this.dir = Direction.values()[random.nextInt(4)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fire() {
|
||||||
|
fireStrategy.fire(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleFireKey(){
|
||||||
|
java.util.List<TankFireObserver> observers = Arrays.asList(new TankFireHandler());
|
||||||
|
TankEvent event = new TankEvent(Timestamp.from(Instant.now()), this);
|
||||||
|
for (TankFireObserver o : observers){
|
||||||
|
o.actionOnFire(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void die() {
|
||||||
|
this.living = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 Direction getDir() {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDir(Direction dir) {
|
||||||
|
this.dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMoving() {
|
||||||
|
return moving;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoving(boolean moving) {
|
||||||
|
this.moving = moving;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLiving() {
|
||||||
|
return living;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLiving(boolean living) {
|
||||||
|
this.living = living;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Group getGroup() {
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroup(Group group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle getRect() {
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRect(Rectangle rect) {
|
||||||
|
this.rect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
public class TankEvent {
|
||||||
|
private Timestamp timestamp;
|
||||||
|
private Tank source;
|
||||||
|
|
||||||
|
public TankEvent(Timestamp timestamp, Tank source) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Timestamp getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tank getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
public class TankFireHandler implements TankFireObserver {
|
||||||
|
@Override
|
||||||
|
public void actionOnFire(TankEvent event) {
|
||||||
|
Tank tank = event.getSource();
|
||||||
|
System.out.println("my tank fire time: " + event.getTimestamp());
|
||||||
|
tank.fire();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public interface TankFireObserver extends Serializable {
|
||||||
|
void actionOnFire(TankEvent event);
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import com.demo.tank.enums.Direction;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.KeyAdapter;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
|
||||||
|
public class TankFrameV14 extends Frame {
|
||||||
|
GameModel gm = GameModel.getInstance();
|
||||||
|
public static final int GAME_WIDTH = 1080;
|
||||||
|
public static final int GAME_HEIGHT = 800;
|
||||||
|
Image image = null;
|
||||||
|
|
||||||
|
public TankFrameV14() {
|
||||||
|
setVisible(true);
|
||||||
|
setBounds(400, 100, GAME_WIDTH, GAME_HEIGHT);
|
||||||
|
setResizable(false);
|
||||||
|
setTitle("tank war");
|
||||||
|
this.addKeyListener(new MyKeyListener());
|
||||||
|
this.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent e) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Graphics g) {
|
||||||
|
if (image == null) {
|
||||||
|
image = this.createImage(GAME_WIDTH, GAME_HEIGHT);
|
||||||
|
}
|
||||||
|
Graphics imgGraphic = image.getGraphics();
|
||||||
|
Color color = g.getColor();
|
||||||
|
imgGraphic.setColor(Color.BLACK);
|
||||||
|
imgGraphic.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
|
||||||
|
imgGraphic.setColor(color);
|
||||||
|
paint(imgGraphic);
|
||||||
|
g.drawImage(image, 0, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
gm.paint(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyKeyListener extends KeyAdapter {
|
||||||
|
boolean bL = false;
|
||||||
|
boolean bR = false;
|
||||||
|
boolean bU = false;
|
||||||
|
boolean bD = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
switch (e.getKeyCode()) {
|
||||||
|
case KeyEvent.VK_A:
|
||||||
|
bL = true;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_D:
|
||||||
|
bR = true;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_W:
|
||||||
|
bU = true;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_S:
|
||||||
|
bD = true;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_O:
|
||||||
|
gm.save();
|
||||||
|
case KeyEvent.VK_L:
|
||||||
|
gm.load();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setTankDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyReleased(KeyEvent e) {
|
||||||
|
switch (e.getKeyCode()) {
|
||||||
|
case KeyEvent.VK_A:
|
||||||
|
bL = false;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_D:
|
||||||
|
bR = false;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_W:
|
||||||
|
bU = false;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_S:
|
||||||
|
bD = false;
|
||||||
|
break;
|
||||||
|
case KeyEvent.VK_SPACE:
|
||||||
|
gm.tank.handleFireKey();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setTankDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTankDirection() {
|
||||||
|
if (!bL && !bR && !bU && !bD) {
|
||||||
|
gm.tank.setMoving(false);
|
||||||
|
} else {
|
||||||
|
gm.tank.setMoving(true);
|
||||||
|
if (bL) gm.tank.setDir(Direction.LEFT);
|
||||||
|
if (bR) gm.tank.setDir(Direction.RIGHT);
|
||||||
|
if (bU) gm.tank.setDir(Direction.UP);
|
||||||
|
if (bD) gm.tank.setDir(Direction.DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class TankTankCollider implements Collider {
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collide(GameObject g1, GameObject g2) {
|
||||||
|
if (g1 instanceof Tank && g2 instanceof Tank) {
|
||||||
|
Tank t1 = (Tank) g1;
|
||||||
|
Tank t2 = (Tank) g2;
|
||||||
|
if (t1.rect.intersects(t2.rect)) {
|
||||||
|
// simple deal
|
||||||
|
t1.back();
|
||||||
|
t2.back();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
public class TankWallCollider implements Collider {
|
||||||
|
@Override
|
||||||
|
public void collide(GameObject g1, GameObject g2) {
|
||||||
|
if (g1 instanceof Tank && g2 instanceof Wall) {
|
||||||
|
Tank t = (Tank) g1;
|
||||||
|
Wall w = (Wall) g2;
|
||||||
|
if (t.rect.intersects(w.rect)) {
|
||||||
|
t.back();
|
||||||
|
}
|
||||||
|
} else if (g1 instanceof Wall && g2 instanceof Bullet) {
|
||||||
|
collide(g2, g1);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.demo.tank.course14;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class Wall extends GameObject {
|
||||||
|
int width, height;
|
||||||
|
Rectangle rect;
|
||||||
|
|
||||||
|
public Wall(int x, int y, int width, int height) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.rect = new Rectangle(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
Color c = g.getColor();
|
||||||
|
g.setColor(Color.DARK_GRAY);
|
||||||
|
g.fillRect(x, y, width, height);
|
||||||
|
g.setColor(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue