This repository has been archived on 2025-02-04. You can view files and clone it, but cannot push or open issues or pull requests.
helpless/oogabooga/examples/tile_game.c

183 lines
No EOL
5.1 KiB
C

#define X_TILE_COUNT 128
#define Y_TILE_COUNT 128
#define TILE_WIDTH 64
#define TILE_HEIGHT 64
#define TILE_COUNT (TILE_WIDTH * TILE_HEIGHT)
#define WORLD_WIDTH (X_TILE_COUNT * TILE_WIDTH)
#define WORLD_HEIGHT (Y_TILE_COUNT * TILE_HEIGHT)
#define Z_LAYER_TILE_GRID -1
#define Z_LAYER_TILE_LAYER_BASE 100
#define Z_LAYER_EDITOR_GUI 200
#define MAX_LAYERS 6
typedef struct Tile_Layer {
Gfx_Image *tile_images[TILE_COUNT];
} Tile_Layer;
Tile_Layer tile_layers[MAX_LAYERS] = {0};
u64 get_tile_index(s32 x, s32 y) {
return y * X_TILE_COUNT + x;
}
u64 get_tile_index_from_pos(Vector2 p) {
s32 x = (s32)((p.x/WORLD_WIDTH)*X_TILE_COUNT);
s32 y = (s32)((p.y/WORLD_HEIGHT)*Y_TILE_COUNT);
return get_tile_index(x, y);
}
typedef enum {
APP_STATE_EDITING,
APP_STATE_PLAYING
} App_State;
float32 delta_time = 0;
App_State app_state = APP_STATE_EDITING;
s64 current_tile_layer = 0;
Matrix4 camera_view;
void update_editor();
void update_game();
int entry(int argc, char **argv) {
window.title = STR("Tile game");
window.scaled_width = 1280; // We need to set the scaled size if we want to handle system scaling (DPI)
window.scaled_height = 720;
window.x = 200;
window.y = 90;
window.clear_color = hex_to_rgba(0x6495EDff);
camera_view = m4_scalar(1.0);
float64 last_time = os_get_current_time_in_seconds();
while (!window.should_close) {
reset_temporary_storage();
draw_frame.projection = m4_make_orthographic_projection(window.pixel_width * -0.5, window.pixel_width * 0.5, window.pixel_height * -0.5, window.pixel_height * 0.5, -1, 10);
draw_frame.enable_z_sorting = true;
float64 now = os_get_current_time_in_seconds();
delta_time = (float32)(now - last_time);
last_time = now;
if (app_state == APP_STATE_EDITING) {
update_editor();
} else if (app_state == APP_STATE_PLAYING) {
update_game();
}
os_update();
gfx_update();
}
return 0;
}
Vector2 screen_to_world(Vector2 screen) {
Matrix4 proj = draw_frame.projection;
Matrix4 view = draw_frame.view;
float window_w = window.width;
float window_h = window.height;
// Normalize the mouse coordinates
float ndc_x = (screen.x / (window_w * 0.5f)) - 1.0f;
float ndc_y = (screen.y / (window_h * 0.5f)) - 1.0f;
// Transform to world coordinates
Vector4 world_pos = v4(ndc_x, ndc_y, 0, 1);
world_pos = m4_transform(m4_inverse(proj), world_pos);
world_pos = m4_transform(view, world_pos);
return world_pos.xy;
}
Vector2 get_mouse_world_pos() {
return screen_to_world(v2(input_frame.mouse_x, input_frame.mouse_y));
}
void update_editor() {
const float32 cam_move_speed = 400.0;
Vector2 cam_move_axis = v2(0, 0);
if (is_key_down('A')) {
cam_move_axis.x -= 1.0;
}
if (is_key_down('D')) {
cam_move_axis.x += 1.0;
}
if (is_key_down('S')) {
cam_move_axis.y -= 1.0;
}
if (is_key_down('W')) {
cam_move_axis.y += 1.0;
}
Vector2 cam_move = v2_mulf(cam_move_axis, delta_time * cam_move_speed);
camera_view = m4_translate(camera_view, v3(v2_expand(cam_move), 0));
draw_frame.view = camera_view;
Vector2 bottom_left = screen_to_world(v2(-window.width/2, -window.height/2));
Vector2 top_right = screen_to_world(v2( window.width/2, window.height/2));
Vector2 origin = v2(-WORLD_WIDTH/2, -WORLD_HEIGHT/2);
int first_visible_tile_x = ((origin.x + bottom_left.x)/WORLD_WIDTH) *X_TILE_COUNT;
int first_visible_tile_y = ((origin.y + bottom_left.y)/WORLD_HEIGHT)*Y_TILE_COUNT;
int last_visible_tile_x = ((origin.x + top_right.x )/WORLD_WIDTH) *X_TILE_COUNT;
int last_visible_tile_y = ((origin.y + top_right.y )/WORLD_HEIGHT)*Y_TILE_COUNT;
// Visualize empty tile grid & react to mouse
push_z_layer(Z_LAYER_TILE_GRID);
for (s32 tile_x = first_visible_tile_x; tile_x <= last_visible_tile_x; tile_x += 1) {
for (s32 tile_y = first_visible_tile_y; tile_y <=last_visible_tile_y; tile_y += 1) {
bool variation = (tile_x%2==0 && tile_y%2==1) || (tile_x%2==1 && tile_y%2==0);
Vector2 pos = v2_add(origin, v2(tile_x*TILE_WIDTH, tile_y*TILE_HEIGHT));
draw_rect(pos, v2(TILE_WIDTH, TILE_HEIGHT), variation?v4(.27,.27,.27,1):v4(.3,.3,.3,1));
push_z_layer(Z_LAYER_EDITOR_GUI);
float left = pos.x;
float bottom = pos.y;
float right = left + TILE_WIDTH;
float top = bottom + TILE_HEIGHT;
Vector2 m = get_mouse_world_pos();
bool hovered = m.x >= left && m.x < right && m.y >= bottom && m.y < top;
if (hovered) {
draw_rect(pos, v2(TILE_WIDTH, TILE_HEIGHT), v4(0, 0, 0, 0.3));
}
pop_z_layer();
}
}
pop_z_layer();
for (int i = 0; i < MAX_LAYERS; i++) {
Tile_Layer *layer = &tile_layers[i];
push_z_layer(Z_LAYER_TILE_LAYER_BASE + i);
Vector2 origin = v2(-WORLD_WIDTH/2, -WORLD_HEIGHT/2);
for (s32 tile_x = first_visible_tile_x; tile_x <= last_visible_tile_x; tile_x += 1) {
for (s32 tile_y = first_visible_tile_y; tile_y <=last_visible_tile_y; tile_y += 1) {
Gfx_Image *img = layer->tile_images[get_tile_index(tile_x, tile_y)];
if (img) {
Vector2 pos = v2_add(origin, v2(tile_x*TILE_WIDTH, tile_y*TILE_HEIGHT));
draw_image(img, pos, v2(TILE_WIDTH, TILE_HEIGHT), COLOR_WHITE);
}
}
}
pop_z_layer();
}
}
void update_game() {
}