添加墙元素实现碰撞效果
Posted B_Lasting_尊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了添加墙元素实现碰撞效果相关的知识,希望对你有一定的参考价值。
碰撞效果实现:
利用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 }
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 }
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的下一步坐标放入检测函数内计算,不然还是会多走一步再退回来。
以上是关于添加墙元素实现碰撞效果的主要内容,如果未能解决你的问题,请参考以下文章
[Unity] 碰撞器, 触发器, 刚体,Dynamic, Kinematic, Static, OnCollision, OnTrigger 全讲
[Unity] 碰撞器, 触发器, 刚体,Dynamic, Kinematic, Static, OnCollision, OnTrigger 全讲