RyanHub - file viewer
filename: src/core/game.c
branch: main
back to repo
#include "engine.h"
/*
* cool fun little game implementation to show off the workings of our engine
*/

#include "cglm/cglm.h"
#include <stdio.h>
#include <math.h>

float player_colors[MAX_PLAYERS][4] = {
    {1.0f, 0.0f, 0.0f, 1.0f},
    {0.0f, 1.0f, 0.0f, 1.0f},
    {0.0f, 0.0f, 1.0f, 1.0f},
    {1.0f, 1.0f, 0.0f, 1.0f},
    {0.0f, 1.0f, 1.0f, 1.0f},
    {0.1f, 0.0f, 0.1f, 1.0f},
    {0.0f, 0.0f, 0.0f, 1.0f},
    {1.0f, 1.0f, 1.0f, 1.0f},
};

// forward declarations of functions
void update_player(ThingID id);
void render_player(ThingID id);

DEFINE_FIELDS(player_fields,
    { "player_id", FIELD_INT },

    { "rot", FIELD_VEC3 },
    { "pos", FIELD_VEC3 },
    { "vel", FIELD_VEC3 },

    { "shape", FIELD_INT },
    //{ "radius", FIELD_FLOAT },
    { "half_extents", FIELD_VEC3 },
);

DEFINE_THING_TYPE(player_thing, "player", player_fields, update_player, render_player, default_physics);

ThingTypeID player_thing_id = -1;

int active_players[MAX_PLAYERS] = { 0 };
ThingID player_things[MAX_PLAYERS] = { -1 };

char* stored_message[MAX_PLAYERS] = {0};

Model* player_model;
Model* floor_model;

void update_player(ThingID id) { // this is implemented per "thing", all "things"'s update methods are executed once per engine step

    // get inputs, update velocities

    int player_id = thing_get_int(id, "player_id");

    float joy_x = engine_joystick_x(player_id);
    float joy_y = engine_joystick_y(player_id);
    float speed = 0.01f;

    char* last_message = engine_last_message(player_id);
    if (last_message != NULL) {
        if (stored_message[player_id] == NULL || strcmp(last_message, stored_message[player_id]) != 0) {
            printf("player %d says: %s\n", player_id, last_message);
            free(stored_message[player_id]);

            stored_message[player_id] = strdup(last_message);
            if (stored_message[player_id] == NULL) {
                perror("strdup failed");
                exit(1);
            }
        }
    }

    vec3 rot;
    thing_get_vec3(id, "rot", rot);
    vec3 vel;
    thing_get_vec3(id, "vel", vel);

    if (engine_button_pressed(player_id, 'A')) rot[0] += 0.4f;
    if (engine_button_pressed(player_id, 'B')) vel[1] = 0.1f;
    thing_set_vec3(id, "rot", rot);

    float gravity = -0.01f;

    vel[0] = joy_x * speed;
    vel[1] += gravity;
    vel[2] = joy_y * speed;

    thing_set_vec3(id, "vel", vel);
}

void render_player(ThingID id) {
    int pid = thing_get_int(id, "player_id");
    if (!active_players[pid]) return;

    vec3 pos, rot, half_extents;
    thing_get_vec3(id, "pos", pos);
    thing_get_vec3(id, "rot", rot);
    thing_get_vec3(id, "half_extents", half_extents);

    vec3 scale = { half_extents[0] * 2.0f, half_extents[1] * 2.0f, half_extents[2] * 2.0f };

    renderer_draw_model(player_model, NULL, player_colors[pid], pos, rot, scale);

    //printf("ID %d: pos=(%.2f,%.2f,%.2f) half_extents=(%.2f,%.2f,%.2f) render scale=(%.2f,%.2f,%.2f)\n",
    //    id, pos[0], pos[1], pos[2], half_extents[0], half_extents[1], half_extents[2],
    //    scale[0], scale[1], scale[2]);

}

void game_tick() { // this is implemented per game and is called each engine step before thing updates, engine expects this to be implemented
    for (int i = 0; i < MAX_PLAYERS; i++) {
        if (!g_game_state.players[i].connected) {
            if (active_players[i]) {
                thing_destroy(player_things[i]);
                player_things[i] = -1;
                active_players[i] = 0;
            }
        }
        else {
            if (!active_players[i]) {
                ThingID new_player = thing_spawn(player_thing_id);
                if (new_player == -1) {
                    printf("Failed to spawn player %d\n", i);
                    continue;
                }

                thing_set_int(new_player, "player_id", i);
                thing_set_vec3(new_player, "pos", (vec3) { 0.0f, 0.5f, 0.0f });
                thing_set_vec3(new_player, "rot", (vec3) { 0.0f, 0.0f, 0.0f });
                thing_set_vec3(new_player, "vel", (vec3) { 0.0f, 0.0f, 0.0f });

                //thing_set_int(new_player, "shape", COLLISION_SPHERE);
                //thing_set_float(new_player, "radius", 0.2f);                
                thing_set_int(new_player, "shape", COLLISION_BOX);
                thing_set_vec3(new_player, "half_extents", (vec3) {0.5f, 0.5f, 0.5f});


                player_things[i] = new_player;
                active_players[i] = 1;
            }
        }
    }

}

void game_init() {
    player_thing_id = thing_register_type(&player_thing);

    //player_model = model_load("assets/models/sphere-low.obj");
    player_model = model_load("assets/models/cube.obj");

    map_load("assets/maps/test.map");
}

void game_end() {

}