add 2048 bare minimum example #27
+121
-90
@@ -1,3 +1,4 @@
|
|||||||
|
#include "dangerzone/render/rect.h"
|
||||||
#include <dangerzone/engine.h>
|
#include <dangerzone/engine.h>
|
||||||
#include <dangerzone/render/misc.h>
|
#include <dangerzone/render/misc.h>
|
||||||
#include <dangerzone/render/text.h>
|
#include <dangerzone/render/text.h>
|
||||||
@@ -27,39 +28,6 @@ typedef struct {
|
|||||||
|
|
||||||
static game_t game;
|
static game_t game;
|
||||||
|
|
||||||
// polling events every frame
|
|
||||||
void
|
|
||||||
client_poll_event()
|
|
||||||
{
|
|
||||||
SDL_Event ev = game_state->event;
|
|
||||||
|
|
||||||
if (ev.type == SDL_EVENT_QUIT) {
|
|
||||||
game_state->is_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev.type == SDL_EVENT_KEY_DOWN) {
|
|
||||||
switch (ev.key.key) {
|
|
||||||
case SDLK_Q:
|
|
||||||
game_state->is_running = false;
|
|
||||||
break;
|
|
||||||
case SDLK_W:
|
|
||||||
game.direction = UP;
|
|
||||||
break;
|
|
||||||
case SDLK_S:
|
|
||||||
game.direction = DOWN;
|
|
||||||
break;
|
|
||||||
case SDLK_A:
|
|
||||||
game.direction = LEFT;
|
|
||||||
break;
|
|
||||||
case SDLK_D:
|
|
||||||
game.direction = RIGHT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
print_area()
|
print_area()
|
||||||
{
|
{
|
||||||
@@ -74,17 +42,19 @@ print_area()
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
move()
|
move()
|
||||||
{
|
{
|
||||||
|
bool retval = false;
|
||||||
switch (game.direction) {
|
switch (game.direction) {
|
||||||
case LEFT:
|
case LEFT:
|
||||||
for (int i = 0; i < SIZE; i++) {
|
for (int i = 0; i < SIZE; i++) {
|
||||||
for (int j = 0; j < SIZE; j++) {
|
for (int j = 0; j < SIZE; j++) {
|
||||||
for (int k = 0; k < SIZE - 1; k++) {
|
for (int k = 0; k < SIZE - 1; k++) {
|
||||||
if (game.area[i][k] == 0) {
|
if (game.area[i][k] == 0 && game.area[i][k + 1] != 0) {
|
||||||
game.area[i][k] = game.area[i][k + 1];
|
game.area[i][k] = game.area[i][k + 1];
|
||||||
game.area[i][k + 1] = 0;
|
game.area[i][k + 1] = 0;
|
||||||
|
retval = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,9 +65,10 @@ move()
|
|||||||
uint32_t *row = game.area[i];
|
uint32_t *row = game.area[i];
|
||||||
for (int j = SIZE - 1; j >= 0; j--) {
|
for (int j = SIZE - 1; j >= 0; j--) {
|
||||||
for (int k = SIZE - 1; k > 0; k--) {
|
for (int k = SIZE - 1; k > 0; k--) {
|
||||||
if (game.area[i][k] == 0) {
|
if (game.area[i][k] == 0 && game.area[i][k - 1] != 0) {
|
||||||
game.area[i][k] = game.area[i][k - 1];
|
game.area[i][k] = game.area[i][k - 1];
|
||||||
game.area[i][k - 1] = 0;
|
game.area[i][k - 1] = 0;
|
||||||
|
retval = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,9 +78,10 @@ move()
|
|||||||
for (int i = 0; i < SIZE; i++) {
|
for (int i = 0; i < SIZE; i++) {
|
||||||
for (int j = 0; j < SIZE; j++) {
|
for (int j = 0; j < SIZE; j++) {
|
||||||
for (int k = 0; k < SIZE - 1; k++) {
|
for (int k = 0; k < SIZE - 1; k++) {
|
||||||
if (game.area[k][i] == 0) {
|
if (game.area[k][i] == 0 && game.area[k + 1][i] != 0) {
|
||||||
game.area[k][i] = game.area[k + 1][i];
|
game.area[k][i] = game.area[k + 1][i];
|
||||||
game.area[k + 1][i] = 0;
|
game.area[k + 1][i] = 0;
|
||||||
|
retval = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,9 +91,10 @@ move()
|
|||||||
for (int i = 0; i < SIZE; i++) {
|
for (int i = 0; i < SIZE; i++) {
|
||||||
for (int j = SIZE - 1; j >= 0; j--) {
|
for (int j = SIZE - 1; j >= 0; j--) {
|
||||||
for (int k = SIZE - 1; k > 0; k--) {
|
for (int k = SIZE - 1; k > 0; k--) {
|
||||||
if (game.area[k][i] == 0) {
|
if (game.area[k][i] == 0 && game.area[k][i - 1] != 0) {
|
||||||
game.area[k][i] = game.area[k - 1][i];
|
game.area[k][i] = game.area[k - 1][i];
|
||||||
game.area[k - 1][i] = 0;
|
game.area[k - 1][i] = 0;
|
||||||
|
retval = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,43 +103,15 @@ move()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool
|
||||||
* Python alternative (only horizontal)
|
combine_horizontal(
|
||||||
*
|
bool has_moved
|
||||||
# combines a shifted row as per the rules of 2048
|
) {
|
||||||
# returns whether there were modifications done
|
bool retval = has_moved;
|
||||||
def combine_row(row: list[int], to_left: bool) -> bool:
|
|
||||||
# make sure it is shifted
|
|
||||||
retval = shift_row(row, to_left)
|
|
||||||
|
|
||||||
if to_left:
|
|
||||||
direction = 1
|
|
||||||
start = 0
|
|
||||||
end = len(row) - 1
|
|
||||||
else:
|
|
||||||
direction = -1
|
|
||||||
start = len(row) - 1
|
|
||||||
end = 0
|
|
||||||
|
|
||||||
for i in range(start, end, direction):
|
|
||||||
if row[i] == 0:
|
|
||||||
continue
|
|
||||||
if row[i] == row[i + direction]:
|
|
||||||
retval = True
|
|
||||||
row[i] *= 2
|
|
||||||
row[i + direction] = 0
|
|
||||||
for j in range(i + direction, end, direction):
|
|
||||||
row[j] = row[j + direction]
|
|
||||||
row[end] = 0
|
|
||||||
|
|
||||||
return retval
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
combine_horizontal()
|
|
||||||
{
|
|
||||||
int8_t direction;
|
int8_t direction;
|
||||||
uint32_t start, end;
|
uint32_t start, end;
|
||||||
switch (game.direction) {
|
switch (game.direction) {
|
||||||
@@ -194,6 +139,7 @@ combine_horizontal()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (row[i] == row[i - direction]) {
|
if (row[i] == row[i - direction]) {
|
||||||
|
retval = true;
|
||||||
row[i] *= 2;
|
row[i] *= 2;
|
||||||
row[i - direction] = 0;
|
row[i - direction] = 0;
|
||||||
for (int j = i - direction; (game.direction == LEFT) ? j < end : j > end; j -= direction) {
|
for (int j = i - direction; (game.direction == LEFT) ? j < end : j > end; j -= direction) {
|
||||||
@@ -203,11 +149,15 @@ combine_horizontal()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
combine_vertical()
|
combine_vertical(
|
||||||
{
|
bool has_moved
|
||||||
|
) {
|
||||||
|
bool retval = has_moved;
|
||||||
int8_t direction;
|
int8_t direction;
|
||||||
uint32_t start, end;
|
uint32_t start, end;
|
||||||
switch (game.direction) {
|
switch (game.direction) {
|
||||||
@@ -233,6 +183,7 @@ combine_vertical()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (game.area[i][col_index] == game.area[i - direction][col_index]) {
|
if (game.area[i][col_index] == game.area[i - direction][col_index]) {
|
||||||
|
retval = true;
|
||||||
game.area[i][col_index] *= 2;
|
game.area[i][col_index] *= 2;
|
||||||
game.area[i - direction][col_index] = 0;
|
game.area[i - direction][col_index] = 0;
|
||||||
for (int j = i - direction; (game.direction == UP) ? j < end : j > end; j -= direction) {
|
for (int j = i - direction; (game.direction == UP) ? j < end : j > end; j -= direction) {
|
||||||
@@ -242,41 +193,121 @@ combine_vertical()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
combine()
|
combine(
|
||||||
{
|
bool has_moved
|
||||||
|
) {
|
||||||
if (game.direction == LEFT || game.direction == RIGHT) {
|
if (game.direction == LEFT || game.direction == RIGHT) {
|
||||||
combine_horizontal();
|
return combine_horizontal(has_moved);
|
||||||
} else {
|
} else {
|
||||||
combine_vertical();
|
return combine_vertical(has_moved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finds a random empty position and puts a two there
|
||||||
|
void
|
||||||
|
new_2()
|
||||||
|
{
|
||||||
|
uint32_t row = rand() % SIZE;
|
||||||
|
uint32_t col = rand() % SIZE;
|
||||||
|
while (game.area[row][col] != 0) {
|
||||||
|
row = rand() % SIZE;
|
||||||
|
col = rand() % SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
game.area[row][col] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
slide()
|
slide()
|
||||||
{
|
{
|
||||||
// 1. move all squares in one direction
|
// 1. move all squares in one direction
|
||||||
move();
|
bool has_moved = move();
|
||||||
|
|
||||||
// 2. then combine them and shift the potential rest by one in the given direction
|
// 2. then combine them and shift the potential rest by one in the given direction
|
||||||
combine();
|
bool has_combined = combine(has_moved);
|
||||||
|
|
||||||
|
printf("moved? %s, combined? %s\n", (has_moved) ? "true" : "false", (has_combined) ? "true" : "false");
|
||||||
|
|
||||||
|
// 3. generate a new 2
|
||||||
|
if (has_moved || has_combined) {
|
||||||
|
new_2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// polling events every frame
|
||||||
|
void
|
||||||
|
client_poll_event()
|
||||||
|
{
|
||||||
|
SDL_Event ev = game_state->event;
|
||||||
|
|
||||||
|
if (ev.type == SDL_EVENT_QUIT) {
|
||||||
|
game_state->is_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type == SDL_EVENT_KEY_DOWN) {
|
||||||
|
switch (ev.key.key) {
|
||||||
|
case SDLK_Q:
|
||||||
|
game_state->is_running = false;
|
||||||
|
break;
|
||||||
|
case SDLK_W:
|
||||||
|
game.direction = UP;
|
||||||
|
slide();
|
||||||
|
break;
|
||||||
|
case SDLK_S:
|
||||||
|
game.direction = DOWN;
|
||||||
|
slide();
|
||||||
|
break;
|
||||||
|
case SDLK_A:
|
||||||
|
game.direction = LEFT;
|
||||||
|
slide();
|
||||||
|
break;
|
||||||
|
case SDLK_D:
|
||||||
|
game.direction = RIGHT;
|
||||||
|
slide();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHR(ord) ((ord) + 48)
|
||||||
|
#define ORD(chr) ((chr) - 48)
|
||||||
|
|
||||||
// performed every frame
|
// performed every frame
|
||||||
void
|
void
|
||||||
client_update_framebuffer()
|
client_update_framebuffer()
|
||||||
{
|
{
|
||||||
//slide();
|
// clear_framebuffer(0xFFFF00);
|
||||||
|
// put_string("Welcome to the most\n*DANGEROUS* 2048 game!",
|
||||||
|
// 20, 20, 2, 2, 3, 0x000000, 0xFFFF00
|
||||||
|
// );
|
||||||
|
|
||||||
// single green demo pixel
|
clear_framebuffer(0x000000);
|
||||||
game_state->framebuffer[0] = 0x00FF00;
|
|
||||||
|
uint32_t tile_size = game_state->width / SIZE;
|
||||||
|
uint8_t border_width = 10;
|
||||||
|
for (int i = 0; i < SIZE; i++) {
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
// background
|
||||||
|
uint32_t x = (border_width / 2) + i * tile_size;
|
||||||
|
uint32_t y = (border_width / 2)+ j * tile_size;
|
||||||
|
uint32_t w = tile_size - border_width;
|
||||||
|
uint32_t h = tile_size - border_width;
|
||||||
|
uint32_t background_color = 0xFFFFFF;
|
||||||
|
put_rect(x, y, w, h, background_color);
|
||||||
|
|
||||||
clear_framebuffer(0xFFFF00);
|
// number in foreground
|
||||||
put_string("Welcome to the most\n*DANGEROUS* 2048 game!",
|
uint32_t foreground_color = 0x000000;
|
||||||
20, 20, 2, 2, 3, 0x000000, 0xFFFF00
|
uint8_t font_size = 7;
|
||||||
);
|
put_char(CHR(game.area[j][i]), x + border_width, y + border_width, font_size, foreground_color, background_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
Reference in New Issue
Block a user