Compare commits
5
Commits
dcd3ed9245
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
403ddc132d | ||
|
|
f9734c3c0a | ||
|
|
f367ef48a8 | ||
|
|
0dafe93b51 | ||
|
|
a14bd280ff |
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "internal/engine_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
engine_internal_state_t *internal_state = NULL;
|
||||
game_state_t *game_state = NULL;
|
||||
|
||||
|
||||
+101
-13
@@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#define SIZE 4
|
||||
#define MOVE_DURATION 0.12f
|
||||
@@ -28,6 +29,14 @@ typedef struct {
|
||||
int col;
|
||||
} line_tile_t;
|
||||
|
||||
typedef enum {
|
||||
GAME_PLAYING,
|
||||
GAME_WON,
|
||||
GAME_LOST
|
||||
} game_status_t;
|
||||
|
||||
static game_status_t game_status;
|
||||
|
||||
typedef struct {
|
||||
uint32_t area[SIZE][SIZE];
|
||||
dir_e direction;
|
||||
@@ -42,6 +51,17 @@ static size_t move_track_count;
|
||||
|
||||
static double last_frame_time;
|
||||
|
||||
static bool
|
||||
board_is_full(void)
|
||||
{
|
||||
for (int r = 0; r < SIZE; ++r)
|
||||
for (int c = 0; c < SIZE; ++c)
|
||||
if (game.area[r][c] == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Pixel size is calculated from the current window size while drawing. */
|
||||
static uint32_t
|
||||
colors(uint32_t number)
|
||||
@@ -55,6 +75,42 @@ colors(uint32_t number)
|
||||
}
|
||||
}
|
||||
|
||||
/* Maps positive values logarithmically: powers of two get evenly spaced hues.
|
||||
Returns 0xRRGGBB. Values outside [min_value, max_value] are clamped. */
|
||||
uint32_t
|
||||
color_for_value(double value, double min_value, double max_value)
|
||||
{
|
||||
if (min_value <= 0.0 || max_value <= min_value || value <= 0.0)
|
||||
return 0xFFFFFF;
|
||||
|
||||
if (value < min_value) value = min_value;
|
||||
if (value > max_value) value = max_value;
|
||||
|
||||
double t = (log2(value) - log2(min_value)) /
|
||||
(log2(max_value) - log2(min_value));
|
||||
|
||||
t = sqrt(t); /* accelerates color changes near the low end */
|
||||
|
||||
/* Sweep hue from blue to red in HSV; full saturation and brightness. */
|
||||
// double h = (1.0 - t) * 240.0;
|
||||
|
||||
double exponent = log2(value / min_value); /* 0 at min_value, 1 per doubling */
|
||||
double h = fmod(20.0 + exponent * 45.0, 360.0);
|
||||
|
||||
double c = 1.0;
|
||||
double x = 1.0 - fabs(fmod(h / 60.0, 2.0) - 1.0);
|
||||
double r, g, b;
|
||||
|
||||
if (h < 60.0) { r = c; g = x; b = 0.0; }
|
||||
else if (h < 120.0) { r = x; g = c; b = 0.0; }
|
||||
else if (h < 180.0) { r = 0.0; g = c; b = x; }
|
||||
else { r = 0.0; g = x; b = c; }
|
||||
|
||||
return ((uint32_t)(r * 255.0) << 16) |
|
||||
((uint32_t)(g * 255.0) << 8) |
|
||||
(uint32_t)(b * 255.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the board coordinate for position p in a line, where p=0 is
|
||||
* the side toward which tiles move.
|
||||
@@ -151,6 +207,8 @@ process_line(dir_e direction, int line, uint32_t output[SIZE])
|
||||
if (i + 1 < input_count &&
|
||||
input[i].value == input[i + 1].value) {
|
||||
uint32_t merged_value = input[i].value * 2;
|
||||
if (merged_value >= 2048)
|
||||
game_status = GAME_WON;
|
||||
|
||||
output[output_count] = merged_value;
|
||||
game.score += merged_value;
|
||||
@@ -194,6 +252,9 @@ process_line(dir_e direction, int line, uint32_t output[SIZE])
|
||||
static bool
|
||||
slide(dir_e direction)
|
||||
{
|
||||
if (game_status != GAME_PLAYING || anim_is_active(&movement))
|
||||
return false;
|
||||
|
||||
if (anim_is_active(&movement))
|
||||
return false;
|
||||
|
||||
@@ -260,16 +321,24 @@ client_poll_event(void)
|
||||
game_state->is_running = false;
|
||||
break;
|
||||
case SDLK_W:
|
||||
slide(UP);
|
||||
case SDLK_UP:
|
||||
if (game_status == GAME_PLAYING)
|
||||
slide(UP);
|
||||
break;
|
||||
case SDLK_S:
|
||||
slide(DOWN);
|
||||
case SDLK_DOWN:
|
||||
if (game_status == GAME_PLAYING)
|
||||
slide(DOWN);
|
||||
break;
|
||||
case SDLK_A:
|
||||
slide(LEFT);
|
||||
case SDLK_LEFT:
|
||||
if (game_status == GAME_PLAYING)
|
||||
slide(LEFT);
|
||||
break;
|
||||
case SDLK_D:
|
||||
slide(RIGHT);
|
||||
case SDLK_RIGHT:
|
||||
if (game_status == GAME_PLAYING)
|
||||
slide(RIGHT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -291,7 +360,7 @@ draw_tile_rect(uint32_t value, float x, float y, float w, float h)
|
||||
uint32_t iy = (uint32_t)y;
|
||||
uint32_t iw = (uint32_t)w;
|
||||
uint32_t ih = (uint32_t)h;
|
||||
uint32_t color = colors(value);
|
||||
uint32_t color = color_for_value((double)value, 2, 131072);
|
||||
|
||||
put_rect(OVERDRAW, ix, iy, iw, ih, color);
|
||||
|
||||
@@ -324,7 +393,12 @@ client_update_framebuffer(void)
|
||||
dt = 0.05f;
|
||||
|
||||
if (anim_is_active(&movement) && anim_update(&movement, dt)) {
|
||||
new_2();
|
||||
if (game_status == GAME_PLAYING) {
|
||||
new_2();
|
||||
|
||||
if (board_is_full())
|
||||
game_status = GAME_LOST;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tile_size = game_state->width / SIZE;
|
||||
@@ -332,7 +406,26 @@ client_update_framebuffer(void)
|
||||
|
||||
clear_framebuffer(OVERDRAW, 0x000000);
|
||||
|
||||
/* Draw all cell backgrounds first. */
|
||||
char score_text[32];
|
||||
snprintf(score_text, sizeof score_text, "score: %u", game.score);
|
||||
put_string(OVERDRAW, score_text,
|
||||
border_width / 2, tile_size * SIZE + border_width / 2,
|
||||
6, 1, 12, 0xFFFFFF, 0x000000);
|
||||
|
||||
if (game_status != GAME_PLAYING) {
|
||||
clear_framebuffer(BASE, 0x000000);
|
||||
const char *message =
|
||||
game_status == GAME_WON ? "YOU WIN!" : "YOU LOSE!";
|
||||
|
||||
put_string(OVERDRAW, message,
|
||||
0 + border_width * 2,
|
||||
game_state->height / 2,
|
||||
6, 1, 12, 0xFFFFFF, 0x000000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Draw all cell backgrounds. */
|
||||
for (int r = 0; r < SIZE; ++r) {
|
||||
for (int c = 0; c < SIZE; ++c) {
|
||||
uint32_t x = border_width / 2 + (uint32_t)c * tile_size;
|
||||
@@ -360,17 +453,12 @@ client_update_framebuffer(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char score_text[32];
|
||||
snprintf(score_text, sizeof score_text, "score: %u", game.score);
|
||||
put_string(OVERDRAW, score_text,
|
||||
border_width / 2, tile_size * SIZE + border_width / 2,
|
||||
6, 1, 12, 0xFFFFFF, 0x000000);
|
||||
}
|
||||
|
||||
static void
|
||||
game_init(void)
|
||||
{
|
||||
game_status = GAME_PLAYING;
|
||||
memset(&game, 0, sizeof game);
|
||||
anim_init(&movement);
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
add_executable(game_2048 2048.c)
|
||||
target_link_libraries(game_2048 PRIVATE dangerzone_engine)
|
||||
target_link_libraries(game_2048 PRIVATE m)
|
||||
|
||||
#add_executable(game_window window.c)
|
||||
#target_link_libraries(game_window PRIVATE dangerzone_engine)
|
||||
|
||||
Reference in New Issue
Block a user