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;
|
8
Entity.h
8
Entity.h
@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include "util/vector.h"
|
||||
#include "Physics_Component.h"
|
||||
#include "Player_Component.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -12,13 +13,12 @@ extern "C" {
|
||||
|
||||
// Entity.
|
||||
typedef struct _Entity {
|
||||
uintptr_t id;
|
||||
uintptr_t type;
|
||||
const char *name;
|
||||
uintptr_t id;
|
||||
char *name;
|
||||
|
||||
Component_Position *position;
|
||||
Component_Hitbox *hitbox;
|
||||
|
||||
Component_Player *player;
|
||||
} Entity;
|
||||
|
||||
|
||||
|
4
Input.c
4
Input.c
@ -1,5 +1,6 @@
|
||||
|
||||
#include "Input.h"
|
||||
#include "App.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
@ -16,8 +17,9 @@ void input_SetDefaultKeymap(System_Input *sys) {
|
||||
sys->systemKeymap[input_Key_Use] = 'L';
|
||||
}
|
||||
|
||||
System_Input *input_NewSystem() {
|
||||
System_Input *input_NewSystem(App *super) {
|
||||
System_Input *sys = malloc(sizeof(System_Input));
|
||||
sys->super = super;
|
||||
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; }
|
||||
|
||||
|
||||
typedef struct _App App;
|
||||
|
||||
typedef struct {
|
||||
App *super;
|
||||
|
||||
input_KeyState keys[input_Key_Count]; // States of keys
|
||||
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
|
||||
@ -55,7 +59,7 @@ typedef struct {
|
||||
|
||||
// Creates a new input system.
|
||||
// Uses a default keymap
|
||||
System_Input *input_NewSystem();
|
||||
System_Input *input_NewSystem(App *super);
|
||||
void input_DeleteSystem(System_Input *sys);
|
||||
|
||||
// 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));
|
||||
sys->super = super;
|
||||
|
||||
sys->pos = tree_Create(sizeof(uintptr_t));
|
||||
sys->hit = tree_Create(sizeof(uintptr_t));
|
||||
|
@ -27,7 +27,8 @@ typedef struct {
|
||||
|
||||
|
||||
// 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
|
||||
// if not, Box is absolute
|
||||
@ -39,21 +40,25 @@ typedef struct {
|
||||
bool fixed;
|
||||
|
||||
physics_HitHandler onHit;
|
||||
void *onHitData;
|
||||
} Component_Hitbox;
|
||||
|
||||
// Returns the absolute version of the hitbox.
|
||||
Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox);
|
||||
|
||||
|
||||
typedef struct _App App;
|
||||
|
||||
// Physics manager
|
||||
typedef struct {
|
||||
App *super;
|
||||
// Every Position & Hitbox components
|
||||
tree_Tree *pos, *hit;
|
||||
vector_Vector *flaggedDelete;
|
||||
} System_Physics;
|
||||
|
||||
// Returns an empty physics system.
|
||||
System_Physics *physics_NewSystem();
|
||||
System_Physics *physics_NewSystem(App *super);
|
||||
// Frees a physics system.
|
||||
void physics_DeleteSystem(System_Physics *sys);
|
||||
|
||||
|
@ -7,15 +7,13 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static const double EPS = 1e-6;
|
||||
|
||||
static inline double dabs(double 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)
|
||||
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;
|
||||
|
||||
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) {
|
||||
// Moves right, hits left edge
|
||||
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
|
||||
|
||||
#include "Types.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -14,21 +15,36 @@ typedef struct _Entity Entity;
|
||||
// Only one entity should have this.
|
||||
typedef struct {
|
||||
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)
|
||||
bool onGround; // If the player is on the ground?
|
||||
bool moveLeft, moveRight; // If the player is moving left/right?
|
||||
} Component_Player;
|
||||
|
||||
|
||||
typedef struct _App App;
|
||||
|
||||
// Player controller instance.
|
||||
// Reads input from the app.
|
||||
typedef struct {
|
||||
App *super;
|
||||
// The player in the world.
|
||||
// Control is paused if equals NULL.
|
||||
Component_Player *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
|
||||
}
|
||||
|
2
Types.c
2
Types.c
@ -9,6 +9,8 @@ static inline double dmax(double x, double y) {
|
||||
return x > y ? x : y;
|
||||
}
|
||||
|
||||
const double EPS = 1e-6;
|
||||
|
||||
|
||||
Vec2 vec2_Add(Vec2 x, Vec2 y) {
|
||||
Vec2 result = {
|
||||
|
Loading…
Reference in New Issue
Block a user