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();
}
我想知道如何在 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();
}