[SDL] SDL Box2D Collision - Box2D 충돌
C, C++ 2024. 1. 30. 12:23 |반응형
충돌을 감지하고 어떤 오브젝트가 충돌했는지 확인해 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
#include <iostream>
#include "SDL.h"
#include "box2d/box2d.h"
int main(int argc, char* argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface* playerSurface = SDL_LoadBMP("player.bmp");
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, playerSurface);
// World 정의
b2Vec2 gravity(0.0f, 9.8f);
b2World world(gravity);
// Player 정의
b2BodyDef playerBodyDef;
playerBodyDef.type = b2_dynamicBody;
playerBodyDef.position.Set(0.0f, 0.0f);
playerBodyDef.linearVelocity = b2Vec2(50.0f, 0.0f);
playerBodyDef.angularVelocity = 0.2f;
b2Body* playerBody = world.CreateBody(&playerBodyDef);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox((float)playerSurface->w / 2, (float)playerSurface->h / 2);
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
fixtureDef.restitution = 0.5f;
playerBody->CreateFixture(&fixtureDef);
// Player 유저 정보
const char* playerName = "Player";
playerBody->GetUserData().pointer = reinterpret_cast<uintptr_t>(playerName);
// Ground 정의
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0.0f, 400.0f);
b2Body* groundBody = world.CreateBody(&groundBodyDef);
b2PolygonShape groundBox;
groundBox.SetAsBox(500.0f, 0.0f);
SDL_Rect groundRect = { 0, 400, 500, 10 };
groundBody->CreateFixture(&groundBox, 0.0f);
// Ground 유저 정보
const char* groundName = "Ground";
groundBody->GetUserData().pointer = reinterpret_cast<uintptr_t>(groundName);
// Wall 정의
b2BodyDef wallBodyDef;
wallBodyDef.position.Set(300.0f, 0.0f);
b2Body* wallBody = world.CreateBody(&wallBodyDef);
b2PolygonShape wallBox;
wallBox.SetAsBox(0.0f, 480.0f);
SDL_Rect wallRect = { 300, 0, 10, 480 };
wallBody->CreateFixture(&wallBox, 0.0f);
// Wall 유저 정보
const char* wallName = "Wall";
wallBody->GetUserData().pointer = reinterpret_cast<uintptr_t>(wallName);
float timeStep = 1.0f / 500.0f;
int velocityIterations = 6;
int positionIterations = 2;
SDL_Event event;
bool quit = false;
while (!quit) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
quit = true;
break;
case SDL_KEYDOWN:
printf("Key pressed: %s\n", SDL_GetKeyName(event.key.keysym.sym));
if (event.key.keysym.sym == SDLK_SPACE) {
playerBody->SetTransform(b2Vec2(0.0f, 0.0f), 0.0f);
playerBody->SetLinearVelocity(b2Vec2(50.0f, 0.0f));
playerBody->SetAngularVelocity(0.2f);
}
if (event.key.keysym.sym == SDLK_ESCAPE)
quit = true;
break;
default:
break;
}
}
world.Step(timeStep, velocityIterations, positionIterations);
for (b2Contact* c = world.GetContactList(); c; c = c->GetNext())
{
if (c->IsTouching()) {
printf("FixtureA: %s\n", (char*)(c->GetFixtureA()->GetBody()->GetUserData().pointer));
printf("FixtureB: %s\n", (char*)(c->GetFixtureB()->GetBody()->GetUserData().pointer));
printf("Count: %d\n", c->GetManifold()->pointCount);
}
//if (c->GetFixtureA()->IsSensor() == false)
//c->GetFixtureA()->SetSensor(true);
}
// A very important point to note if you do this, is that the existence of a contact in these
// lists does not mean that the two fixtures of the contact are actually touching - it only
// means their AABBs are touching. If you want to know if the fixtures themselves are really
// touching you can use c->IsTouching() to check.
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
// Ground 그리기
SDL_SetRenderDrawColor(renderer, 220, 140, 20, SDL_ALPHA_OPAQUE);
SDL_RenderFillRect(renderer, &groundRect);
// Wall 그리기
SDL_SetRenderDrawColor(renderer, 64, 64, 64, SDL_ALPHA_OPAQUE);
SDL_RenderFillRect(renderer, &wallRect);
// Player 그리기
b2Vec2 playerPosition = playerBody->GetPosition();
SDL_Rect destRect = { (int)playerPosition.x - playerSurface->w / 2,
(int)playerPosition.y - playerSurface->h / 2, playerSurface->w, playerSurface->h };
SDL_RendererFlip flip = SDL_FLIP_NONE;
float angle = playerBody->GetAngle() * (180 / (float)M_PI);
SDL_RenderCopyEx(renderer, texture, NULL, &destRect, angle, NULL, flip);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_FreeSurface(playerSurface);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
|
코드를 작성하고 빌드한다.
오브젝트 UserData 설정시 SetUserData()를 사용하면 안된다는 것에 주의한다. (아래 참고 참조)
※ 참고
Box2D Dynamic Module - Contacts
반응형
'C, C++' 카테고리의 다른 글
[SDL] SDL Box2D Add Collision Shape - Box2D 충돌 감지 (1) | 2024.01.30 |
---|---|
[SDL] SDL Box2D DebugDraw - 디버그 드로우 (1) | 2024.01.30 |
[SDL] SDL Box2D - 물리 라이브러리 (0) | 2024.01.27 |
[SDL] SDL OpenCV (1) | 2024.01.27 |
[SDL] SDL Dear ImGui Project - SDL Dear ImGui SDL 프로젝트 (1) | 2024.01.26 |