-
Notifications
You must be signed in to change notification settings - Fork 17
spaceship use bitmap #429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
spaceship use bitmap #429
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,8 +8,6 @@ | |
| #include <Service/Sched/Scheduler.h> | ||
| #include <Util/uint_to_str.h> | ||
|
|
||
| #include <algorithm> | ||
|
|
||
| using namespace hitcon::service::sched; | ||
| using hitcon::game::EventType; | ||
|
|
||
|
|
@@ -29,7 +27,7 @@ void SpaceshipApp::Init() { scheduler.Queue(&_routine_task, nullptr); } | |
| // 1. OnEntry: menu -> ready | ||
| void SpaceshipApp::OnEntry() { | ||
| _state = INIT; | ||
| display_set_mode_scroll_text("Ready..."); | ||
| > display_set_mode_scroll_text("Ready..."); | ||
| } | ||
| // 2. OnExit | ||
| void SpaceshipApp::OnExit() { | ||
|
|
@@ -42,8 +40,6 @@ void SpaceshipApp::OnExit() { | |
| void SpaceshipApp::OnButton(button_t button) {} | ||
| // 4. OnEdgeButton | ||
| void SpaceshipApp::OnEdgeButton(button_t button) { | ||
| constexpr int last_row = DISPLAY_WIDTH * (DISPLAY_HEIGHT - 2); | ||
|
|
||
| if ((button & BUTTON_VALUE_MASK) == BUTTON_BACK) { | ||
| badge_controller.BackToMenu(this); | ||
| return; | ||
|
|
@@ -52,15 +48,17 @@ void SpaceshipApp::OnEdgeButton(button_t button) { | |
| if (_state == RUN) { | ||
| switch (button & BUTTON_VALUE_MASK) { | ||
| case BUTTON_DOWN: // move _my_position down | ||
| if (_my_position < last_row) _SyncMyPlane(_my_position + DISPLAY_WIDTH); | ||
| if (_my_position < PLANE_UPPER_BOUND) { | ||
| _SyncMyPlane(_my_position << 1); | ||
| } | ||
| break; | ||
| case BUTTON_UP: // move _my_position up | ||
| if (_my_position > DISPLAY_WIDTH) | ||
| _SyncMyPlane(_my_position - DISPLAY_WIDTH); | ||
| if (_my_position > PLANE_LOWER_BOUND) { | ||
| _SyncMyPlane(_my_position >> 1); | ||
| } | ||
| break; | ||
| case BUTTON_RIGHT: // emit bullet | ||
| _bullets[_num_bullets] = _my_position + 2; | ||
| _num_bullets += 1; | ||
| _bullets[2] |= _my_position; | ||
| break; | ||
| default: | ||
| break; | ||
|
|
@@ -76,14 +74,18 @@ void SpaceshipApp::OnEdgeButton(button_t button) { | |
|
|
||
| void SpaceshipApp::_StartGame() { | ||
| // setup my plane | ||
| _SyncMyPlane(DISPLAY_WIDTH); | ||
| _my_plane[2] = {0}; | ||
| _my_position = 0; | ||
| _SyncMyPlane(PLANE_LOWER_BOUND); | ||
| // setup enemy | ||
| _enemy_position[DISPLAY_WIDTH] = {0}; | ||
| _GenerateEnemy(); | ||
| _has_enemy = true; | ||
| // setup bullets | ||
| _num_bullets = 0; | ||
| // setup score | ||
| _score = 0; | ||
| // setup bullets | ||
| _bullets[DISPLAY_WIDTH] = {0}; | ||
| // setup display | ||
| _frame_buf[DISPLAY_WIDTH] = {0}; | ||
| // setup state | ||
| _state = RUN; | ||
| scheduler.EnablePeriodic(&_routine_task); | ||
|
|
@@ -105,83 +107,76 @@ void SpaceshipApp::Routine(void* unused) { | |
|
|
||
| // render current status | ||
| _Render(); | ||
|
|
||
| // move on | ||
| // ## 1. move all bullets to right | ||
| _MoveBulletsToRight(); | ||
| // ## 2. generate enemy or move enemy to left | ||
| if (_has_enemy) { | ||
| _enemy_position -= 1; | ||
| } else { | ||
| _GenerateEnemy(); | ||
| _has_enemy = true; | ||
| } | ||
| _MoveEnemyToLeft(); | ||
| if (!_has_enemy) _GenerateEnemy(); | ||
| } | ||
|
|
||
| void SpaceshipApp::_SyncMyPlane(uint8_t new_position) { | ||
| if (new_position != _my_position) { | ||
| _my_position = new_position; | ||
| _my_plane[0] = _my_position; | ||
| _my_plane[1] = _my_position + 1; | ||
| _my_plane[2] = _my_position - DISPLAY_WIDTH; | ||
| _my_plane[3] = _my_position + DISPLAY_WIDTH; | ||
| _my_plane[0] = _my_position | _my_position << 1 | _my_position >> 1; | ||
| _my_plane[1] = _my_position; | ||
| } | ||
| } | ||
|
|
||
| void SpaceshipApp::_Render() { | ||
| uint8_t frame_buf[DISPLAY_HEIGHT * DISPLAY_WIDTH] = {0}; | ||
| // ## 1. render plane | ||
| for (uint8_t i = 0; i < 4; i++) { | ||
| frame_buf[_my_plane[i]] = 1; | ||
| } | ||
| // ## 2. render enemy | ||
| frame_buf[_enemy_position] = 1; | ||
| // ## 3. render bullets | ||
| for (uint8_t i = 0; i < _num_bullets; i++) { | ||
| frame_buf[_bullets[i]] = 1; | ||
| for (uint8_t i = 0; i < DISPLAY_WIDTH; i++) { | ||
| _frame_buf[i] = _enemy_position[i] | _bullets[i]; | ||
| if (i < 2) { | ||
| _frame_buf[i] |= _my_plane[i]; | ||
| } | ||
| } | ||
| display_set_mode_fixed(frame_buf); | ||
| display_set_mode_fixed_packed(_frame_buf); | ||
| } | ||
|
|
||
| void SpaceshipApp::_CheckCollision() { | ||
| for (uint8_t i = 0; i < 4; i++) { | ||
| if (_my_plane[i] == _enemy_position) { | ||
| for (uint8_t i = 0; i < 2; i++) { | ||
| if ((_my_plane[i] & _enemy_position[i]) != 0) { | ||
| _state = GAME_OVER; // game over! | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void SpaceshipApp::_UpdateScoreBullets() { | ||
| uint8_t left_bullets = 0; | ||
| for (uint8_t i = 0; i < _num_bullets; i++) { | ||
| if (_bullets[i] == _enemy_position) { | ||
| for (uint8_t i = 0; i < DISPLAY_WIDTH; i++) { | ||
| if ((_bullets[i] & _enemy_position[i]) != 0) { | ||
| _score += 1; | ||
| _bullets[i] &= ~_enemy_position[i]; // remove bullet | ||
| _enemy_position[i] = 0; // remove enemy | ||
| _has_enemy = false; | ||
| // this bullet is used. | ||
| } else { | ||
| _bullets[left_bullets] = _bullets[i]; | ||
| left_bullets += 1; | ||
| break; | ||
| } | ||
| } | ||
| _num_bullets = left_bullets; // update _num_bullets | ||
| } | ||
|
|
||
| void SpaceshipApp::_MoveBulletsToRight() { | ||
| uint8_t left_bullets = 0; | ||
| for (uint8_t i = 0; i < _num_bullets; i++) { | ||
| _bullets[i] += 1; | ||
| if (_bullets[i] % DISPLAY_WIDTH > 0) { // check bullet within region | ||
| _bullets[left_bullets] = _bullets[i]; | ||
| left_bullets += 1; | ||
| } | ||
| // bullets stay in column 2 to column DISPLAY_WIDTH-1 | ||
| for (uint8_t i = DISPLAY_WIDTH - 1; i >= 2; i--) { | ||
| _bullets[i] = _bullets[i - 1]; | ||
| } | ||
| _num_bullets = left_bullets; // update _num_bullets | ||
| } | ||
|
|
||
| void SpaceshipApp::_GenerateEnemy() { | ||
| uint8_t row = g_fast_random_pool.GetRandom() % (DISPLAY_HEIGHT - 2); | ||
| _enemy_position = (row + 2) * DISPLAY_WIDTH - 1; | ||
| _enemy_position[DISPLAY_WIDTH - 1] = 1 << (row + 1); | ||
| _has_enemy = true; | ||
| } | ||
|
|
||
| void SpaceshipApp::_MoveEnemyToLeft() { | ||
| if (!_has_enemy) return; | ||
| _has_enemy = false; | ||
| for (uint8_t i = 0; i < (DISPLAY_WIDTH - 1); i++) { | ||
| _enemy_position[i] = _enemy_position[i + 1]; | ||
| _enemy_position[i + 1] = 0; | ||
| if (_enemy_position[i] > 0) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Best to use != 0 for bitfield checks |
||
| _has_enemy = true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace spaceship | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,26 +16,29 @@ enum state_t { INIT, RUN, GAME_OVER, END }; | |
|
|
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might want to static_assert() on the display height.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can I use instead of using
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason why you need static_assert() is because you used a byte to represent a column, which is 8 pixels currently. Whenever that changes your code will break, and we'll want to warn anyone of that using static_assert(). |
||
| class SpaceshipApp : public App { | ||
| private: | ||
| // interval for bullet and enemy moving | ||
| static constexpr unsigned INTERVAL = 350; | ||
| static_assert(DISPLAY_HEIGHT) static constexpr unsigned INTERVAL = 350; | ||
| static constexpr unsigned PLANE_LOWER_BOUND = 1 << 1; | ||
| static constexpr unsigned PLANE_UPPER_BOUND = 1 << (DISPLAY_HEIGHT - 2); | ||
|
|
||
| PeriodicTask _routine_task; | ||
| uint8_t _my_position = 0; | ||
| uint8_t _my_plane[4]; | ||
| uint8_t _enemy_position; | ||
| uint8_t _my_position; | ||
| uint8_t _my_plane[2]; | ||
| uint8_t _enemy_position[DISPLAY_WIDTH]; | ||
| bool _has_enemy; | ||
| uint32_t _score; | ||
| uint8_t _state; | ||
|
|
||
| // handle bullets | ||
| uint8_t _num_bullets; | ||
| uint8_t _bullets[DISPLAY_HEIGHT * DISPLAY_WIDTH]; // 0: head | ||
| uint8_t _bullets[DISPLAY_WIDTH]; | ||
| // for display | ||
| uint8_t _frame_buf[DISPLAY_WIDTH]; | ||
|
|
||
| void Routine(void* unused); | ||
| void _StartGame(); | ||
| void _GenerateEnemy(); | ||
| void _Render(); | ||
| void _SyncMyPlane(uint8_t new_position); | ||
| void _MoveEnemyToLeft(); | ||
| void _MoveBulletsToRight(); | ||
| void _CheckCollision(); | ||
| void _UpdateScoreBullets(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.