-
Notifications
You must be signed in to change notification settings - Fork 4
/
GameScene.cpp
205 lines (160 loc) · 5.42 KB
/
GameScene.cpp
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <raylib.h>
#include <box2d/box2d.h>
#include <LDtkLoader/Project.hpp>
#include <LDtkLoader/World.hpp>
#include <fmt/core.h>
#include <Constants.hpp>
#include <utils/DebugUtils.hpp>
#include "GameScene.hpp"
#include "../../physics/PhysicsTypes.hpp"
#include "../Scenes.hpp"
#include "./entities/BaseEntity.hpp"
using namespace std;
Player *GameScene::player = nullptr;
b2World *GameScene::world = nullptr;
GameScene::GameScene()
{
player = new Player();
ldtkProject = new ldtk::Project();
ldtkProject->loadFromFile(AppConstants::GetAssetPath("world.ldtk"));
ldtkWorld = &ldtkProject->getWorld();
current_level = -1;
set_selected_level(0);
}
GameScene::~GameScene()
{
delete ldtkProject;
delete ldtkWorld;
delete player;
delete world;
ldtkProject = nullptr;
UnloadTexture(renderedLevelTexture);
UnloadTexture(currentTilesetTexture);
}
void GameScene::draw()
{
ClearBackground(RAYWHITE);
DrawTextureRec(renderedLevelTexture,
{0, 0, (float)renderedLevelTexture.width, (float)-renderedLevelTexture.height},
{0, 0}, WHITE);
player->draw();
// DEBUG stuff
DebugUtils::draw_physics_objects_bounding_boxes(world);
}
Scenes GameScene::update(float dt)
{
const float timeStep = 1.0f / 60.0f;
const int32 velocityIterations = 6;
const int32 positionIterations = 2;
world->Step(timeStep, velocityIterations, positionIterations);
player->update(dt);
return Scenes::NONE;
}
void GameScene::set_selected_level(int lvl)
{
// unload current tileset texture if necessary
if (current_level >= 0)
{
UnloadTexture(currentTilesetTexture);
}
if (world != nullptr)
{
// if we had an old world then delete it and recreate
// a new one for the new level
delete world;
world = nullptr;
}
b2Vec2 gravity(0.0f, 60.0f);
world = new b2World(gravity);
current_level = lvl;
currentLdtkLevel = &ldtkWorld->getLevel(current_level);
DebugUtils::println("----------------------------------------------");
DebugUtils::print("Loaded LDTK map with {} levels in it", ldtkWorld->allLevels().size());
DebugUtils::print("The loaded level is {} and it has {} layers", current_level, currentLdtkLevel->allLayers().size());
for (auto &&layer : currentLdtkLevel->allLayers())
{
DebugUtils::print(" - {}", layer.getName());
}
auto testTileLayerTileset = currentLdtkLevel->getLayer("TileLayer").getTileset();
DebugUtils::println("The path to the tile layer tileset is: {}", testTileLayerTileset.path);
DebugUtils::println("----------------------------------------------");
auto levelSize = currentLdtkLevel->size;
auto renderTexture = LoadRenderTexture(levelSize.x, levelSize.y);
BeginTextureMode(renderTexture);
if (currentLdtkLevel->hasBgImage())
{
DebugUtils::println("Drawing background image");
auto backgroundPath = currentLdtkLevel->getBgImage();
auto backgroundTexture = LoadTexture(AppConstants::GetAssetPath(backgroundPath.path.c_str()).c_str());
SetTextureFilter(backgroundTexture, TEXTURE_FILTER_TRILINEAR);
// Draw texture and repeat it 5x5 times withing the specified rect
// TODO this texture should tile for the whole screen
DrawTextureV(backgroundTexture, {0, 0}, WHITE);
}
// draw all tileset layers
for (auto &&layer : currentLdtkLevel->allLayers())
{
if (layer.hasTileset())
{
currentTilesetTexture = LoadTexture(AppConstants::GetAssetPath(layer.getTileset().path).c_str());
// if it is a tile layer then draw every tile to the frame buffer
for (auto &&tile : layer.allTiles())
{
auto source_pos = tile.getTextureRect();
auto tile_size = float(layer.getTileset().tile_size);
Rectangle source_rect = {
.x = float(source_pos.x),
.y = float(source_pos.y),
.width = tile.flipX ? -tile_size : tile_size,
.height = tile.flipY ? -tile_size : tile_size,
};
Vector2 target_pos = {
(float)tile.getPosition().x,
(float)tile.getPosition().y,
};
DrawTextureRec(currentTilesetTexture, source_rect, target_pos, WHITE);
}
}
}
EndTextureMode();
renderedLevelTexture = renderTexture.texture;
// get entity positions
DebugUtils::println("Entities in level:");
for (auto &&entity : currentLdtkLevel->getLayer("Entities").allEntities())
{
DebugUtils::println(" - {}", entity.getName());
if (entity.getName() == "Player")
{
player->init_for_level(&entity, world);
}
if (entity.getName() == "Portal")
{
float target_lvl = entity.getField<float>("level_destination").value();
DebugUtils::println("Portal goes to level: {}", target_lvl);
}
}
// create solid blocks on level
DebugUtils::println("Loading solid blocks in level:");
for (auto &&entity : currentLdtkLevel->getLayer("PhysicsEntities").allEntities())
{
// box2d width and height start from the center of the box
auto b2width = entity.getSize().x / 2.0f;
auto b2height = entity.getSize().y / 2.0f;
auto centerX = entity.getPosition().x + b2width;
auto centerY = entity.getPosition().y + b2height;
b2BodyDef bodyDef;
bodyDef.userData.pointer = (uintptr_t)PhysicsTypes::SolidBlock.c_str();
bodyDef.position.Set(centerX / GameConstants::PhysicsWorldScale,
centerY / GameConstants::PhysicsWorldScale);
b2Body *body = world->CreateBody(&bodyDef);
b2PolygonShape groundBox;
groundBox.SetAsBox(b2width / GameConstants::PhysicsWorldScale,
b2height / GameConstants::PhysicsWorldScale);
body->CreateFixture(&groundBox, 0.0f);
DebugUtils::println(" - x:{} y:{} width:{} height:{}",
centerX,
centerY,
b2width,
b2height);
}
}