Basic Input/Output
We played some optimization tennis with the WASD code, its was stupid.
I still don't know what I'm doing with this repo, maybe I should just make a game about unfinished game projects ... "The minds of Indie Developers"
Regardless though I want some input and some result of that input to appear on screen. I mean that's 99% of the game done at that point isn't it?
So some typing later ...
/* Data Types */
struct transform {
float position[3];
};
struct input_device {
float move_axis[2];
};
struct time {
float delta;
};
struct player {
struct transform tform;
};
struct ground {
struct transform tform;
};
struct game {
/* Platform */
struct input_device input_device;
struct time time;
/* World */
struct player player;
struct ground ground;
};
/* Game loopy functions */
void update_platform(struct game *game);
void update_player(struct game *game);
void update_render(struct game *game);
Now to hook some Raylib so we can get some input, my nice simple wasd controls
void
update_platform(
struct game *game)
{
/* Input Device
*/
uint8_t kw = IsKeyDown(KEY_W);
uint8_t ka = IsKeyDown(KEY_A);
uint8_t ks = IsKeyDown(KEY_S);
uint8_t kd = IsKeyDown(KEY_D);
int8_t mx = kd - ka;
int8_t my = kw - ks;
uint8_t ml = (mx & my) & 1;
/* 1 or (sqrt(2) / 2), we do this so that we dont move faster
* when going diagonal, this is what you'd get if you
* normalized the vector {1, 0, 1}, then asked for its
* length.
*/
float len_rcp = (float[2]) { 1.f, 0.70710678118f }[ml];
float kb_x = mx * len_rcp;
float kb_y = my * len_rcp;
game->input_device = (struct input_device) {
.move_axis = { kb_x, kb_y },
};
/* Timer
*/
game->time = (struct time) {
.delta = GetFrameTime(),
};
}
Sooooo. maybe not as 'simple' as it could be, I should provide some context, some time ago a friend and myself were making a prototype game and for whatever reason we played some optimization tennis with the WASD code, its was stupid, it was fun. (Maybe not a surprise but we never started making the game, let alone finish the prototype).
We got rid of all the branches and the vector normalization code, in a weird way I actually think its a nice example of how to approach optimization, we went from logic to data. And we pushed vector normalization code back in time.
I do personally have a grudge with the seemingly default approach of endless fucking branches that folk seem to have, but that is a rant for another day.
We also need to store the accumulation of the input, with some time logic so it can handle any inconsistent frame times.
void
update_player(
struct game *game)
{
/* Update player based on input
*/
float dt = game->time.delta;
float sp = 10.f;
float ds = dt * sp;
game->player.tform.position[0] += ds * game->input_device.move_axis[0];
game->player.tform.position[2] += ds * game->input_device.move_axis[1];
}
Woo! Now that we have all that, we can reach back into Raylib to render this.
void
update_render(
struct game *game)
{
BeginDrawing();
ClearBackground(RAYWHITE);
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 10.0f, 10.0f };
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
BeginMode3D(camera);
Vector3 cubePosition = {
game->player.tform.position[0],
game->player.tform.position[1],
game->player.tform.position[2]
};
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(10, 1.0f);
EndMode3D();
EndDrawing();
}
Yesh! (Said Sir Sean), it moves!

Early Access incoming.
Shoulda made a Gif then you'd see the sheer amazing level of gameplay.