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/Engine.cpp
- Committer:
- lewisgw
- Date:
- 2019-05-07
- Revision:
- 29:bdc4138b5171
- Parent:
- 28:be77ad6c0bda
File content as of revision 29:bdc4138b5171:
#include "Engine.h" // Reference for the technique used to generate random numbers. // [1] "rand" cplusplus. [Online] Available: // http://www.cplusplus.com/reference/cstdlib/rand/ [Accessed: 22 April 2019]. // Buffer to print updated score. char buffer[14]; // Constructor and destructor. Engine::Engine() {} Engine::~Engine() {} void Engine::init() { // Reset functions are used for init. reset_skater(); reset_engine(); srand(time(NULL)); // Set up for generating random numbers, [1]. } void Engine::check_reset(N5110 &lcd, Gamepad &gamepad) { // If reset flag is true, end and restart the game. if (_skater.get_reset_flag()) { gamepad.leds_on(); execute_dying_sequence(lcd, gamepad); wait(1); // Short pause. reset_skater(); reset_engine(); } } void Engine::execute_dying_sequence(N5110 &lcd, Gamepad &gamepad) { // Player has died and game needs to restart, printing their score. wait(1); // Short pause. gamepad.leds_off(); lcd.clear(); for (int i = 0; i < 40; i = i + 8) { // Counter for y direction, sweeps top // to bottom. for (int j = 0; j < 84; j++) { // Counter for x direction, sweeps L to R. lcd.setPixel(j,i,true); lcd.setPixel(i,j,true); lcd.printString("TRY AGAIN",30,5); lcd.refresh(); gamepad.tone(int(1099 - 15.4*j - 1.2*i), 0.05); // Frequency of tone is // dependent on counters. wait(0.001); // Control speed of the sequence. sprintf(buffer,"%2d",_player_score); lcd.printString(buffer,0,5); } } } void Engine::reset_skater() { // Initial values for skater. _skater_direction = Left; _start_platform_flag = true; // For printing start text in EngineController. _skater.set_reset_flag(false); _moving_counter = 0; _jump_counter = 20; // Start game falling onto the platform. _fall_flag = false; } void Engine::reset_engine() { // Inital values for engine (and gamepad input). _input.coord.x = 0; _input.coord.y = 0; _input.A_flag = false; _lower_platforms.init(40); // 40 is the platform y coord. _upper_platforms.init(22); // 22 is the platform y coord. _coin.init(); _fire.init(); _coin_collision_flag = false; _player_score = 0; _fire_height = 0; } void Engine::read_input(Gamepad &gamepad) { // Set up the input struct for use. _input.coord = gamepad.get_mapped_coord(); _input.A_flag = gamepad.check_event(Gamepad::A_PRESSED); } void Engine::process_y(Gamepad &gamepad) { // Sets the y coord by first checking if the skater should be falling. set_fall_flag(); // Update the fall flag dependent on skater position. if (_fall_flag) { _skater.fall(_fall_flag, gamepad); // Fall if the skater should be. } else { _skater.set_y_position(_input.A_flag, _jump_counter, _level_condition, gamepad); } _fall_flag = _skater.get_fall_flag(); // Update fall flag. _skater_y = _skater.get_y_position(); _jump_counter = _skater.get_jump_counter(); // Update jump counter. } void Engine::set_fall_flag() { // Set the fall flag to true if the skater is not on one of the lower // platforms. The start platform condition has been offset by 6 to account for // skater sprite size. // If the skater is between platform 1 and 2, and on the lower level. if (((_lower_line_1.x_end < _skater_x) && (_skater_x < (_lower_line_2.x_start - 6))) && _skater_y == 23) { _fall_flag = true; // If the skater is between platforms 2 and 3, and on the lower level. } else if (((_lower_line_2.x_end < _skater_x) && (_skater_x < (_lower_line_3.x_start - 6))) && _skater_y == 23) { _fall_flag = true; // If the skater is between platforms 3 and 1, and on the lower level. } else if (((_lower_line_3.x_end < _skater_x) && (_skater_x < (_lower_line_1.x_start - 6))) && _skater_y == 23) { _fall_flag = true; } } void Engine::process_x(int game_counter) { // Sets the x coord from input. _skater.set_x_position_and_sprite(_input.coord.x, _moving_counter, _skater_direction, _input.coord.y); _skater_x = _skater.get_x_position(); _moving_counter = _skater.get_moving_counter(); // Update moving counter. _speed_divider = int(-0.05*_player_score + 4); // Speed divider is calculated // from player score. // Move the skater along with platforms at rate determined by speed divider if // the skater is not moving left. if ((game_counter % _speed_divider == 0) && (_input.coord.x > -0.1)) { _moving_counter--; } } void Engine::process_sprite() { // Update the sprite and direction. _skater_sprite = _skater.get_sprite_value(); _skater_direction = _skater.get_direction(); } void Engine::set_level_condition() { // If the skater is under or on top of any of the upper platforms, set // level condition to 1. // Offset of 6 is to account for sprite size. // If the skater is between start and end of upper platform 1. if (((_upper_line_1.x_start - 6) <= _skater_x) && (_skater_x <= _upper_line_1.x_end)) { _level_condition = 1; // If the skater is between start and end of upper platform 2. } else if (((_upper_line_2.x_start - 6) <= _skater_x) && (_skater_x <= _upper_line_2.x_end)) { _level_condition = 1; // If the skater is between start and end of upper platform 3. } else if (((_upper_line_3.x_start - 6) <= _skater_x) && (_skater_x <= _upper_line_3.x_end)) { _level_condition = 1; } else { _level_condition = 0; } } void Engine::generate_level(int game_counter) { // Generate properties for the level. generate_lower_lines(); generate_upper_lines(); _coin.generate_coin(); generate_fire(game_counter); } void Engine::draw_screen_fire(int game_counter, N5110 &lcd) { // Prints the dynamic fire at the bottom of the screen. // Restricts the max fire height multiplier, which is dependent on player // score. Fire will start when score = 3. if (_player_score < 15) { _fire_height = _player_score; } else { _fire_height = 14; } // i corresponds to horizontal positions of pixels. for (int i = 1; i < 84; i++) { if (i % 4 == 0) { // j corresponds to vertical height of pixels, and the max height is // dependent on game counter (0 to 99) so changes every loop, and is // scaled. for (int j = 0; j < game_counter*0.01*_fire_height; j++) { lcd.setPixel(i + (rand() % 8 + 1) ,50 - j*1.3,true); // Horizontal // position of pixel is constrained random [1], multiplier on j varies // local height. lcd.setPixel(i - (rand() % 8 + 1) ,50 - j*1.2,true); // [1]. lcd.setPixel(i - (rand() % 8 + 1) ,50 - j*1.6,true); // [1]. lcd.setPixel(i + (rand() % 8 + 1) ,50 - j*1.1,true); // [1]. lcd.setPixel(i - (rand() % 8 + 1) ,50 - j*1.4,true); // [1]. } } } } void Engine::generate_lower_lines() { // Use a scaled random number to generate the length of the lower lines. _length_1 = (rand() %20) + 10; // [1]. _lower_platforms.set_line_1(_length_1); _lower_line_1 = _lower_platforms.get_line_1(); _length_2 = (rand() %20) + 10; // [1]. _lower_platforms.set_line_2(_length_2); _lower_line_2 = _lower_platforms.get_line_2(); _length_3 = (rand() %20) + 10; // [1]. _lower_platforms.set_line_3(_length_3); _lower_line_3 = _lower_platforms.get_line_3(); } void Engine::generate_upper_lines() { // Set the length of the upper lines to be proportionally smaller to // the length of the lower lines. _upper_platforms.set_line_1(_length_1 / 2); _upper_line_1 = _upper_platforms.get_line_1(); _upper_platforms.set_line_2(_length_2 / 2); _upper_line_2 = _upper_platforms.get_line_2(); _upper_platforms.set_line_3(_length_3 / 2); _upper_line_3 = _upper_platforms.get_line_3(); } void Engine::generate_fire(int game_counter) { // Generates the x and y coordinate of the fire. Y oscillates from 5 to 23. _fire.generate_fire(); // Generates X coord of fire. // Y is calculated from parabolic relation to game counter. _fire_y = int(-0.0073*game_counter*game_counter + 0.73*game_counter + 5); } void Engine::update_lcd(N5110 &lcd, int game_counter){ // Draw all sprites, screen fire, platforms and player score. lcd.drawSprite(_skater_x,_skater_y,17,10, (int *)_skater.get_sprite(_skater_sprite)); lcd.drawSprite(_coin.get_coin_x(),_coin.get_coin_y(),5,5, (int*)_coin.get_coin_sprite()); lcd.drawSprite(_fire.get_fire_x(),_fire_y,5,8,(int*)_fire.get_fire_sprite()); lcd.drawLine(_lower_line_2.x_start,_lower_line_2.y,_lower_line_2.x_end, _lower_line_2.y,FILL_BLACK); lcd.drawLine(_lower_line_1.x_start,_lower_line_1.y,_lower_line_1.x_end, _lower_line_1.y,FILL_BLACK); lcd.drawLine(_lower_line_3.x_start,_lower_line_3.y,_lower_line_3.x_end, _lower_line_3.y,FILL_BLACK); lcd.drawLine(_upper_line_2.x_start,_upper_line_2.y,_upper_line_2.x_end, _upper_line_2.y,FILL_BLACK); lcd.drawLine(_upper_line_1.x_start,_upper_line_1.y,_upper_line_1.x_end, _upper_line_1.y,FILL_BLACK); lcd.drawLine(_upper_line_3.x_start,_upper_line_3.y,_upper_line_3.x_end, _upper_line_3.y,FILL_BLACK); // Print the score. sprintf(buffer,"%2d",_player_score); lcd.printString(buffer,0,0); draw_screen_fire(game_counter, lcd); } bool Engine::get_start_platform_flag() { if (_input.A_flag) _start_platform_flag = false; // Makes starting platform // vanish after first jump of the game. return _start_platform_flag; } void Engine::check_coin_collision(Gamepad &gamepad) { // If skater x and y coord matches the coin's. Small adjustment for Y coord // compensates for skater sprite size. if (_skater_x == _coin.get_coin_x() && (_skater_y == _coin.get_coin_y() - 10)) { _coin_collision_flag = true; _player_score++; _coin.set_coin((rand() % 100),(abs(rand() % 100 - 20))); // Place coin // on a constrained random position, [1]. gamepad.tone(1500, 0.05); // Make collection noise on buzzer. wait(0.05); gamepad.tone(3000, 0.05); } } void Engine::check_fire_collision(Gamepad &gamepad, int game_counter) { // If skater is not ducking, has same x coord and within a range of y coord // as fire. if (_input.coord.y > -0.1 && _skater_x == _fire.get_fire_x() && _skater_y > _fire_y - 10 && _skater_y < _fire_y + 10 ) { // A range of Y coords to make collision // more frequent. _skater.set_reset_flag(true); gamepad.tone(400, 0.25); // Make collision noise on buzzer. wait(0.05); gamepad.tone(200, 0.25); } else if ( _skater_x < -10 || _skater_x > 84 ) { // If skater goes off the // screen. _skater.set_reset_flag(true); gamepad.tone(200, 0.5); } // If the skater collides with the scaled peak of the background fire. if (_skater_y > (50 - game_counter*_fire_height*0.023)) { _fall_flag = true; wait(0.05); // Slow down falling sequence. } } int Engine::get_player_score() { return _player_score; }