Player & initial app code

This commit is contained in:
Edgaru089 2024-03-01 17:09:24 +08:00
parent 658eb5b60c
commit 71228c61a7
11 changed files with 139 additions and 15 deletions

13
App.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "Entity.h"
#include "Physics_Component.h"
#include "Player_Component.h"
#include "Input.h"
typedef struct _App {
System_Physics *physics;
System_Player *player;
System_Input *input;
} App;

View File

@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include "util/vector.h" #include "util/vector.h"
#include "Physics_Component.h" #include "Physics_Component.h"
#include "Player_Component.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -13,12 +14,11 @@ extern "C" {
// Entity. // Entity.
typedef struct _Entity { typedef struct _Entity {
uintptr_t id; uintptr_t id;
uintptr_t type; char *name;
const char *name;
Component_Position *position; Component_Position *position;
Component_Hitbox *hitbox; Component_Hitbox *hitbox;
Component_Player *player;
} Entity; } Entity;

View File

@ -1,5 +1,6 @@
#include "Input.h" #include "Input.h"
#include "App.h"
#include <stdlib.h> #include <stdlib.h>
#include <windows.h> #include <windows.h>
@ -16,8 +17,9 @@ void input_SetDefaultKeymap(System_Input *sys) {
sys->systemKeymap[input_Key_Use] = 'L'; sys->systemKeymap[input_Key_Use] = 'L';
} }
System_Input *input_NewSystem() { System_Input *input_NewSystem(App *super) {
System_Input *sys = malloc(sizeof(System_Input)); System_Input *sys = malloc(sizeof(System_Input));
sys->super = super;
return sys; return sys;
} }

View File

@ -46,7 +46,11 @@ static inline bool input_IsPressed(input_KeyState state) { return state == Press
static inline bool input_IsReleased(input_KeyState state) { return state == Released || state == JustReleased; } static inline bool input_IsReleased(input_KeyState state) { return state == Released || state == JustReleased; }
typedef struct _App App;
typedef struct { typedef struct {
App *super;
input_KeyState keys[input_Key_Count]; // States of keys input_KeyState keys[input_Key_Count]; // States of keys
unsigned int systemKeymap[input_Key_Count]; // Which system key (VK code) this function uses unsigned int systemKeymap[input_Key_Count]; // Which system key (VK code) this function uses
// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes // https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
@ -55,7 +59,7 @@ typedef struct {
// Creates a new input system. // Creates a new input system.
// Uses a default keymap // Uses a default keymap
System_Input *input_NewSystem(); System_Input *input_NewSystem(App *super);
void input_DeleteSystem(System_Input *sys); void input_DeleteSystem(System_Input *sys);
// Sets the keymaps to default. // Sets the keymaps to default.

View File

@ -24,8 +24,9 @@ Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox) {
} }
System_Physics *physics_NewSystem() { System_Physics *physics_NewSystem(App *super) {
System_Physics *sys = malloc(sizeof(System_Physics)); System_Physics *sys = malloc(sizeof(System_Physics));
sys->super = super;
sys->pos = tree_Create(sizeof(uintptr_t)); sys->pos = tree_Create(sizeof(uintptr_t));
sys->hit = tree_Create(sizeof(uintptr_t)); sys->hit = tree_Create(sizeof(uintptr_t));

View File

@ -27,7 +27,8 @@ typedef struct {
// Handler called when hitboxes are hit // Handler called when hitboxes are hit
typedef void (*physics_HitHandler)(Entity *me, Entity *other, Vec2 triedDelta); typedef void (*physics_HitHandler)(Entity *me, Entity *other, Vec2 triedDelta, void *data);
// Box is relative to Position if exists // Box is relative to Position if exists
// if not, Box is absolute // if not, Box is absolute
@ -39,21 +40,25 @@ typedef struct {
bool fixed; bool fixed;
physics_HitHandler onHit; physics_HitHandler onHit;
void *onHitData;
} Component_Hitbox; } Component_Hitbox;
// Returns the absolute version of the hitbox. // Returns the absolute version of the hitbox.
Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox); Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox);
typedef struct _App App;
// Physics manager // Physics manager
typedef struct { typedef struct {
App *super;
// Every Position & Hitbox components // Every Position & Hitbox components
tree_Tree *pos, *hit; tree_Tree *pos, *hit;
vector_Vector *flaggedDelete; vector_Vector *flaggedDelete;
} System_Physics; } System_Physics;
// Returns an empty physics system. // Returns an empty physics system.
System_Physics *physics_NewSystem(); System_Physics *physics_NewSystem(App *super);
// Frees a physics system. // Frees a physics system.
void physics_DeleteSystem(System_Physics *sys); void physics_DeleteSystem(System_Physics *sys);

View File

@ -7,15 +7,13 @@
#include <stdlib.h> #include <stdlib.h>
static const double EPS = 1e-6;
static inline double dabs(double x) { static inline double dabs(double x) {
return x < 0 ? -x : x; return x < 0 ? -x : x;
} }
static inline void call_hithandler(Entity *me, Entity *other, Vec2 triedDelta) { static inline void call_hithandler(Entity *me, Entity *other, Vec2 triedDelta, void *data) {
if (me->hitbox->onHit) if (me->hitbox->onHit)
me->hitbox->onHit(me, other, triedDelta); me->hitbox->onHit(me, other, triedDelta, data);
} }
@ -34,7 +32,7 @@ void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime) {
continue; continue;
if (box2_Intersects(tohit, box2_OffsetX(mybox, delta), NULL)) { if (box2_Intersects(tohit, box2_OffsetX(mybox, delta), NULL)) {
call_hithandler(e, tohit_comp->super, vec2(delta, 0)); call_hithandler(e, tohit_comp->super, vec2(delta, 0), e->hitbox->onHitData);
if (delta > 0) { if (delta > 0) {
// Moves right, hits left edge // Moves right, hits left edge
double maxdelta = tohit.lefttop.x - mybox.lefttop.x - mybox.size.x; double maxdelta = tohit.lefttop.x - mybox.lefttop.x - mybox.size.x;

80
Player_Component.c Normal file
View File

@ -0,0 +1,80 @@
#include "Player_Component.h"
#include "Entity.h"
#include "App.h"
#include "Input.h"
#include "util/assert.h"
#include <stdlib.h>
static inline double dabs(double x) {
return x < 0.0 ? -x : x;
}
System_Player *player_NewSystem(App *super) {
System_Player *sys = malloc(sizeof(System_Player));
sys->super = super;
return sys;
}
void player_DeleteSystem(System_Player *sys) {
free(sys);
}
static void _player_OnHit(Entity *me, Entity *other, Vec2 triedDelta, void *data) {
ASSERT(me->player && "_player_OnHit called with ME as non-player");
// Moving down
if (triedDelta.y > 0)
me->player->onGround = true;
}
void player_AddEntity(System_Player *sys, Entity *e) {
if (e->player) {
ASSERT(!sys->player && "Two player entities are added! Did you forget to DeleteEntity for player?");
sys->player = e->player;
ASSERT(e->hitbox && "Player does not have Hitbox component");
e->hitbox->onHit = &_player_OnHit;
}
}
void player_DeleteEntity(System_Player *sys, uintptr_t id) {
if (sys->player && sys->player->super->id == id)
sys->player = NULL;
}
static double walkSpeed = 2.0, jumpSpeed = 5.0;
static int airjumpCount = 1;
void player_Advance(System_Player *sys, Duration deltaTime) {
if (!sys->player)
return;
// The bulk of player logic right here
System_Input *input = sys->super->input;
double targetVecX = 0.0;
// Move left/right
if (input_IsPressed(input->keys[input_Key_Left]))
targetVecX += -walkSpeed;
if (input_IsPressed(input->keys[input_Key_Right]))
targetVecX += walkSpeed;
sys->player->super->position->velocity.x = targetVecX;
if (sys->player->onGround)
sys->player->jumpCount = 0;
// Jump
if (sys->super->input->keys[input_Key_Jump] == JustPressed) {
if (sys->player->onGround || sys->player->jumpCount < airjumpCount)
sys->player->super->position->velocity.x = jumpSpeed;
if (!sys->player->onGround) // Took the second clause, airjumped
sys->player->jumpCount++;
}
// Check OnGround again
if (dabs(sys->player->super->position->velocity.y) > EPS)
sys->player->onGround = false;
}

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Types.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -14,6 +15,7 @@ typedef struct _Entity Entity;
// Only one entity should have this. // Only one entity should have this.
typedef struct { typedef struct {
Entity *super; Entity *super;
int jumpCount; // Number of times the player has jumped since leaving ground int jumpCount; // Number of times the player has jumped since leaving ground
// (Initial jump does not count) // (Initial jump does not count)
bool onGround; // If the player is on the ground? bool onGround; // If the player is on the ground?
@ -21,14 +23,28 @@ typedef struct {
} Component_Player; } Component_Player;
typedef struct _App App;
// Player controller instance. // Player controller instance.
// Reads input from the app. // Reads input from the app.
typedef struct { typedef struct {
App *super;
// The player in the world. // The player in the world.
// Control is paused if equals NULL. // Control is paused if equals NULL.
Component_Player *player; Component_Player *player;
} System_Player; } System_Player;
System_Player *player_NewSystem(App *super);
void player_DeleteSystem(System_Player *sys);
// Adds an entity.
void player_AddEntity(System_Player *sys, Entity *e);
// Deletes an entity.
void player_DeleteEntity(System_Player *sys, uintptr_t id);
// Called on every frame.
void player_Advance(System_Player *sys, Duration deltaTime);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -9,6 +9,8 @@ static inline double dmax(double x, double y) {
return x > y ? x : y; return x > y ? x : y;
} }
const double EPS = 1e-6;
Vec2 vec2_Add(Vec2 x, Vec2 y) { Vec2 vec2_Add(Vec2 x, Vec2 y) {
Vec2 result = { Vec2 result = {

View File

@ -55,6 +55,9 @@ TimePoint time_Now();
Duration time_Since(TimePoint prev); Duration time_Since(TimePoint prev);
Duration time_Difference(TimePoint now, TimePoint prev); Duration time_Difference(TimePoint now, TimePoint prev);
// 1e-6
extern const double EPS;
#ifdef __cplusplus #ifdef __cplusplus
} }