Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Engine.cpp
00001 #include "Engine.h" 00002 00003 // Reference for the technique used to generate random numbers. 00004 // [1] "rand" cplusplus. [Online] Available: 00005 // http://www.cplusplus.com/reference/cstdlib/rand/ [Accessed: 22 April 2019]. 00006 00007 // Buffer to print updated score. 00008 char buffer[14]; 00009 00010 // Constructor and destructor. 00011 Engine::Engine() {} 00012 00013 Engine::~Engine() {} 00014 00015 void Engine::init() { 00016 // Reset functions are used for init. 00017 reset_skater(); 00018 reset_engine(); 00019 srand(time(NULL)); // Set up for generating random numbers, [1]. 00020 } 00021 00022 void Engine::check_reset(N5110 &lcd, Gamepad &gamepad) { 00023 // If reset flag is true, end and restart the game. 00024 if (_skater.get_reset_flag()) { 00025 gamepad.leds_on(); 00026 execute_dying_sequence(lcd, gamepad); 00027 wait(1); // Short pause. 00028 reset_skater(); 00029 reset_engine(); 00030 } 00031 } 00032 00033 void Engine::execute_dying_sequence(N5110 &lcd, Gamepad &gamepad) { 00034 // Player has died and game needs to restart, printing their score. 00035 wait(1); // Short pause. 00036 gamepad.leds_off(); 00037 lcd.clear(); 00038 for (int i = 0; i < 40; i = i + 8) { // Counter for y direction, sweeps top 00039 // to bottom. 00040 for (int j = 0; j < 84; j++) { // Counter for x direction, sweeps L to R. 00041 lcd.setPixel(j,i,true); 00042 lcd.setPixel(i,j,true); 00043 lcd.printString("TRY AGAIN",30,5); 00044 lcd.refresh(); 00045 gamepad.tone(int(1099 - 15.4*j - 1.2*i), 0.05); // Frequency of tone is 00046 // dependent on counters. 00047 wait(0.001); // Control speed of the sequence. 00048 sprintf(buffer,"%2d",_player_score); 00049 lcd.printString(buffer,0,5); 00050 } 00051 } 00052 } 00053 00054 void Engine::reset_skater() { 00055 // Initial values for skater. 00056 _skater_direction = Left; 00057 _start_platform_flag = true; // For printing start text in EngineController. 00058 _skater.set_reset_flag(false); 00059 _moving_counter = 0; 00060 _jump_counter = 20; // Start game falling onto the platform. 00061 _fall_flag = false; 00062 } 00063 00064 void Engine::reset_engine() { 00065 // Inital values for engine (and gamepad input). 00066 _input.coord.x = 0; 00067 _input.coord.y = 0; 00068 _input.A_flag = false; 00069 _lower_platforms.init(40); // 40 is the platform y coord. 00070 _upper_platforms.init(22); // 22 is the platform y coord. 00071 _coin.init(); 00072 _fire.init(); 00073 _coin_collision_flag = false; 00074 _player_score = 0; 00075 _fire_height = 0; 00076 } 00077 00078 void Engine::read_input(Gamepad &gamepad) { 00079 // Set up the input struct for use. 00080 _input.coord = gamepad.get_mapped_coord(); 00081 _input.A_flag = gamepad.check_event(Gamepad::A_PRESSED); 00082 } 00083 00084 void Engine::process_y(Gamepad &gamepad) { 00085 // Sets the y coord by first checking if the skater should be falling. 00086 set_fall_flag(); // Update the fall flag dependent on skater position. 00087 if (_fall_flag) { 00088 _skater.fall(_fall_flag, gamepad); // Fall if the skater should be. 00089 } else { 00090 _skater.set_y_position(_input.A_flag, _jump_counter, _level_condition, 00091 gamepad); 00092 } 00093 _fall_flag = _skater.get_fall_flag(); // Update fall flag. 00094 _skater_y = _skater.get_y_position(); 00095 _jump_counter = _skater.get_jump_counter(); // Update jump counter. 00096 } 00097 00098 void Engine::set_fall_flag() { 00099 // Set the fall flag to true if the skater is not on one of the lower 00100 // platforms. The start platform condition has been offset by 6 to account for 00101 // skater sprite size. 00102 // If the skater is between platform 1 and 2, and on the lower level. 00103 if (((_lower_line_1.x_end < _skater_x) 00104 && (_skater_x < (_lower_line_2.x_start - 6))) 00105 && _skater_y == 23) { 00106 _fall_flag = true; 00107 // If the skater is between platforms 2 and 3, and on the lower level. 00108 } else if (((_lower_line_2.x_end < _skater_x) 00109 && (_skater_x < (_lower_line_3.x_start - 6))) 00110 && _skater_y == 23) { 00111 _fall_flag = true; 00112 // If the skater is between platforms 3 and 1, and on the lower level. 00113 } else if (((_lower_line_3.x_end < _skater_x) 00114 && (_skater_x < (_lower_line_1.x_start - 6))) 00115 && _skater_y == 23) { 00116 _fall_flag = true; 00117 } 00118 } 00119 00120 void Engine::process_x(int game_counter) { 00121 // Sets the x coord from input. 00122 _skater.set_x_position_and_sprite(_input.coord.x, 00123 _moving_counter, 00124 _skater_direction, 00125 _input.coord.y); 00126 _skater_x = _skater.get_x_position(); 00127 _moving_counter = _skater.get_moving_counter(); // Update moving counter. 00128 _speed_divider = int(-0.05*_player_score + 4); // Speed divider is calculated 00129 // from player score. 00130 // Move the skater along with platforms at rate determined by speed divider if 00131 // the skater is not moving left. 00132 if ((game_counter % _speed_divider == 0) && (_input.coord.x > -0.1)) { 00133 _moving_counter--; 00134 } 00135 } 00136 00137 void Engine::process_sprite() { 00138 // Update the sprite and direction. 00139 _skater_sprite = _skater.get_sprite_value(); 00140 _skater_direction = _skater.get_direction(); 00141 } 00142 00143 00144 void Engine::set_level_condition() { 00145 // If the skater is under or on top of any of the upper platforms, set 00146 // level condition to 1. 00147 // Offset of 6 is to account for sprite size. 00148 // If the skater is between start and end of upper platform 1. 00149 if (((_upper_line_1.x_start - 6) <= _skater_x) 00150 && (_skater_x <= _upper_line_1.x_end)) { 00151 _level_condition = 1; 00152 // If the skater is between start and end of upper platform 2. 00153 } else if (((_upper_line_2.x_start - 6) <= _skater_x) 00154 && (_skater_x <= _upper_line_2.x_end)) { 00155 _level_condition = 1; 00156 // If the skater is between start and end of upper platform 3. 00157 } else if (((_upper_line_3.x_start - 6) <= _skater_x) 00158 && (_skater_x <= _upper_line_3.x_end)) { 00159 _level_condition = 1; 00160 } else { 00161 _level_condition = 0; 00162 } 00163 } 00164 00165 void Engine::generate_level(int game_counter) { 00166 // Generate properties for the level. 00167 generate_lower_lines(); 00168 generate_upper_lines(); 00169 _coin.generate_coin(); 00170 generate_fire(game_counter); 00171 } 00172 00173 void Engine::draw_screen_fire(int game_counter, N5110 &lcd) { 00174 // Prints the dynamic fire at the bottom of the screen. 00175 // Restricts the max fire height multiplier, which is dependent on player 00176 // score. Fire will start when score = 3. 00177 if (_player_score < 15) { 00178 _fire_height = _player_score; 00179 } else { 00180 _fire_height = 14; 00181 } 00182 // i corresponds to horizontal positions of pixels. 00183 for (int i = 1; i < 84; i++) { 00184 if (i % 4 == 0) { 00185 // j corresponds to vertical height of pixels, and the max height is 00186 // dependent on game counter (0 to 99) so changes every loop, and is 00187 // scaled. 00188 for (int j = 0; j < game_counter*0.01*_fire_height; j++) { 00189 lcd.setPixel(i + (rand() % 8 + 1) ,50 - j*1.3,true); // Horizontal 00190 // position of pixel is constrained random [1], multiplier on j varies 00191 // local height. 00192 lcd.setPixel(i - (rand() % 8 + 1) ,50 - j*1.2,true); // [1]. 00193 lcd.setPixel(i - (rand() % 8 + 1) ,50 - j*1.6,true); // [1]. 00194 lcd.setPixel(i + (rand() % 8 + 1) ,50 - j*1.1,true); // [1]. 00195 lcd.setPixel(i - (rand() % 8 + 1) ,50 - j*1.4,true); // [1]. 00196 } 00197 } 00198 } 00199 } 00200 00201 void Engine::generate_lower_lines() { 00202 // Use a scaled random number to generate the length of the lower lines. 00203 _length_1 = (rand() %20) + 10; // [1]. 00204 _lower_platforms.set_line_1(_length_1); 00205 _lower_line_1 = _lower_platforms.get_line_1(); 00206 _length_2 = (rand() %20) + 10; // [1]. 00207 _lower_platforms.set_line_2(_length_2); 00208 _lower_line_2 = _lower_platforms.get_line_2(); 00209 _length_3 = (rand() %20) + 10; // [1]. 00210 _lower_platforms.set_line_3(_length_3); 00211 _lower_line_3 = _lower_platforms.get_line_3(); 00212 } 00213 00214 void Engine::generate_upper_lines() { 00215 // Set the length of the upper lines to be proportionally smaller to 00216 // the length of the lower lines. 00217 _upper_platforms.set_line_1(_length_1 / 2); 00218 _upper_line_1 = _upper_platforms.get_line_1(); 00219 _upper_platforms.set_line_2(_length_2 / 2); 00220 _upper_line_2 = _upper_platforms.get_line_2(); 00221 _upper_platforms.set_line_3(_length_3 / 2); 00222 _upper_line_3 = _upper_platforms.get_line_3(); 00223 } 00224 00225 void Engine::generate_fire(int game_counter) { 00226 // Generates the x and y coordinate of the fire. Y oscillates from 5 to 23. 00227 _fire.generate_fire(); // Generates X coord of fire. 00228 // Y is calculated from parabolic relation to game counter. 00229 _fire_y = int(-0.0073*game_counter*game_counter + 0.73*game_counter + 5); 00230 } 00231 00232 void Engine::update_lcd(N5110 &lcd, int game_counter){ 00233 // Draw all sprites, screen fire, platforms and player score. 00234 lcd.drawSprite(_skater_x,_skater_y,17,10, 00235 (int *)_skater.get_sprite(_skater_sprite)); 00236 lcd.drawSprite(_coin.get_coin_x(),_coin.get_coin_y(),5,5, 00237 (int*)_coin.get_coin_sprite()); 00238 lcd.drawSprite(_fire.get_fire_x(),_fire_y,5,8,(int*)_fire.get_fire_sprite()); 00239 lcd.drawLine(_lower_line_2.x_start,_lower_line_2.y,_lower_line_2.x_end, 00240 _lower_line_2.y,FILL_BLACK); 00241 lcd.drawLine(_lower_line_1.x_start,_lower_line_1.y,_lower_line_1.x_end, 00242 _lower_line_1.y,FILL_BLACK); 00243 lcd.drawLine(_lower_line_3.x_start,_lower_line_3.y,_lower_line_3.x_end, 00244 _lower_line_3.y,FILL_BLACK); 00245 lcd.drawLine(_upper_line_2.x_start,_upper_line_2.y,_upper_line_2.x_end, 00246 _upper_line_2.y,FILL_BLACK); 00247 lcd.drawLine(_upper_line_1.x_start,_upper_line_1.y,_upper_line_1.x_end, 00248 _upper_line_1.y,FILL_BLACK); 00249 lcd.drawLine(_upper_line_3.x_start,_upper_line_3.y,_upper_line_3.x_end, 00250 _upper_line_3.y,FILL_BLACK); 00251 // Print the score. 00252 sprintf(buffer,"%2d",_player_score); 00253 lcd.printString(buffer,0,0); 00254 draw_screen_fire(game_counter, lcd); 00255 } 00256 00257 bool Engine::get_start_platform_flag() { 00258 if (_input.A_flag) _start_platform_flag = false; // Makes starting platform 00259 // vanish after first jump of the game. 00260 return _start_platform_flag; 00261 } 00262 00263 void Engine::check_coin_collision(Gamepad &gamepad) { 00264 // If skater x and y coord matches the coin's. Small adjustment for Y coord 00265 // compensates for skater sprite size. 00266 if (_skater_x == _coin.get_coin_x() 00267 && (_skater_y == _coin.get_coin_y() - 10)) { 00268 _coin_collision_flag = true; 00269 _player_score++; 00270 _coin.set_coin((rand() % 100),(abs(rand() % 100 - 20))); // Place coin 00271 // on a constrained random position, [1]. 00272 gamepad.tone(1500, 0.05); // Make collection noise on buzzer. 00273 wait(0.05); 00274 gamepad.tone(3000, 0.05); 00275 } 00276 } 00277 00278 void Engine::check_fire_collision(Gamepad &gamepad, int game_counter) { 00279 // If skater is not ducking, has same x coord and within a range of y coord 00280 // as fire. 00281 if (_input.coord.y > -0.1 00282 && _skater_x == _fire.get_fire_x() 00283 && _skater_y > _fire_y - 10 00284 && _skater_y < _fire_y + 10 00285 ) { // A range of Y coords to make collision 00286 // more frequent. 00287 _skater.set_reset_flag(true); 00288 gamepad.tone(400, 0.25); // Make collision noise on buzzer. 00289 wait(0.05); 00290 gamepad.tone(200, 0.25); 00291 } else if ( _skater_x < -10 || _skater_x > 84 ) { // If skater goes off the 00292 // screen. 00293 _skater.set_reset_flag(true); 00294 gamepad.tone(200, 0.5); 00295 } 00296 // If the skater collides with the scaled peak of the background fire. 00297 if (_skater_y > (50 - game_counter*_fire_height*0.023)) { 00298 _fall_flag = true; 00299 wait(0.05); // Slow down falling sequence. 00300 } 00301 } 00302 00303 int Engine::get_player_score() { 00304 return _player_score; 00305 } 00306
Generated on Mon Jul 18 2022 14:06:02 by
1.7.2