@@ -112,6 +112,13 @@ void state_init(GameState *s)
112
112
s -> queueTail = 0 ;
113
113
}
114
114
115
+ void state_free (GameState * s )
116
+ {
117
+ free (s -> towers );
118
+ free (s -> enemies );
119
+ free (s -> queue );
120
+ }
121
+
115
122
void state_reset (GameState * s )
116
123
{
117
124
s -> towerLen = 0 ;
@@ -249,27 +256,106 @@ typedef enum EditBox
249
256
EB_SPACING ,
250
257
} EditBox ;
251
258
252
- int main ( void )
259
+ typedef enum Scene
253
260
{
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 ;
258
267
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
+ {
259
277
InitWindow (screenWidth , screenHeight , "Scale TD" );
260
278
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
+ {
261
352
Camera2D camera = { 0 };
262
353
camera .target = (Vector2 ){ screenWidth / 2 , screenHeight / 2 };
263
354
camera .offset = (Vector2 ){ screenWidth /2.0f , screenHeight /2.0f };
264
355
camera .rotation = 0.0f ;
265
356
camera .zoom = 1.0f ;
266
357
267
- SetTargetFPS (60 );
268
-
269
358
unsigned int frame = -600 ; // test rollover robustness
270
-
271
- GameState state ;
272
- state_init (& state );
273
359
274
360
Rectangle path = {100 , 200 , screenWidth - 100 , TOWER_SIZE };
275
361
int currentType = ET_SUB ;
@@ -314,7 +400,7 @@ int main(void)
314
400
315
401
if (IsKeyPressed (KEY_R ))
316
402
{
317
- state_reset (& state );
403
+ state_reset (state );
318
404
shotHead = shotTail = 0 ;
319
405
}
320
406
@@ -331,16 +417,16 @@ int main(void)
331
417
canPlaceTower = !CheckCollisionPointRec (GetMousePosition (), queueButton );
332
418
canPlaceTower &= !CheckCollisionPointRec (GetMousePosition (), (Rectangle ){0 , 0 , screenWidth , 30 });
333
419
canPlaceTower &= !CheckCollisionPointRec (GetMousePosition (), path );
334
- canPlaceTower &= !CheckCollisionPointRec (GetMousePosition (), state . home .rect );
420
+ canPlaceTower &= !CheckCollisionPointRec (GetMousePosition (), state -> home .rect );
335
421
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 );
338
424
}
339
425
}
340
426
341
- if (IsMouseButtonPressed (0 ) && state . towerLen < MAX_TOWERS && canPlaceTower && currentType != ET_NONE )
427
+ if (IsMouseButtonPressed (0 ) && state -> towerLen < MAX_TOWERS && canPlaceTower && currentType != ET_NONE )
342
428
{
343
- state_addTower (& state , tileX , tileY , currentType , currentScale );
429
+ state_addTower (state , tileX , tileY , currentType , currentScale );
344
430
}
345
431
346
432
if (paused )
@@ -349,16 +435,16 @@ int main(void)
349
435
}
350
436
351
437
// ------------------ 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 )
353
439
{
354
- Enemy * e = state . enemies + i_enemy ;
440
+ Enemy * e = state -> enemies + i_enemy ;
355
441
if (!e -> alive )
356
442
continue ;
357
443
358
444
// 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 )
360
446
{
361
- Tower * t = state . towers + i_tower ;
447
+ Tower * t = state -> towers + i_tower ;
362
448
if (frame - t -> lastShot < t -> cooldown )
363
449
continue ;
364
450
if (!CheckCollisionCircles (e -> pos , ENEMY_SIZE , t -> center , t -> range ))
@@ -387,9 +473,9 @@ int main(void)
387
473
}
388
474
389
475
// touch home -> remove itself + health
390
- if (CheckCollisionPointRec (e -> pos , state . home .rect ))
476
+ if (CheckCollisionPointRec (e -> pos , state -> home .rect ))
391
477
{
392
- -- state . home .health ;
478
+ -- state -> home .health ;
393
479
e -> alive = false;
394
480
continue ;
395
481
}
@@ -409,20 +495,20 @@ int main(void)
409
495
-- s -> shotLife ;
410
496
}
411
497
// 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 )
413
499
{
414
- EnemyQueue e = state . queue [i_queue % QUEUE_SIZE ];
500
+ EnemyQueue e = state -> queue [i_queue % QUEUE_SIZE ];
415
501
if (e .spawnFrame - frame < frame - e .spawnFrame )
416
502
break ;
417
503
418
- assert (state . enemiesLen < MAX_ENEMIES );
419
- state . enemies [state . enemiesLen ++ ] = (Enemy ){
504
+ assert (state -> enemiesLen < MAX_ENEMIES );
505
+ state -> enemies [state -> enemiesLen ++ ] = (Enemy ){
420
506
.pos = {screenWidth + 50 , screenHeight / 2 },
421
507
.speed = {-0.5 , 0 },
422
508
.health = e .health ,
423
509
.alive = true,
424
510
};
425
- ++ state . queueTail ;
511
+ ++ state -> queueTail ;
426
512
}
427
513
428
514
++ frame ;
@@ -450,10 +536,10 @@ int main(void)
450
536
// Towers
451
537
char text [64 ] = "" ;
452
538
int textWidthPixels = 0 ;
453
- for (int i = 0 ; i < state . towerLen ; ++ i ) {
539
+ for (int i = 0 ; i < state -> towerLen ; ++ i ) {
454
540
assert (currentType < ET_EOL );
455
541
456
- Tower t = state . towers [i ];
542
+ Tower t = state -> towers [i ];
457
543
DrawRectangleRec (t .rect , DARKGRAY );
458
544
snprintf (text , sizeof (text ), SIGNS [t .type ], t .scale );
459
545
int fontSize = FONT_SIZE ;
@@ -471,20 +557,20 @@ int main(void)
471
557
}
472
558
473
559
// 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 );
476
562
textWidthPixels = MeasureText (text , FONT_SIZE );
477
563
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 ,
480
566
FONT_SIZE ,
481
567
BLACK );
482
568
483
569
// Enemies
484
570
int aliveCount = 0 ;
485
- for (int i = state . enemiesLen - 1 ; i >= 0 ; -- i )
571
+ for (int i = state -> enemiesLen - 1 ; i >= 0 ; -- i )
486
572
{
487
- Enemy e = state . enemies [i ];
573
+ Enemy e = state -> enemies [i ];
488
574
if (!e .alive )
489
575
continue ;
490
576
@@ -515,8 +601,8 @@ int main(void)
515
601
Vector2 varTarget = {rand () % 8 - 4 , rand () % 8 - 4 };
516
602
517
603
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 ),
520
606
RED );
521
607
}
522
608
@@ -578,7 +664,7 @@ int main(void)
578
664
assert (count > 0 );
579
665
assert (spacing > 0 );
580
666
581
- state_addQueueFromString (& state , frame , healthText , count , spacing );
667
+ state_addQueueFromString (state , frame , healthText , count , spacing );
582
668
}
583
669
584
670
int xPos = 4 ;
@@ -611,13 +697,13 @@ int main(void)
611
697
snprintf (text , sizeof (text ), "Frame: %u" , frame );
612
698
DrawText (text , 4 , yPos , FONT_SIZE , BLACK );
613
699
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 );
615
701
DrawText (text , 4 , yPos , FONT_SIZE , BLACK );
616
702
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 );
618
704
DrawText (text , 4 , yPos , FONT_SIZE , BLACK );
619
705
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 );
621
707
DrawText (text , 4 , yPos , FONT_SIZE , BLACK );
622
708
yPos += 24 ;
623
709
snprintf (text , sizeof (text ), "Shots: %d: %d -> %d" , shotHead - shotTail , shotTail , shotHead );
@@ -635,8 +721,5 @@ int main(void)
635
721
EndDrawing ();
636
722
}
637
723
638
- // De-Initialization
639
- CloseWindow ();
640
-
641
- return 0 ;
724
+ free (shots );
642
725
}
0 commit comments