Use shared memory space for game data (#14727)

This commit is contained in:
Marcio Teixeira
2019-07-28 00:44:16 -06:00
committed by Scott Lahteine
parent 17abb94532
commit fec52e61ea
11 changed files with 458 additions and 287 deletions

View File

@@ -28,8 +28,6 @@
#define BRICK_H 5
#define BRICK_TOP MENU_FONT_ASCENT
#define BRICK_ROWS 4
#define BRICK_COLS 16
#define PADDLE_H 2
#define PADDLE_VEL 3
@@ -42,51 +40,47 @@
#define BRICK_COL(X) ((X) / (BRICK_W))
#define BRICK_ROW(Y) ((Y - (BRICK_TOP)) / (BRICK_H))
uint8_t balls_left, brick_count;
uint16_t bricks[BRICK_ROWS];
brickout_data_t &bdat = marlin_game_data.brickout;
inline void reset_bricks(const uint16_t v) {
brick_count = (BRICK_COLS) * (BRICK_ROWS);
LOOP_L_N(i, BRICK_ROWS) bricks[i] = v;
bdat.brick_count = (BRICK_COLS) * (BRICK_ROWS);
LOOP_L_N(i, BRICK_ROWS) bdat.bricks[i] = v;
}
int8_t paddle_x, hit_dir;
fixed_t ballx, bally, ballh, ballv;
void reset_ball() {
constexpr uint8_t ball_dist = 24;
bally = BTOF(PADDLE_Y - ball_dist);
ballv = FTOP(1.3f);
ballh = -FTOP(1.25f);
uint8_t bx = paddle_x + (PADDLE_W) / 2 + ball_dist;
if (bx >= LCD_PIXEL_WIDTH - 10) { bx -= ball_dist * 2; ballh = -ballh; }
ballx = BTOF(bx);
hit_dir = -1;
bdat.bally = BTOF(PADDLE_Y - ball_dist);
bdat.ballv = FTOP(1.3f);
bdat.ballh = -FTOP(1.25f);
uint8_t bx = bdat.paddle_x + (PADDLE_W) / 2 + ball_dist;
if (bx >= LCD_PIXEL_WIDTH - 10) { bx -= ball_dist * 2; bdat.ballh = -bdat.ballh; }
bdat.ballx = BTOF(bx);
bdat.hit_dir = -1;
}
void BrickoutGame::game_screen() {
if (game_frame()) { // Run logic twice for finer resolution
// Update Paddle Position
paddle_x = constrain(int8_t(ui.encoderPosition), 0, (LCD_PIXEL_WIDTH - (PADDLE_W)) / (PADDLE_VEL));
ui.encoderPosition = paddle_x;
paddle_x *= (PADDLE_VEL);
bdat.paddle_x = constrain(int8_t(ui.encoderPosition), 0, (LCD_PIXEL_WIDTH - (PADDLE_W)) / (PADDLE_VEL));
ui.encoderPosition = bdat.paddle_x;
bdat.paddle_x *= (PADDLE_VEL);
// Run the ball logic
if (game_state) do {
// Provisionally update the ball position
const fixed_t newx = ballx + ballh, newy = bally + ballv; // current next position
const fixed_t newx = bdat.ballx + bdat.ballh, newy = bdat.bally + bdat.ballv; // current next position
if (!WITHIN(newx, 0, BTOF(LCD_PIXEL_WIDTH - 1))) { // out in x?
ballh = -ballh; _BUZZ(5, 220); // bounce x
bdat.ballh = -bdat.ballh; _BUZZ(5, 220); // bounce x
}
if (newy < 0) { // out in y?
ballv = -ballv; _BUZZ(5, 280); // bounce v
hit_dir = 1;
bdat.ballv = -bdat.ballv; _BUZZ(5, 280); // bounce v
bdat.hit_dir = 1;
}
// Did the ball go below the bottom?
else if (newy > BTOF(LCD_PIXEL_HEIGHT)) {
BUZZ(500, 75);
if (--balls_left) reset_ball(); else game_state = 0;
if (--bdat.balls_left) reset_ball(); else game_state = 0;
break; // done
}
@@ -94,42 +88,42 @@ void BrickoutGame::game_screen() {
if (WITHIN(newy, BTOF(BRICK_TOP), BTOF(BRICK_BOT))) {
const int8_t bit = BRICK_COL(FTOB(newx)), row = BRICK_ROW(FTOB(newy));
const uint16_t mask = _BV(bit);
if (bricks[row] & mask) {
if (bdat.bricks[row] & mask) {
// Yes. Remove it!
bricks[row] &= ~mask;
bdat.bricks[row] &= ~mask;
// Score!
score += BRICK_ROWS - row;
// If bricks are gone, go to reset state
if (!--brick_count) game_state = 2;
if (!--bdat.brick_count) game_state = 2;
// Bounce the ball cleverly
if ((ballv < 0) == (hit_dir < 0)) { ballv = -ballv; ballh += fixed_t(random(-16, 16)); _BUZZ(5, 880); }
else { ballh = -ballh; ballv += fixed_t(random(-16, 16)); _BUZZ(5, 640); }
if ((bdat.ballv < 0) == (bdat.hit_dir < 0)) { bdat.ballv = -bdat.ballv; bdat.ballh += fixed_t(random(-16, 16)); _BUZZ(5, 880); }
else { bdat.ballh = -bdat.ballh; bdat.ballv += fixed_t(random(-16, 16)); _BUZZ(5, 640); }
}
}
// Is the ball moving down and in paddle range?
else if (ballv > 0 && WITHIN(newy, BTOF(PADDLE_Y), BTOF(PADDLE_Y + PADDLE_H))) {
else if (bdat.ballv > 0 && WITHIN(newy, BTOF(PADDLE_Y), BTOF(PADDLE_Y + PADDLE_H))) {
// Ball actually hitting paddle
const int8_t diff = FTOB(newx) - paddle_x;
const int8_t diff = FTOB(newx) - bdat.paddle_x;
if (WITHIN(diff, 0, PADDLE_W - 1)) {
// Reverse Y direction
ballv = -ballv; _BUZZ(3, 880);
hit_dir = -1;
bdat.ballv = -bdat.ballv; _BUZZ(3, 880);
bdat.hit_dir = -1;
// Near edges affects X velocity
const bool is_left_edge = (diff <= 1);
if (is_left_edge || diff >= PADDLE_W-1 - 1) {
if ((ballh > 0) == is_left_edge) ballh = -ballh;
if ((bdat.ballh > 0) == is_left_edge) bdat.ballh = -bdat.ballh;
}
else if (diff <= 3) {
ballh += fixed_t(random(-64, 0));
NOLESS(ballh, BTOF(-2));
NOMORE(ballh, BTOF(2));
bdat.ballh += fixed_t(random(-64, 0));
NOLESS(bdat.ballh, BTOF(-2));
NOMORE(bdat.ballh, BTOF(2));
}
else if (diff >= PADDLE_W-1 - 3) {
ballh += fixed_t(random( 0, 64));
NOLESS(ballh, BTOF(-2));
NOMORE(ballh, BTOF(2));
bdat.ballh += fixed_t(random( 0, 64));
NOLESS(bdat.ballh, BTOF(-2));
NOMORE(bdat.ballh, BTOF(2));
}
// Paddle hit after clearing the board? Reset the board.
@@ -137,7 +131,7 @@ void BrickoutGame::game_screen() {
}
}
ballx += ballh; bally += ballv; // update with new velocity
bdat.ballx += bdat.ballh; bdat.bally += bdat.ballv; // update with new velocity
} while (false);
}
@@ -150,7 +144,7 @@ void BrickoutGame::game_screen() {
const uint8_t yy = y * BRICK_H + BRICK_TOP;
if (PAGE_CONTAINS(yy, yy + BRICK_H - 1)) {
for (uint8_t x = 0; x < BRICK_COLS; ++x) {
if (TEST(bricks[y], x)) {
if (TEST(bdat.bricks[y], x)) {
const uint8_t xx = x * BRICK_W;
for (uint8_t v = 0; v < BRICK_H - 1; ++v)
if (PAGE_CONTAINS(yy + v, yy + v))
@@ -163,20 +157,20 @@ void BrickoutGame::game_screen() {
// Draw paddle
if (PAGE_CONTAINS(PADDLE_Y-1, PADDLE_Y)) {
u8g.drawHLine(paddle_x, PADDLE_Y, PADDLE_W);
u8g.drawHLine(bdat.paddle_x, PADDLE_Y, PADDLE_W);
#if PADDLE_H > 1
u8g.drawHLine(paddle_x, PADDLE_Y-1, PADDLE_W);
u8g.drawHLine(bdat.paddle_x, PADDLE_Y-1, PADDLE_W);
#if PADDLE_H > 2
u8g.drawHLine(paddle_x, PADDLE_Y-2, PADDLE_W);
u8g.drawHLine(bdat.paddle_x, PADDLE_Y-2, PADDLE_W);
#endif
#endif
}
// Draw ball while game is running
if (game_state) {
const uint8_t by = FTOB(bally);
const uint8_t by = FTOB(bdat.bally);
if (PAGE_CONTAINS(by, by+1))
u8g.drawFrame(FTOB(ballx), by, 2, 2);
u8g.drawFrame(FTOB(bdat.ballx), by, 2, 2);
}
// Or draw GAME OVER
else
@@ -192,18 +186,20 @@ void BrickoutGame::game_screen() {
// Balls Left
lcd_moveto(LCD_PIXEL_WIDTH - MENU_FONT_WIDTH * 3, MENU_FONT_ASCENT - 1);
PGM_P const ohs = PSTR("ooo\0\0");
lcd_put_u8str_P(ohs + 3 - balls_left);
lcd_put_u8str_P(ohs + 3 - bdat.balls_left);
}
// A click always exits this game
if (ui.use_click()) exit_game();
}
#define SCREEN_M ((LCD_PIXEL_WIDTH) / 2)
void BrickoutGame::enter_game() {
init_game(2, game_screen); // 2 = reset bricks on paddle hit
constexpr uint8_t paddle_start = SCREEN_M - (PADDLE_W) / 2;
paddle_x = paddle_start;
balls_left = 3;
bdat.paddle_x = paddle_start;
bdat.balls_left = 3;
reset_bricks(0x0000);
reset_ball();
ui.encoderPosition = paddle_start / (PADDLE_VEL);