Player & initial app code
This commit is contained in:
parent
658eb5b60c
commit
71228c61a7
13
App.h
Normal file
13
App.h
Normal 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;
|
6
Entity.h
6
Entity.h
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
4
Input.c
4
Input.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
Input.h
6
Input.h
@ -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.
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
80
Player_Component.c
Normal 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;
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
2
Types.c
2
Types.c
@ -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 = {
|
||||||
|
3
Types.h
3
Types.h
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user