Skip to content

Commit d01f88e

Browse files
committed
Add Gem Maze tutorial
1 parent a49203f commit d01f88e

28 files changed

Lines changed: 2349 additions & 0 deletions

Tutorials/GemMaze/Definitions.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// ---------------------------------------------------------
2+
// NAMES FOR ALL ASSETS IN THE ROM
3+
// ---------------------------------------------------------
4+
5+
6+
// names for textures
7+
enum Textures
8+
{
9+
TextureGemMaze
10+
};
11+
12+
// ---------------------------------------------------------
13+
14+
// names for sound effects
15+
enum Sounds
16+
{
17+
SoundStart,
18+
SoundCollectRedGem,
19+
SoundCollectBlueGem,
20+
SoundCollectTime,
21+
SoundDeath,
22+
SoundTimeOut,
23+
SoundGoal
24+
};
25+
26+
27+
// ---------------------------------------------------------
28+
// DEFINITIONS FOR GAME LOGIC
29+
// ---------------------------------------------------------
30+
31+
32+
// game is handled as a state machine
33+
enum GameStates
34+
{
35+
StateStart,
36+
StatePlay,
37+
StateDeath,
38+
StateGoal
39+
};
40+
41+
// ---------------------------------------------------------
42+
43+
// the different tiles in our map
44+
enum TileTypes
45+
{
46+
TileEmpty,
47+
TileWall,
48+
TileSpikes,
49+
TileGoal,
50+
TilePlayer,
51+
TileTime,
52+
TileRedGem,
53+
TileBlueGem
54+
};
55+
56+
57+
// ---------------------------------------------------------
58+
// GLOBAL VARIABLES
59+
// ---------------------------------------------------------
60+
61+
62+
// game objects from our libraries
63+
tileset TilesMaze;
64+
tilemap MapMaze;
65+
numberfont FontNumbers;
66+
67+
// ---------------------------------------------------------
68+
69+
// state of our game session
70+
int GameState;
71+
int RemainingTimeFrames;
72+
int CollectedGems;

Tutorials/GemMaze/GameLogic.h

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
// ---------------------------------------------------------
2+
// BASIC FUNCTIONS FOR GAME LOGIC
3+
// ---------------------------------------------------------
4+
5+
6+
void LoadMaze()
7+
{
8+
// make a copy of the original maze,
9+
// so that we can modify it in the game
10+
memcpy( &MazeArray, &OriginalMazeArray, sizeof(OriginalMazeArray) );
11+
12+
// detect the player start position tile
13+
for( int TileY = 0; TileY < MAZE_HEIGHT; ++TileY )
14+
for( int TileX = 0; TileX < MAZE_WIDTH; ++TileX )
15+
if( MazeArray[ TileY ][ TileX ] == TilePlayer )
16+
{
17+
Player_Create( &Player1, TileX, TileY );
18+
MazeArray[ TileY ][ TileX ] = TileEmpty;
19+
return;
20+
}
21+
}
22+
23+
// ---------------------------------------------------------
24+
25+
// set initial state for the whole game
26+
void ResetGameSession()
27+
{
28+
// load the level map
29+
LoadMaze();
30+
31+
// reset the player
32+
Player_Reset( &Player1 );
33+
34+
// set initial game state
35+
GameState = StateStart;
36+
RemainingTimeFrames = 30 * frames_per_second;
37+
CollectedGems = 0;
38+
}
39+
40+
// ---------------------------------------------------------
41+
42+
void ProcessTileUnderPlayer( int TileX, int TileY )
43+
{
44+
int* Tile = &MazeArray[ TileY ][ TileX ];
45+
46+
// collect a red gem
47+
if( *Tile == TileRedGem )
48+
{
49+
*Tile = TileEmpty;
50+
CollectedGems += 1;
51+
play_sound( SoundCollectRedGem );
52+
return;
53+
}
54+
55+
// collect a red gem
56+
if( *Tile == TileBlueGem )
57+
{
58+
*Tile = TileEmpty;
59+
CollectedGems += 5;
60+
play_sound( SoundCollectBlueGem );
61+
return;
62+
}
63+
64+
// collect extra time
65+
if( *Tile == TileTime )
66+
{
67+
*Tile = TileEmpty;
68+
RemainingTimeFrames += 10 * frames_per_second;
69+
play_sound( SoundCollectTime );
70+
return;
71+
}
72+
73+
// arrive at the goal
74+
if( *Tile == TileGoal )
75+
{
76+
play_sound( SoundGoal );
77+
GameState = StateGoal;
78+
return;
79+
}
80+
81+
// die from spikes
82+
if( *Tile == TileSpikes )
83+
{
84+
play_sound( SoundDeath );
85+
GameState = StateDeath;
86+
return;
87+
}
88+
}
89+
90+
// ---------------------------------------------------------
91+
92+
// when the player steps over certain tiles,
93+
// gameplay events will happen; this function
94+
// will process all tiles under the player
95+
void ProcessPlayerPosition()
96+
{
97+
// find all tiles covered by the player
98+
int MinTileX = box_left ( &Player1.Shape ) / TilesMaze.width;
99+
int MaxTileX = box_right ( &Player1.Shape ) / TilesMaze.width;
100+
int MinTileY = box_top ( &Player1.Shape ) / TilesMaze.height;
101+
int MaxTileY = box_bottom( &Player1.Shape ) / TilesMaze.height;
102+
103+
// process all of them
104+
for( int TileY = MinTileY; TileY <= MaxTileY; ++TileY )
105+
for( int TileX = MinTileX; TileX <= MaxTileX; ++TileX )
106+
ProcessTileUnderPlayer( TileX, TileY );
107+
}
108+
109+
110+
// ---------------------------------------------------------
111+
// GAME DRAWING FUNCTIONS
112+
// ---------------------------------------------------------
113+
114+
115+
void DrawGame()
116+
{
117+
// focus camera on the player, but keep
118+
// the map always filling the whole screen
119+
MapMaze.camera_position = Player1.Shape.position;
120+
tilemap_clip_camera_position( &MapMaze );
121+
122+
// draw the map
123+
tilemap_draw_from_camera( &MapMaze );
124+
125+
// draw the player over the map
126+
Player_Draw( &Player1 );
127+
}
128+
129+
// ---------------------------------------------------------
130+
131+
void DrawGUI()
132+
{
133+
select_texture( TextureGemMaze );
134+
135+
// draw frame for collected gems at top-left corner
136+
select_region( RegionGuiGems );
137+
draw_region_at( 0, 0 );
138+
139+
// draw the number of collected gems, always using 2 digits
140+
numberfont_print_int_fixed( &FontNumbers, 51, 6, CollectedGems, 2 );
141+
142+
// draw remaining time at top-right corner
143+
select_region( RegionGuiTime );
144+
draw_region_at( screen_width-1, 0 );
145+
146+
// draw the number of remaining seconds, always using 2 digits
147+
int RemainingSeconds = RemainingTimeFrames / frames_per_second;
148+
numberfont_print_int_fixed( &FontNumbers, 599, 6, RemainingSeconds, 2 );
149+
}
150+
151+
152+
// ---------------------------------------------------------
153+
// GAME UPDATE FUNCTIONS FOR EACH GAME STATE
154+
// ---------------------------------------------------------
155+
156+
157+
void RunState_Start()
158+
{
159+
// draw the scene without GUI
160+
DrawGame();
161+
162+
// darken the screen
163+
clear_screen( make_color_rgba( 0, 0, 0, 128 ) );
164+
165+
// draw the press start text
166+
select_region( RegionTextStart );
167+
draw_region_at( screen_width/2, screen_height/2 );
168+
169+
// init play if start is pressed
170+
if( gamepad_button_start() == 1 )
171+
{
172+
play_sound( SoundStart );
173+
GameState = StatePlay;
174+
}
175+
}
176+
177+
// ---------------------------------------------------------
178+
179+
void RunState_Play()
180+
{
181+
// update player movement
182+
Player_Update( &Player1 );
183+
184+
// check if player steps on special tiles
185+
ProcessPlayerPosition();
186+
187+
// decrease time, and check for time out
188+
RemainingTimeFrames--;
189+
190+
if( RemainingTimeFrames <= 0 )
191+
{
192+
play_sound( SoundTimeOut );
193+
GameState = StateDeath;
194+
}
195+
196+
// draw the scene with GUI
197+
DrawGame();
198+
DrawGUI();
199+
}
200+
201+
// ---------------------------------------------------------
202+
203+
void RunState_Death()
204+
{
205+
// draw the scene with GUI
206+
DrawGame();
207+
DrawGUI();
208+
209+
// darken the screen
210+
clear_screen( make_color_rgba( 64, 0, 0, 128 ) );
211+
212+
// show a death message
213+
select_region( RegionTextDeath );
214+
draw_region_at( screen_width/2, screen_height/2 );
215+
216+
// reset game if start is pressed
217+
if( gamepad_button_start() == 1 )
218+
ResetGameSession();
219+
}
220+
221+
// ---------------------------------------------------------
222+
223+
void RunState_Goal()
224+
{
225+
// draw the scene with GUI
226+
DrawGame();
227+
DrawGUI();
228+
229+
// lighten the screen
230+
clear_screen( make_color_rgba( 200, 255, 255, 128 ) );
231+
232+
// show a clear message
233+
select_region( RegionTextClear );
234+
draw_region_at( screen_width/2, 160 );
235+
236+
// show the number of collected gems, always using 2 digits
237+
numberfont_print_int_fixed( &FontNumbers, 304, 220, CollectedGems, 2 );
238+
239+
// reset game if start is pressed
240+
if( gamepad_button_start() == 1 )
241+
ResetGameSession();
242+
}

0 commit comments

Comments
 (0)