#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() {
}