Skip to content

Commit a622245

Browse files
committed
Add basic menu
1 parent 9901076 commit a622245

File tree

1 file changed

+128
-45
lines changed

1 file changed

+128
-45
lines changed

src/main.c

+128-45
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ void state_init(GameState *s)
112112
s->queueTail = 0;
113113
}
114114

115+
void state_free(GameState *s)
116+
{
117+
free(s->towers);
118+
free(s->enemies);
119+
free(s->queue);
120+
}
121+
115122
void state_reset(GameState *s)
116123
{
117124
s->towerLen = 0;
@@ -249,27 +256,106 @@ typedef enum EditBox
249256
EB_SPACING,
250257
} EditBox;
251258

252-
int main(void)
259+
typedef enum Scene
253260
{
254-
// Initialization
255-
//--------------------------------------------------------------------------------------
256-
const int screenWidth = 800;
257-
const int screenHeight = 450;
261+
SC_MENU,
262+
SC_TURORIAL,
263+
SC_LEVEL_SELECT,
264+
SC_LEVEL,
265+
SC_PLAYGROUND,
266+
} Scene;
258267

268+
const int screenWidth = 800;
269+
const int screenHeight = 450;
270+
Scene scene;
271+
272+
void menu(void);
273+
void playground(GameState *state);
274+
275+
int main(void)
276+
{
259277
InitWindow(screenWidth, screenHeight, "Scale TD");
260278

279+
SetTargetFPS(60);
280+
281+
GameState state;
282+
state_init(&state);
283+
284+
scene = SC_MENU;
285+
286+
while (!WindowShouldClose()) // Detect window close button or ESC key
287+
{
288+
switch (scene)
289+
{
290+
case SC_MENU:
291+
menu();
292+
break;
293+
case SC_PLAYGROUND:
294+
state_reset(&state);
295+
playground(&state);
296+
break;
297+
}
298+
}
299+
300+
state_free(&state);
301+
302+
// De-Initialization
303+
CloseWindow();
304+
305+
return 0;
306+
}
307+
308+
void menu(void)
309+
{
310+
bool sceneChange = false;
311+
312+
// Main game loop
313+
while (!WindowShouldClose() && !sceneChange) // Detect window close button or ESC key
314+
{
315+
BeginDrawing();
316+
317+
ClearBackground(LIGHTGRAY);
318+
319+
int textW = MeasureText("Scale TD", 100);
320+
DrawText("Scale TD", (screenWidth - textW) / 2, 40, 100, BLACK);
321+
322+
GuiSetState(STATE_DISABLED);
323+
int yPos = 300;
324+
if (GuiButton((Rectangle){screenWidth / 2 - 100, yPos, 200, 24}, "Tutorial"))
325+
{
326+
scene = SC_TURORIAL;
327+
sceneChange = true;
328+
}
329+
yPos += 40;
330+
if (GuiButton((Rectangle){screenWidth / 2 - 100, yPos, 200, 24}, "Level select"))
331+
{
332+
scene = SC_LEVEL_SELECT;
333+
sceneChange = true;
334+
}
335+
GuiSetState(STATE_NORMAL);
336+
yPos += 40;
337+
if (GuiButton((Rectangle){screenWidth / 2 - 100, yPos, 200, 24}, "Playground"))
338+
{
339+
scene = SC_PLAYGROUND;
340+
sceneChange = true;
341+
}
342+
yPos += 40;
343+
344+
GuiUnlock();
345+
346+
EndDrawing();
347+
}
348+
}
349+
350+
void playground(GameState *state)
351+
{
261352
Camera2D camera = { 0 };
262353
camera.target = (Vector2){ screenWidth / 2, screenHeight / 2 };
263354
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
264355
camera.rotation = 0.0f;
265356
camera.zoom = 1.0f;
266357

267-
SetTargetFPS(60);
268-
269358
unsigned int frame = -600; // test rollover robustness
270-
271-
GameState state;
272-
state_init(&state);
273359

274360
Rectangle path = {100, 200, screenWidth - 100, TOWER_SIZE};
275361
int currentType = ET_SUB;
@@ -314,7 +400,7 @@ int main(void)
314400

315401
if (IsKeyPressed(KEY_R))
316402
{
317-
state_reset(&state);
403+
state_reset(state);
318404
shotHead = shotTail = 0;
319405
}
320406

@@ -331,16 +417,16 @@ int main(void)
331417
canPlaceTower = !CheckCollisionPointRec(GetMousePosition(), queueButton);
332418
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), (Rectangle){0, 0, screenWidth, 30});
333419
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), path);
334-
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), state.home.rect);
420+
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), state->home.rect);
335421
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), guiArea);
336-
for (int i = 0; i < state.towerLen; ++i) {
337-
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), state.towers[i].rect);
422+
for (int i = 0; i < state->towerLen; ++i) {
423+
canPlaceTower &= !CheckCollisionPointRec(GetMousePosition(), state->towers[i].rect);
338424
}
339425
}
340426

341-
if (IsMouseButtonPressed(0) && state.towerLen < MAX_TOWERS && canPlaceTower && currentType != ET_NONE)
427+
if (IsMouseButtonPressed(0) && state->towerLen < MAX_TOWERS && canPlaceTower && currentType != ET_NONE)
342428
{
343-
state_addTower(&state, tileX, tileY, currentType, currentScale);
429+
state_addTower(state, tileX, tileY, currentType, currentScale);
344430
}
345431

346432
if (paused)
@@ -349,16 +435,16 @@ int main(void)
349435
}
350436

351437
// ------------------ Logic ------------------
352-
for (int i_enemy = 0; i_enemy < state.enemiesLen; ++i_enemy)
438+
for (int i_enemy = 0; i_enemy < state->enemiesLen; ++i_enemy)
353439
{
354-
Enemy *e = state.enemies + i_enemy;
440+
Enemy *e = state->enemies + i_enemy;
355441
if (!e->alive)
356442
continue;
357443

358444
// tower in range -> shoot
359-
for (int i_tower = 0; i_tower < state.towerLen; ++i_tower)
445+
for (int i_tower = 0; i_tower < state->towerLen; ++i_tower)
360446
{
361-
Tower *t = state.towers + i_tower;
447+
Tower *t = state->towers + i_tower;
362448
if (frame - t->lastShot < t->cooldown)
363449
continue;
364450
if (!CheckCollisionCircles(e->pos, ENEMY_SIZE, t->center, t->range))
@@ -387,9 +473,9 @@ int main(void)
387473
}
388474

389475
// touch home -> remove itself + health
390-
if (CheckCollisionPointRec(e->pos, state.home.rect))
476+
if (CheckCollisionPointRec(e->pos, state->home.rect))
391477
{
392-
--state.home.health;
478+
--state->home.health;
393479
e->alive = false;
394480
continue;
395481
}
@@ -409,20 +495,20 @@ int main(void)
409495
--s->shotLife;
410496
}
411497
// spawn new enemies
412-
for (int i_queue = state.queueTail; i_queue != state.queueHead; ++i_queue)
498+
for (int i_queue = state->queueTail; i_queue != state->queueHead; ++i_queue)
413499
{
414-
EnemyQueue e = state.queue[i_queue % QUEUE_SIZE];
500+
EnemyQueue e = state->queue[i_queue % QUEUE_SIZE];
415501
if (e.spawnFrame - frame < frame - e.spawnFrame)
416502
break;
417503

418-
assert(state.enemiesLen < MAX_ENEMIES);
419-
state.enemies[state.enemiesLen++] = (Enemy){
504+
assert(state->enemiesLen < MAX_ENEMIES);
505+
state->enemies[state->enemiesLen++] = (Enemy){
420506
.pos = {screenWidth + 50, screenHeight / 2},
421507
.speed = {-0.5, 0},
422508
.health = e.health,
423509
.alive = true,
424510
};
425-
++state.queueTail;
511+
++state->queueTail;
426512
}
427513

428514
++frame;
@@ -450,10 +536,10 @@ int main(void)
450536
// Towers
451537
char text[64] = "";
452538
int textWidthPixels = 0;
453-
for (int i = 0; i < state.towerLen; ++i) {
539+
for (int i = 0; i < state->towerLen; ++i) {
454540
assert(currentType < ET_EOL);
455541

456-
Tower t = state.towers[i];
542+
Tower t = state->towers[i];
457543
DrawRectangleRec(t.rect, DARKGRAY);
458544
snprintf(text, sizeof(text), SIGNS[t.type], t.scale);
459545
int fontSize = FONT_SIZE;
@@ -471,20 +557,20 @@ int main(void)
471557
}
472558

473559
// Home
474-
DrawRectangleRec(state.home.rect, RED);
475-
snprintf(text, sizeof(text), "%d", state.home.health);
560+
DrawRectangleRec(state->home.rect, RED);
561+
snprintf(text, sizeof(text), "%d", state->home.health);
476562
textWidthPixels = MeasureText(text, FONT_SIZE);
477563
DrawText(text,
478-
state.home.rect.x + (TOWER_SIZE - textWidthPixels) / 2,
479-
state.home.rect.y + (TOWER_SIZE - FONT_SIZE) / 2,
564+
state->home.rect.x + (TOWER_SIZE - textWidthPixels) / 2,
565+
state->home.rect.y + (TOWER_SIZE - FONT_SIZE) / 2,
480566
FONT_SIZE,
481567
BLACK);
482568

483569
// Enemies
484570
int aliveCount = 0;
485-
for (int i = state.enemiesLen-1; i >= 0; --i)
571+
for (int i = state->enemiesLen-1; i >= 0; --i)
486572
{
487-
Enemy e = state.enemies[i];
573+
Enemy e = state->enemies[i];
488574
if (!e.alive)
489575
continue;
490576

@@ -515,8 +601,8 @@ int main(void)
515601
Vector2 varTarget = {rand() % 8 - 4, rand() % 8 - 4};
516602

517603
DrawLineV(
518-
Vector2Add(state.towers[s.tower].center, varTower),
519-
Vector2Add(state.enemies[s.target].pos, varTarget),
604+
Vector2Add(state->towers[s.tower].center, varTower),
605+
Vector2Add(state->enemies[s.target].pos, varTarget),
520606
RED);
521607
}
522608

@@ -578,7 +664,7 @@ int main(void)
578664
assert(count > 0);
579665
assert(spacing > 0);
580666

581-
state_addQueueFromString(&state, frame, healthText, count, spacing);
667+
state_addQueueFromString(state, frame, healthText, count, spacing);
582668
}
583669

584670
int xPos = 4;
@@ -611,13 +697,13 @@ int main(void)
611697
snprintf(text, sizeof(text), "Frame: %u", frame);
612698
DrawText(text, 4, yPos, FONT_SIZE, BLACK);
613699
yPos += 24;
614-
snprintf(text, sizeof(text), "Towers: %d / %d", state.towerLen, MAX_TOWERS);
700+
snprintf(text, sizeof(text), "Towers: %d / %d", state->towerLen, MAX_TOWERS);
615701
DrawText(text, 4, yPos, FONT_SIZE, BLACK);
616702
yPos += 24;
617-
snprintf(text, sizeof(text), "Enemies: %d - (%d / %d)", aliveCount, state.enemiesLen, MAX_ENEMIES);
703+
snprintf(text, sizeof(text), "Enemies: %d - (%d / %d)", aliveCount, state->enemiesLen, MAX_ENEMIES);
618704
DrawText(text, 4, yPos, FONT_SIZE, BLACK);
619705
yPos += 24;
620-
snprintf(text, sizeof(text), "Queue: %d: %d -> %d", state.queueHead - state.queueTail, state.queueTail, state.queueHead);
706+
snprintf(text, sizeof(text), "Queue: %d: %d -> %d", state->queueHead - state->queueTail, state->queueTail, state->queueHead);
621707
DrawText(text, 4, yPos, FONT_SIZE, BLACK);
622708
yPos += 24;
623709
snprintf(text, sizeof(text), "Shots: %d: %d -> %d", shotHead - shotTail, shotTail, shotHead);
@@ -635,8 +721,5 @@ int main(void)
635721
EndDrawing();
636722
}
637723

638-
// De-Initialization
639-
CloseWindow();
640-
641-
return 0;
724+
free(shots);
642725
}

0 commit comments

Comments
 (0)