Skip to content

Commit

Permalink
v1.0 Bare-bones 2048
Browse files Browse the repository at this point in the history
- This is the barest of ports of 2048
- It plays the game and allows you to play it again
- No sounds, only the D-Pad and Start are recognized.
- Fixed up `README`, added more images

If you want 2048 and nothing but pure pure tile moving action, here is the game

Future versions will have more creature comforts, graphical improvements, etc.
  • Loading branch information
schuylermartin45 committed Sep 13, 2022
1 parent 8f3e5de commit 89f9a8c
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 9 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Gameboy 2048

![Gameboy 2048](./img/screenshots/04_v1_0_0_release_photo.png)

After an incredibly irresponsible purchase at a local retro gaming store, I
promised myself that I would finally get around to developing something that
ran on a Gameboy.
Expand Down Expand Up @@ -57,4 +59,7 @@ I used the new GBDK-2020 releases of the
and ran them using [wine](https://www.winehq.org/).

## How to play
TODO
Press `Start` to start a new game. Use the `D-Pad` to scroll tiles.

When the game is over, pressing `Start` will allow you to start a new
game.
Binary file added img/screenshots/02_first_run_on_dmg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/screenshots/03_first_run_on_gbc.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/screenshots/04_v1_0_0_release_photo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 48 additions & 5 deletions src/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,24 @@ Description: Represents the current game board.

#include "board.h"

//#define TEST_EASY_WIN 1

/***** Variables *****/

/***** Functions *****/

/*
** Generate a new tile on the board.
** @param board Board to modify
*/
void board_generate_tile(Board* board) {
// Decide if we are dropping a 2 or a 4, biased towards 2 (roughly 88% of
// the time...Great Scott!)
const TileId tileId = (rand() < 225) ? 1 : 2;
#ifdef TEST_EASY_WIN
const TileId tileId = 10;
#else
const TileId tileId = (rand() < 225) ? 1 : 2;
#endif

// Scan for all available spots, storing the row value in the upper 4 bits
// and the column in the lower 4 bits.
Expand Down Expand Up @@ -52,6 +62,7 @@ void board_generate_tile(Board* board) {
void board_init(Board* board) {
// Initialize the board to 0
board->score = 0;
board->reached_2048 = false;
for (size_t r=0; r<BOARD_SIZE; ++r) {
for (size_t c=0; c<BOARD_SIZE; ++c) {
board->grid[r][c] = 0;
Expand Down Expand Up @@ -177,12 +188,44 @@ void board_shift(Board* board, const BoardDirection direction) {
** @param board Game board to check
** @return Enum indicating if the game has ended
*/
Endgame board_check(const Board* board) {
// TODO complete
Endgame board_check(Board* board) {
// The end game must be checked against all tile positions. So we check
// every board position for such an event. Therefore the "continue"
// conditions are checked at the end of checking all tiles.
bool keep_going = false;
for (size_t r=0; r<BOARD_SIZE; ++r) {
for (size_t c=0; c<BOARD_SIZE; ++c) {
board->grid[r][c];
const TileId cur_val = board->grid[r][c];
// Win conditions
if (!board->reached_2048 && cur_val == TILE_ID_2048) {
// This flag allows the player to keep going.
board->reached_2048 = true;
return ENDGAME_WIN_2048;
}
else if (board->reached_2048 && cur_val == MAX_TILE_ID) {
return ENDGAME_WIN_4096;
}
// Continue playing conditions
else if (cur_val == NULL_TILE_ID) {
keep_going = true;
}
else if ((r > 0) && (cur_val == board->grid[r-1][c])) {
keep_going = true;
}
else if ((r < BOUND_SIZE) && (cur_val == board->grid[r+1][c])) {
keep_going = true;
}
else if ((c > 0) && (cur_val == board->grid[r][c-1])) {
keep_going = true;
}
else if ((c < BOUND_SIZE) && (cur_val == board->grid[r][c+1])) {
keep_going = true;
}
}
}
return ENDGAME_NONE;
if (keep_going) {
return ENDGAME_NONE;
}
// If all checks fail, the game has been lost
return ENDGAME_LOSS;
}
13 changes: 10 additions & 3 deletions src/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ Description: Represents the current game board.
#ifndef BOARD_H
#define BOARD_H

#include <stdbool.h>
#include <stdint.h>

#include "grid_tile.h"

/***** Constants *****/

#define MAX_TILE_ID 12
#define BOARD_SIZE 4
#define TILE_ID_2048 11
#define MAX_TILE_ID 12
#define BOARD_SIZE 4
#define BOUND_SIZE (BOARD_SIZE - 1)

// Macros used for board availability checks
#define ROW_4_BIT_MASK 0xF0
Expand All @@ -28,7 +31,11 @@ typedef uint8_t Score;

/// Stores data associated with the current game
typedef struct {
/// Current score
Score score;
/// Tracks if the game is going to 4096
bool reached_2048;
/// Gameplay grid system
TileId grid[BOARD_SIZE][BOARD_SIZE];
} Board;

Expand Down Expand Up @@ -58,6 +65,6 @@ void board_generate_tile(Board* board);
void board_shift(Board* board, const BoardDirection direction);

/// Check if the game is over
Endgame board_check(const Board* board);
Endgame board_check(Board* board);

#endif
36 changes: 36 additions & 0 deletions src/gb2048.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,43 @@ int main() {

if (direction != BOARD_NONE) {
board_shift(&board, direction);
const Endgame endgame = board_check(&board);
render_board(&board);
// Allow the final board to render then draw the menu
if (endgame != ENDGAME_NONE) {
render_window_show(true);
switch (endgame) {
case ENDGAME_WIN_2048:
render_str_relative(
REL_POS_1,
REL_POS_1,
"2048! Continue?"
);
break;
case ENDGAME_WIN_4096:
render_str_relative(
REL_POS_1,
REL_POS_1,
"4096! Play again?"
);
break;
case ENDGAME_LOSS:
render_str_relative(
REL_POS_1,
REL_POS_1,
"Game Over."
);
break;
}
wait_on_button_pressed(J_START);
render_window_hide();
// Allow the user to play again
if ((endgame == ENDGAME_WIN_4096) || (endgame == ENDGAME_LOSS)) {
board_init(&board);
render_board(&board);
}
continue;
}
}

wait_vbl_done();
Expand Down

0 comments on commit 89f9a8c

Please sign in to comment.