2D Raylib 纹理碰撞

2D Raylib Texture Collisions

我想知道如何在 Raylib 中正确处理碰撞。设置好基础后,比如 window,我会首先加载播放器纹理,如下所示:

Texture2D playerTexture = LoadTexture("Player.png");

之后,我会绘制纹理,使用 Raylib 函数 DrawTextureEx,它允许我调整纹理的旋转和缩放。然后,我会为玩家添加一个简单的移动脚本,这样就差不多了。

至于碰撞,我只是在矩形上测试玩家碰撞。要获得矩形的面积,我只需创建一个简单的 Rectangle 结构,如下所示:

Rectangle rect1 = {100, 100, 50, 50};

至于获得播放器区域,我会做类似的事情:

Rectangle playerArea = {player.x, player.y, playerTexture.width*player.scale, playerTexture.height*player.scale} //Values are stored in Player struct

然而,当我尝试像这样检查 collisons 时,没有任何反应:

    if (CheckCollisionRecs(playerArea, rect1)) {
        DrawText("Collided", 5, 5, 25, BLACK);
    }

如果需要,这是我的完整代码:

#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>

#define WIDTH 1200 
#define HEIGHT 800

typedef struct {
    const int width;
    const int height;
    int FPS;
} Window;

Window window = {
    .FPS = 60,
};

typedef struct {
    Vector2 pos;
    Vector2 acc;
    Vector2 vel;
    int width;
    int height;

    double accSpeed;
    int maxVel;
    double friction;
    double rotation;
    double scale;

} Player;

Player player = {

    .pos = {WIDTH/2, HEIGHT/2},
    .acc = {0, 0},
    .vel = {0, 0},
    .width = 25,
    .height = 25,

    .accSpeed = 0.15,
    .maxVel = 7,
    .friction = 0.2,
    .rotation = 0,
    .scale = 0.5,
};

void movePlayer();
int rectCollide();

int main() {

    InitWindow(WIDTH, HEIGHT, "Window");
    SetTargetFPS(window.FPS);

    Texture2D playerImg = LoadTexture("Player.png");

    Rectangle playerArea = {player.pos.x, player.pos.y, playerImg.width*player.scale, playerImg.height*player.scale};
    Rectangle rect1 = {100, 100, 50, 50};

    Camera2D camera = { 0 };
    camera.target = (Vector2){ player.pos.x + 20.0f, player.pos.y + 20.0f };
    camera.offset = (Vector2){WIDTH/2.0f, HEIGHT/2.0f };
    camera.rotation = 0.0f;
    camera.zoom = 1.0f;

    if (CheckCollisionRecs(playerArea, rect1)) {
        DrawText("Collided", 5, 5, 25, BLACK);
    }

    while (!WindowShouldClose()) {

        BeginDrawing();
        ClearBackground(SKYBLUE);

        movePlayer();

        camera.target = (Vector2){ player.pos.x + 20, player.pos.y + 20 };

        BeginMode2D(camera);
        DrawRectangle(100, 100, 50, 50, BLACK);
        DrawTextureEx(playerImg, player.pos, player.rotation, player.scale, RAYWHITE);
        
        EndMode2D();

        EndDrawing();
    }
    UnloadTexture(playerImg);

    CloseWindow();

    return 0;
}

void movePlayer() {
    if (IsKeyDown(KEY_LEFT) && player.vel.x > -player.maxVel) {
        player.acc.x = -player.accSpeed;
    } else if (IsKeyDown(KEY_RIGHT) && player.vel.x < player.maxVel) {
        player.acc.x = player.accSpeed;
    } else if (abs(player.vel.x) > 0.2) {
        if (player.vel.x < 0) {
            player.acc.x = player.friction;
        } else {
            player.acc.x = -player.friction;
        }
    } else {
        player.vel.x = 0;
        player.acc.x = 0;
    }
    player.vel.x += player.acc.x;
    player.pos.x += player.vel.x;

    if (IsKeyDown(KEY_UP) && player.vel.y > -player.maxVel) {
        player.acc.y = -player.accSpeed;
    } else if (IsKeyDown(KEY_DOWN) && player.vel.x < player.maxVel) {
        player.acc.y = player.accSpeed;
    } else if (abs(player.vel.y) > 0.2) {
        if (player.vel.y < 0) {
            player.acc.y = player.friction;
        } else {
            player.acc.y = -player.friction;
        }
    } else {
        player.vel.y = 0;
        player.acc.y = 0;
    }
    player.vel.y += player.acc.y;
    player.pos.y += player.vel.y;
}

int rectCollide(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
  return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2;
}

所以,我想知道:首先,有没有更好的方法来获取纹理的面积,而不必为每个纹理创建一个 Rectangle 结构,并将比例乘以纹理的宽度和高度?其次,我想知道为什么没有检测到我的碰撞。我的代码有什么问题?

碰撞检查

if (CheckCollisionRecs(playerArea, rect1))

在事件循环之前。

即使在循环内移动它也不会产生任何影响,因为 playerArea 永远不会在您的事件循环中更新。

快速修复是在移动玩家后更新碰撞框。

main 的示例片段,无图像)

Rectangle playerArea;    
Rectangle rect1 = {100, 100, 50, 50};    
    
while (!WindowShouldClose()) {    
    movePlayer();    
        
    playerArea = (Rectangle) {    
        player.pos.x,                
        player.pos.y,                
        player.width,     
        player.height,     
    };    
        
    camera.target = (Vector2){ player.pos.x + 20, player.pos.y + 20 };    
            
    BeginDrawing();    
        ClearBackground(SKYBLUE);    
         
        BeginMode2D(camera);    
        
        DrawRectangleRec(rect1, RED);    
        DrawRectangle(player.pos.x, player.pos.y, player.width, player.height, RAYWHITE);    
    
        EndMode2D();    
            
        if (CheckCollisionRecs(playerArea, rect1))
            DrawText("Collided", 5, 5, 25, BLACK);     
    EndDrawing();    
}