添加墙元素实现碰撞效果

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 }
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的下一步坐标放入检测函数内计算,不然还是会多走一步再退回来。

以上是关于添加墙元素实现碰撞效果的主要内容,如果未能解决你的问题,请参考以下文章

学习 Python 之 Pygame 开发坦克大战

Unity的物理引擎是如何实现碰撞的呢?

[Unity] 碰撞器, 触发器, 刚体,Dynamic, Kinematic, Static, OnCollision, OnTrigger 全讲

[Unity] 碰撞器, 触发器, 刚体,Dynamic, Kinematic, Static, OnCollision, OnTrigger 全讲

CSS代码片段

CSS代码片段