碰撞效果实现:
利用CollisionUtils判断两个对象是否发生碰撞
x1:第一个矩形的x坐标
y1:第一个矩形的y坐标
w1:第一个矩形的宽度
h1:第一个矩形的高度
x2:第二个矩形的x坐标
y2:第二个矩形的y坐标
w2:第二个矩形的宽度
h2:第二个矩形的高度
可以理解为tank和wall的碰撞检测,如果发生碰撞则返回true,否则返回false
代码实现:
1、创建一个墙类,继承于Element
1 package Itheima.bean; 2 3 public class Wall extends Element { 4 public Wall(int x,int y) { 5 this.x=x; 6 this.y=y; 7 this.imagePath="res/img/wall.gif"; 8 getSize(); //获取墙的宽高 9 } 10 }
Wall
2、在设置类将Wall对象添加入集合,遍历集合
1 package Itheima; 2 3 import java.util.List; 4 import java.util.concurrent.CopyOnWriteArrayList; 5 6 import org.itheima.game.Window; 7 import org.lwjgl.input.Keyboard; 8 9 import Itheima.bean.Bullet; 10 import Itheima.bean.Direction; 11 import Itheima.bean.Element; 12 import Itheima.bean.Tank; 13 import Itheima.bean.Wall; 14 15 public class TankWorld extends Window { 16 Tank tank; 17 Wall wall; 18 List<Element> list; 19 20 public TankWorld(String title, int width, int height, int fps) { 21 super(title, width, height, fps); 22 // TODO 自动生成的构造函数存根 23 } 24 25 @Override 26 protected void onCreate() { 27 list = new CopyOnWriteArrayList<>(); 28 tank = new Tank(0, 0); 29 wall = new Wall(64, 64); 30 list.add(tank); 31 list.add(wall); 32 } 33 34 @Override 35 protected void onMouseEvent(int key, int x, int y) { 36 // TODO 自动生成的方法存根 37 38 } 39 40 @Override 41 protected void onKeyEvent(int key) { 42 switch (key) { 43 case Keyboard.KEY_UP: 44 tank.move(Direction.UP); 45 break; 46 47 case Keyboard.KEY_DOWN: 48 tank.move(Direction.DOWN); 49 break; 50 case Keyboard.KEY_LEFT: 51 tank.move(Direction.LEFT); 52 break; 53 case Keyboard.KEY_RIGHT: 54 tank.move(Direction.RIGHT); 55 break; 56 case Keyboard.KEY_SPACE: 57 Bullet bullet = tank.fire(); 58 list.add(bullet); 59 break; 60 } 61 } 62 63 @Override 64 protected void onDisplayUpdate() { 65 for (Element e : list) { 66 e.draw(); 67 } 68 69 for (Element e1 : list) { 70 if(e1 instanceof Tank){ //遍历到Tank对象 71 Tank t = (Tank) e1; //将e1转换成Tank类 72 for (Element e2 : list) { 73 if(e2 instanceof Wall){ //遍历到Wall对象 74 Wall w = (Wall) e2; //将e2转换成Wall对象 75 boolean result = t.impact(w); //判断Tank与Wall是否发生碰撞 76 if(result){ 77 break; //如果撞上了就跳出循环 不继续和下一个墙做判断 78 } 79 } 80 } 81 } 82 } 83 } 84 85 }
TankWorld
3、Tank类碰撞方法
1 package Itheima.bean; 2 3 import java.util.Collections; 4 5 import org.itheima.game.utils.CollisionUtils; 6 7 import Itheima.Constants; 8 9 public class Tank extends Element { 10 private int speed = 32; // 移动速度 11 Direction dir = Direction.UP; // 方向默认向上 12 Direction badDirection = null; //记录tank不能走的方向 13 14 public Tank(int x, int y) { // 构造方法 15 this.x = x; 16 this.y = y; 17 this.imagePath = "res/img/tank_u.gif"; 18 getSize(); // 获取tank宽高 19 } 20 21 public void move(Direction dir) { 22 if(badDirection!=null && dir == badDirection){ //判断当前方向是否等于不能走的方向 23 return ; //如果是则不执行下面的代码 24 } 25 if (dir != this.dir) { // 传入的方向不等于当前方向 26 this.dir = dir; // 当前方向等于传入的方向 27 switch (dir) { // 只更换方向不做移动 28 case UP: 29 this.imagePath = "res/img/tank_u.gif"; 30 break; 31 32 case DOWN: 33 this.imagePath = "res/img/tank_d.gif"; 34 break; 35 case LEFT: 36 this.imagePath = "res/img/tank_l.gif"; 37 break; 38 case RIGHT: 39 this.imagePath = "res/img/tank_r.gif"; 40 break; 41 } 42 } 43 switch (dir) { // 如果当前方向等于传入的方向 44 case UP: 45 y -= speed; 46 break; 47 48 case DOWN: 49 y += speed; 50 break; 51 case LEFT: 52 x -= speed; 53 break; 54 case RIGHT: 55 x += speed; 56 break; 57 } 58 // 越界处理 59 if (x < 0) { 60 x = 0; 61 } 62 if (x > Constants.WIDTH - this.width) { 63 x = Constants.WIDTH - this.width; 64 } 65 if (y < 0) { 66 y = 0; 67 } 68 if (y > Constants.HEIGHT - this.height) { 69 y = Constants.HEIGHT - this.height; 70 } 71 } 72 73 public Bullet fire() { 74 Bullet b = new Bullet(this); // 根据tank坐标生成子弹 75 return b; 76 } 77 78 public boolean impact(Wall w) { // 判断是否发生碰撞 79 int x1 = this.x; // 坦克的参数 80 int y1 = this.y; 81 int w1 = this.width; 82 int h1 = this.height; 83 84 int x2 = w.x; // 墙的参数 85 int y2 = w.y; 86 int w2 = w.width; 87 int h2 = w.height; 88 89 // 根据tank的方向计算下一步的坐标 90 switch (this.dir) { 91 case UP: 92 y1 -= speed; 93 break; 94 95 case DOWN: 96 y1 += speed; 97 break; 98 case LEFT: 99 x1 -= speed; 100 break; 101 case RIGHT: 102 x1 += speed; 103 break; 104 } 105 106 //碰撞检测函数 107 boolean result = CollisionUtils.isCollisionWithRect(x1, y1, w1, h1, x2, y2, w2, h2); 108 109 if (result) { 110 badDirection = this.dir; 111 switch (this.dir) { 112 case UP: 113 this.y = y2 + h2; 114 break; 115 116 case DOWN: 117 this.y = y2 - h1; 118 break; 119 case LEFT: 120 this.x = x2 + w2; 121 break; 122 case RIGHT: 123 this.x = x2 - w1; 124 break; 125 } 126 }else{ 127 badDirection = null; 128 } 129 return result; 130 } 131 }
Tank
随笔说:
必须将tank的下一步坐标放入检测函数内计算,不然还是会多走一步再退回来。
时间: 2024-10-14 06:18:26