0454-Bomb-墙壁碰撞检测

环境

  • Time 2024-03-20
  • Zig 0.12.0-dev.3152+90c1a2c41
  • WSL-Ubuntu 22.04.3 LTS
  • raylib 5.0

前言

说明

参考资料:

  1. 《游戏开发:世嘉新人培训教材》
  2. 图片素材:https://www.ituring.com.cn/book/1742

目标

对于玩家来说,墙壁不可以通行,需要实现碰撞检测。

isCollision

在引擎层的 backend.zig 中,新增了一个方法来进行碰撞的检测。

pub fn isCollision(rec1: basic.Rectangle, rec2: basic.Rectangle) bool {
    return ray.CheckCollisionRecs(toRayRec(rec1), toRayRec(rec2));
}

map.zig

地图层提供了对于碰撞检测的方法,遇到墙则不可以进行移动。

pub fn isCollisionX(self: WorldMap, x: usize, y: usize, role: Role) bool {
        for (0..3) |i| {
            if (self.isCollision(x, y + i -| 1, role)) return true;
        } else return false;
    }

    pub fn isCollisionY(self: WorldMap, x: usize, y: usize, role: Role) bool {
        for (0..3) |i| {
            if (self.isCollision(x + i - 1, y, role)) return true;
        } else return false;
    }

    pub fn isCollision(self: WorldMap, x: usize, y: usize, role: Role) bool {
        const cell = self.data[x + y * width];
        if (!cell.contains(.wall)) return false;

        const rec = engine.Rectangle{
            .x = x * tileMap.unit,
            .y = y * tileMap.unit,
            .width = tileMap.unit,
            .height = tileMap.unit,
        };
        return engine.isCollision(rec, role.toCollisionRec());

play.zig

玩法模块中新增了键盘的控制。

    fn controlPlayer(self: Gameplay) void {
        const speed = engine.frameTime() * roleSpeed;
        var p1 = self.map.player1().*;
        if (engine.isDown(engine.Key.a)) {
            p1.x -|= speed;
            const cell = p1.getCell();
            if (!self.map.isCollisionX(cell.x -| 1, cell.y, p1))
                self.map.player1().*.x = p1.x;
        }

        if (engine.isDown(engine.Key.d)) {
            p1.x += speed;
            const cell = p1.getCell();
            if (!self.map.isCollisionX(cell.x + 1, cell.y, p1))
                self.map.player1().*.x = p1.x;
        }

        p1 = self.map.player1().*;
        if (engine.isDown(engine.Key.w)) {
            p1.y -|= speed;
            const cell = p1.getCell();
            if (!self.map.isCollisionY(cell.x, cell.y -| 1, p1))
                self.map.player1().*.y = p1.y;
        }
        if (engine.isDown(engine.Key.s)) {
            p1.y += speed;
            const cell = p1.getCell();
            if (!self.map.isCollisionY(cell.x, cell.y + 1, p1))
                self.map.player1().*.y = p1.y;
        }
    }

碰撞盒

    fn toCollisionRec(self: Role) engine.Rectangle {
        return engine.Rectangle{
            .x = self.x / speedUnit + 5,
            .y = self.y / speedUnit + 5,
            .width = tileMap.unit - 10,
            .height = tileMap.unit - 7,
        };
    }

效果

和之前差不多,只是不能通过墙壁。

总结

实现了角色和墙壁的碰撞检测,增加了碰撞盒子的实现。

附录

posted @ 2026-08-16 08:50  jiangbo4444  阅读(9)  评论(0)    收藏  举报