Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad6536bdab
|
||
|
|
403ddc132d | ||
|
|
f9734c3c0a | ||
|
|
f367ef48a8 | ||
|
|
0dafe93b51 | ||
|
|
a14bd280ff | ||
|
|
dcd3ed9245 |
@@ -9,6 +9,10 @@ typedef enum {
|
|||||||
OVERDRAW
|
OVERDRAW
|
||||||
} framebuffer_e;
|
} framebuffer_e;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x, y;
|
||||||
|
} v2;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
bool is_running;
|
bool is_running;
|
||||||
@@ -17,9 +21,9 @@ typedef struct {
|
|||||||
SDL_Rect dirty_rect;
|
SDL_Rect dirty_rect;
|
||||||
uint16_t width, height;
|
uint16_t width, height;
|
||||||
// base layer ~ layer 0
|
// base layer ~ layer 0
|
||||||
uint32_t *framebuffer_base;
|
uint32_t *framebuffer_base;
|
||||||
// layer on top of that ~ layer 1
|
// layer on top of that ~ layer 1
|
||||||
uint32_t *framebuffer_overdraw;
|
uint32_t *framebuffer_overdraw;
|
||||||
} game_state_t;
|
} game_state_t;
|
||||||
|
|
||||||
extern game_state_t *game_state;
|
extern game_state_t *game_state;
|
||||||
|
|||||||
@@ -4,16 +4,33 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
put_pixel(
|
put_pixel(
|
||||||
framebuffer_e framebuffer,
|
framebuffer_e framebuffer,
|
||||||
unsigned int x,
|
unsigned int x,
|
||||||
unsigned int y,
|
unsigned int y,
|
||||||
uint32_t color
|
uint32_t color
|
||||||
);
|
);
|
||||||
|
|
||||||
void
|
void
|
||||||
clear_framebuffer(
|
clear_framebuffer(
|
||||||
framebuffer_e framebuffer,
|
framebuffer_e framebuffer,
|
||||||
uint32_t color
|
uint32_t color
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
put_line(
|
||||||
|
v2 a,
|
||||||
|
v2 b,
|
||||||
|
framebuffer_e framebuffer,
|
||||||
|
uint32_t color
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
put_triangle(
|
||||||
|
v2 a,
|
||||||
|
v2 b,
|
||||||
|
v2 c,
|
||||||
|
framebuffer_e framebuffer,
|
||||||
|
uint32_t color
|
||||||
|
);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "internal/engine_internal.h"
|
#include "internal/engine_internal.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
engine_internal_state_t *internal_state = NULL;
|
engine_internal_state_t *internal_state = NULL;
|
||||||
game_state_t *game_state = NULL;
|
game_state_t *game_state = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "internal/util/error.h"
|
#include "internal/util/error.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
// helper function to return the correct pointer to a framebuffer for drawing selection
|
// helper function to return the correct pointer to a framebuffer for drawing selection
|
||||||
uint32_t*
|
uint32_t*
|
||||||
@@ -23,11 +25,11 @@ get_framebuffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// alter a pixel at an imaginary x & y coordinates
|
// alter a pixel at an imaginary x & y coordinates
|
||||||
void
|
void
|
||||||
put_pixel(
|
put_pixel(
|
||||||
framebuffer_e framebuffer,
|
framebuffer_e framebuffer,
|
||||||
unsigned int x,
|
unsigned int x,
|
||||||
unsigned int y,
|
unsigned int y,
|
||||||
uint32_t color
|
uint32_t color
|
||||||
) {
|
) {
|
||||||
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
|
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
|
||||||
@@ -55,7 +57,7 @@ clear_framebuffer(
|
|||||||
uint32_t color
|
uint32_t color
|
||||||
) {
|
) {
|
||||||
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
|
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
|
||||||
|
|
||||||
for (size_t i = 0;
|
for (size_t i = 0;
|
||||||
i < (size_t)game_state->width * game_state->height;
|
i < (size_t)game_state->width * game_state->height;
|
||||||
++i) {
|
++i) {
|
||||||
@@ -69,3 +71,84 @@ clear_framebuffer(
|
|||||||
game_state->height
|
game_state->height
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
normalize_v2(
|
||||||
|
v2 input,
|
||||||
|
v2 *output
|
||||||
|
) {
|
||||||
|
double min = (input.x > input.y) ? input.y : input.x;
|
||||||
|
|
||||||
|
for (int i = min; i > 1; i--) {
|
||||||
|
if ((int)input.x % (int)min == 0 && (int)input.y % (int)min == 0) {
|
||||||
|
input.x /= min;
|
||||||
|
input.y /= min;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output->x = input.x;
|
||||||
|
output->y = input.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// subtract vector b from vector a
|
||||||
|
void
|
||||||
|
sub_v2(
|
||||||
|
v2 a,
|
||||||
|
v2 b,
|
||||||
|
v2 *dest
|
||||||
|
) {
|
||||||
|
dest->x = b.x - a.x;
|
||||||
|
dest->y = b.y - a.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a line between two points with a given color
|
||||||
|
void
|
||||||
|
put_line(
|
||||||
|
v2 a, v2 b,
|
||||||
|
framebuffer_e fb,
|
||||||
|
uint32_t color
|
||||||
|
) {
|
||||||
|
int x0 = (int)round(a.x);
|
||||||
|
int y0 = (int)round(a.y);
|
||||||
|
int x1 = (int)round(b.x);
|
||||||
|
int y1 = (int)round(b.y);
|
||||||
|
|
||||||
|
int dx = abs(x1 - x0);
|
||||||
|
int sx = x0 < x1 ? 1 : -1;
|
||||||
|
int dy = -abs(y1 - y0);
|
||||||
|
int sy = y0 < y1 ? 1 : -1;
|
||||||
|
int err = dx + dy;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
put_pixel(fb, x0, y0, color);
|
||||||
|
|
||||||
|
if (x0 == x1 && y0 == y1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int e2 = 2 * err;
|
||||||
|
if (e2 >= dy) {
|
||||||
|
err += dy;
|
||||||
|
x0 += sx;
|
||||||
|
}
|
||||||
|
if (e2 <= dx) {
|
||||||
|
err += dx;
|
||||||
|
y0 += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a frame of a triangle with a given color
|
||||||
|
void
|
||||||
|
put_triangle(
|
||||||
|
v2 a,
|
||||||
|
v2 b,
|
||||||
|
v2 c,
|
||||||
|
framebuffer_e framebuffer,
|
||||||
|
uint32_t color
|
||||||
|
) {
|
||||||
|
put_line(a, b, framebuffer, color);
|
||||||
|
put_line(b, c, framebuffer, color);
|
||||||
|
put_line(a, c, framebuffer, color);
|
||||||
|
}
|
||||||
|
|||||||
+101
-13
@@ -10,6 +10,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define SIZE 4
|
#define SIZE 4
|
||||||
#define MOVE_DURATION 0.12f
|
#define MOVE_DURATION 0.12f
|
||||||
@@ -28,6 +29,14 @@ typedef struct {
|
|||||||
int col;
|
int col;
|
||||||
} line_tile_t;
|
} line_tile_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GAME_PLAYING,
|
||||||
|
GAME_WON,
|
||||||
|
GAME_LOST
|
||||||
|
} game_status_t;
|
||||||
|
|
||||||
|
static game_status_t game_status;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t area[SIZE][SIZE];
|
uint32_t area[SIZE][SIZE];
|
||||||
dir_e direction;
|
dir_e direction;
|
||||||
@@ -42,6 +51,17 @@ static size_t move_track_count;
|
|||||||
|
|
||||||
static double last_frame_time;
|
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. */
|
/* Pixel size is calculated from the current window size while drawing. */
|
||||||
static uint32_t
|
static uint32_t
|
||||||
colors(uint32_t number)
|
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
|
* Return the board coordinate for position p in a line, where p=0 is
|
||||||
* the side toward which tiles move.
|
* 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 &&
|
if (i + 1 < input_count &&
|
||||||
input[i].value == input[i + 1].value) {
|
input[i].value == input[i + 1].value) {
|
||||||
uint32_t merged_value = input[i].value * 2;
|
uint32_t merged_value = input[i].value * 2;
|
||||||
|
if (merged_value >= 2048)
|
||||||
|
game_status = GAME_WON;
|
||||||
|
|
||||||
output[output_count] = merged_value;
|
output[output_count] = merged_value;
|
||||||
game.score += merged_value;
|
game.score += merged_value;
|
||||||
@@ -194,6 +252,9 @@ process_line(dir_e direction, int line, uint32_t output[SIZE])
|
|||||||
static bool
|
static bool
|
||||||
slide(dir_e direction)
|
slide(dir_e direction)
|
||||||
{
|
{
|
||||||
|
if (game_status != GAME_PLAYING || anim_is_active(&movement))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (anim_is_active(&movement))
|
if (anim_is_active(&movement))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -260,16 +321,24 @@ client_poll_event(void)
|
|||||||
game_state->is_running = false;
|
game_state->is_running = false;
|
||||||
break;
|
break;
|
||||||
case SDLK_W:
|
case SDLK_W:
|
||||||
slide(UP);
|
case SDLK_UP:
|
||||||
|
if (game_status == GAME_PLAYING)
|
||||||
|
slide(UP);
|
||||||
break;
|
break;
|
||||||
case SDLK_S:
|
case SDLK_S:
|
||||||
slide(DOWN);
|
case SDLK_DOWN:
|
||||||
|
if (game_status == GAME_PLAYING)
|
||||||
|
slide(DOWN);
|
||||||
break;
|
break;
|
||||||
case SDLK_A:
|
case SDLK_A:
|
||||||
slide(LEFT);
|
case SDLK_LEFT:
|
||||||
|
if (game_status == GAME_PLAYING)
|
||||||
|
slide(LEFT);
|
||||||
break;
|
break;
|
||||||
case SDLK_D:
|
case SDLK_D:
|
||||||
slide(RIGHT);
|
case SDLK_RIGHT:
|
||||||
|
if (game_status == GAME_PLAYING)
|
||||||
|
slide(RIGHT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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 iy = (uint32_t)y;
|
||||||
uint32_t iw = (uint32_t)w;
|
uint32_t iw = (uint32_t)w;
|
||||||
uint32_t ih = (uint32_t)h;
|
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);
|
put_rect(OVERDRAW, ix, iy, iw, ih, color);
|
||||||
|
|
||||||
@@ -324,7 +393,12 @@ client_update_framebuffer(void)
|
|||||||
dt = 0.05f;
|
dt = 0.05f;
|
||||||
|
|
||||||
if (anim_is_active(&movement) && anim_update(&movement, dt)) {
|
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;
|
uint32_t tile_size = game_state->width / SIZE;
|
||||||
@@ -332,7 +406,26 @@ client_update_framebuffer(void)
|
|||||||
|
|
||||||
clear_framebuffer(OVERDRAW, 0x000000);
|
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 r = 0; r < SIZE; ++r) {
|
||||||
for (int c = 0; c < SIZE; ++c) {
|
for (int c = 0; c < SIZE; ++c) {
|
||||||
uint32_t x = border_width / 2 + (uint32_t)c * tile_size;
|
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
|
static void
|
||||||
game_init(void)
|
game_init(void)
|
||||||
{
|
{
|
||||||
|
game_status = GAME_PLAYING;
|
||||||
memset(&game, 0, sizeof game);
|
memset(&game, 0, sizeof game);
|
||||||
anim_init(&movement);
|
anim_init(&movement);
|
||||||
srand((unsigned)time(NULL));
|
srand((unsigned)time(NULL));
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
#include <dangerzone/engine.h>
|
||||||
|
#include <dangerzone/render/misc.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// a point in 3D space
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double x, y, z;
|
||||||
|
} v3;
|
||||||
|
|
||||||
|
// a triangle with 3 points in 3D space
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
v3 p[3];
|
||||||
|
} tri;
|
||||||
|
|
||||||
|
// a grouping of triangles - can desribe any 3D object
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tri *tris;
|
||||||
|
} mesh;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float m[4][4];
|
||||||
|
} mat4x4;
|
||||||
|
|
||||||
|
#define PI 3.1415926535
|
||||||
|
|
||||||
|
void multiply_matrix_vector(v3 input, v3 *output, mat4x4 m)
|
||||||
|
{
|
||||||
|
output->x = input.x * m.m[0][0] + input.y * m.m[1][0] + input.z * m.m[2][0] + m.m[3][0];
|
||||||
|
output->y = input.x * m.m[0][1] + input.y * m.m[1][1] + input.z * m.m[2][1] + m.m[3][1];
|
||||||
|
output->z = input.x * m.m[0][2] + input.y * m.m[1][2] + input.z * m.m[2][2] + m.m[3][2];
|
||||||
|
double w = input.x * m.m[0][3] + input.y * m.m[1][3] + input.z * m.m[2][3] + m.m[3][3];
|
||||||
|
|
||||||
|
if (w != 0)
|
||||||
|
{
|
||||||
|
output->x /= w;
|
||||||
|
output->y /= w;
|
||||||
|
output->z /= w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT(_e) do { if (!(_e)) { fprintf(stderr, "assert failed for %s\n", #_e); exit(1); } } while (0)
|
||||||
|
|
||||||
|
struct {
|
||||||
|
mesh m;
|
||||||
|
mat4x4 mproj;
|
||||||
|
double near, far, fov;
|
||||||
|
unsigned int screen_width, screen_height;
|
||||||
|
} state;
|
||||||
|
|
||||||
|
// a unit-sized cube mesh defined with triangles
|
||||||
|
#define CUBE_TRI_AMOUNT 12
|
||||||
|
|
||||||
|
tri cube_mesh[CUBE_TRI_AMOUNT] =
|
||||||
|
{
|
||||||
|
// south
|
||||||
|
{{ {0,0,0}, {0,1,0}, {1,1,0} }},
|
||||||
|
{{ {0,0,0}, {1,1,0}, {1,0,0} }},
|
||||||
|
// west
|
||||||
|
{{ {1,0,0}, {1,1,0}, {1,1,1} }},
|
||||||
|
{{ {1,0,0}, {1,1,1}, {1,0,1} }},
|
||||||
|
// north
|
||||||
|
{{ {1,0,1}, {1,1,1}, {0,1,1} }},
|
||||||
|
{{ {1,0,1}, {0,1,1}, {0,0,1} }},
|
||||||
|
// east
|
||||||
|
{{ {0,0,1}, {0,1,1}, {0,1,0} }},
|
||||||
|
{{ {0,0,1}, {0,1,0}, {0,0,0} }},
|
||||||
|
// top
|
||||||
|
{{ {0,1,0}, {0,1,1}, {1,1,1} }},
|
||||||
|
{{ {0,1,0}, {1,1,1}, {1,1,0} }},
|
||||||
|
// bottom
|
||||||
|
{{ {0,0,1}, {0,0,0}, {1,0,0} }},
|
||||||
|
{{ {0,0,1}, {1,0,0}, {1,0,1} }},
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
game_init()
|
||||||
|
{
|
||||||
|
state.m.tris = cube_mesh;
|
||||||
|
|
||||||
|
memset(&state.mproj, 0, sizeof(state.mproj));
|
||||||
|
|
||||||
|
state.near = 0.1;
|
||||||
|
state.far = 1000000.0;
|
||||||
|
state.fov = 90.0;
|
||||||
|
state.screen_width = 500;
|
||||||
|
state.screen_height = 500;
|
||||||
|
|
||||||
|
// aspect ratio
|
||||||
|
double a = (float)state.screen_height / (float)state.screen_width;
|
||||||
|
|
||||||
|
// fov tangent
|
||||||
|
double fov_rad = 1.0 / tanf(state.fov * 0.5 / 180.0 * PI);
|
||||||
|
|
||||||
|
state.mproj.m[0][0] = a * fov_rad;
|
||||||
|
state.mproj.m[1][1] = fov_rad;
|
||||||
|
state.mproj.m[2][2] = state.far / (state.far - state.near);
|
||||||
|
state.mproj.m[3][2] = (-state.far * state.near) / (state.far - state.near);
|
||||||
|
state.mproj.m[2][3] = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_poll_events()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
client_update_framebuffer()
|
||||||
|
{
|
||||||
|
clear_framebuffer(BASE, 0x000000);
|
||||||
|
clear_framebuffer(OVERDRAW, 0x000000);
|
||||||
|
|
||||||
|
mat4x4 mrotz = { 0 }, mrotx = { 0 };
|
||||||
|
|
||||||
|
double theta = SDL_GetTicks() / 1000.0;
|
||||||
|
|
||||||
|
// Rotation Z
|
||||||
|
mrotz.m[0][0] = cosf(theta);
|
||||||
|
mrotz.m[0][1] = sinf(theta);
|
||||||
|
mrotz.m[1][0] = -sinf(theta);
|
||||||
|
mrotz.m[1][1] = cosf(theta);
|
||||||
|
mrotz.m[2][2] = 1;
|
||||||
|
mrotz.m[3][3] = 1;
|
||||||
|
|
||||||
|
// Rotation X
|
||||||
|
mrotx.m[0][0] = 1;
|
||||||
|
mrotx.m[1][1] = cosf(theta * 0.5f);
|
||||||
|
mrotx.m[1][2] = sinf(theta * 0.5f);
|
||||||
|
mrotx.m[2][1] = -sinf(theta * 0.5f);
|
||||||
|
mrotx.m[2][2] = cosf(theta * 0.5f);
|
||||||
|
mrotx.m[3][3] = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < CUBE_TRI_AMOUNT; i++)
|
||||||
|
{
|
||||||
|
// project from 3D to 2D
|
||||||
|
tri triangle = state.m.tris[i];
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
triangle.p[k].x -= 0.5;
|
||||||
|
triangle.p[k].y -= 0.5;
|
||||||
|
triangle.p[k].z -= 0.5;
|
||||||
|
}
|
||||||
|
tri projected, translated, rotatedz, rotatedzx;
|
||||||
|
|
||||||
|
multiply_matrix_vector(triangle.p[0], &rotatedz.p[0], mrotz);
|
||||||
|
multiply_matrix_vector(triangle.p[1], &rotatedz.p[1], mrotz);
|
||||||
|
multiply_matrix_vector(triangle.p[2], &rotatedz.p[2], mrotz);
|
||||||
|
|
||||||
|
multiply_matrix_vector(rotatedz.p[0], &rotatedzx.p[0], mrotx);
|
||||||
|
multiply_matrix_vector(rotatedz.p[1], &rotatedzx.p[1], mrotx);
|
||||||
|
multiply_matrix_vector(rotatedz.p[2], &rotatedzx.p[2], mrotx);
|
||||||
|
|
||||||
|
translated = rotatedzx;
|
||||||
|
translated.p[0].z = rotatedzx.p[0].z + 3.0;
|
||||||
|
translated.p[1].z = rotatedzx.p[1].z + 3.0;
|
||||||
|
translated.p[2].z = rotatedzx.p[2].z + 3.0;
|
||||||
|
|
||||||
|
multiply_matrix_vector(translated.p[0], &projected.p[0], state.mproj);
|
||||||
|
multiply_matrix_vector(translated.p[1], &projected.p[1], state.mproj);
|
||||||
|
multiply_matrix_vector(translated.p[2], &projected.p[2], state.mproj);
|
||||||
|
|
||||||
|
// scale into view
|
||||||
|
projected.p[0].x += 1.0;
|
||||||
|
projected.p[0].y += 1.0;
|
||||||
|
|
||||||
|
projected.p[1].x += 1.0;
|
||||||
|
projected.p[1].y += 1.0;
|
||||||
|
|
||||||
|
projected.p[2].x += 1.0;
|
||||||
|
projected.p[2].y += 1.0;
|
||||||
|
|
||||||
|
|
||||||
|
projected.p[0].x *= 0.5 * state.screen_width;
|
||||||
|
projected.p[0].y *= 0.5 * state.screen_height;
|
||||||
|
|
||||||
|
projected.p[1].x *= 0.5 * state.screen_width;
|
||||||
|
projected.p[1].y *= 0.5 * state.screen_height;
|
||||||
|
|
||||||
|
projected.p[2].x *= 0.5 * state.screen_width;
|
||||||
|
projected.p[2].y *= 0.5 * state.screen_height;
|
||||||
|
|
||||||
|
|
||||||
|
put_triangle(
|
||||||
|
(v2){.x=projected.p[0].x, .y=projected.p[0].y},
|
||||||
|
(v2){.x=projected.p[1].x, .y=projected.p[1].y},
|
||||||
|
(v2){.x=projected.p[2].x, .y=projected.p[2].y},
|
||||||
|
OVERDRAW, 0xFFFFFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
game_init();
|
||||||
|
|
||||||
|
if (engine_init(
|
||||||
|
state.screen_width, state.screen_height, "3D demo",
|
||||||
|
client_poll_events, client_update_framebuffer
|
||||||
|
)) {
|
||||||
|
engine_start();
|
||||||
|
|
||||||
|
engine_stop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
add_executable(game_2048 2048.c)
|
add_executable(game_2048 2048.c)
|
||||||
target_link_libraries(game_2048 PRIVATE dangerzone_engine)
|
target_link_libraries(game_2048 PRIVATE dangerzone_engine)
|
||||||
|
target_link_libraries(game_2048 PRIVATE m)
|
||||||
|
|
||||||
|
add_executable(game_3d 3d.c)
|
||||||
|
target_link_libraries(game_3d PRIVATE dangerzone_engine)
|
||||||
|
target_link_libraries(game_3d PRIVATE m)
|
||||||
|
|
||||||
#add_executable(game_window window.c)
|
#add_executable(game_window window.c)
|
||||||
#target_link_libraries(game_window PRIVATE dangerzone_engine)
|
#target_link_libraries(game_window PRIVATE dangerzone_engine)
|
||||||
|
|||||||
Reference in New Issue
Block a user