diff --git a/src/core/bridge.c b/src/core/bridge.c index 02a9840..35f2304 100644 --- a/src/core/bridge.c +++ b/src/core/bridge.c @@ -35,6 +35,7 @@ w_bridge *create_bridge() { td->player->position = (Vector2){ .x = (td->chunk_group->position + CHUNK_GROUP_MID_LEN) * CHUNK_W * CUBE_W, .y = CHUNK_MID_H * CUBE_H}; + td->player->collision = (w_collision){0}; td->camera = malloc(sizeof(Camera2D)); if (td->camera == NULL) { @@ -95,79 +96,62 @@ void destroy_bridge(w_bridge *td) { } void physics_update(w_bridge *td) { - if (td->keyboard->left) { - if (td->player->src.width > 0) { - td->player->src.width = -td->player->src.width; - } - td->player->velocity.x -= 1; - } else if (td->keyboard->right) { - if (td->player->src.width < 0) { - td->player->src.width = -td->player->src.width; - } - td->player->velocity.x += 1; - } - - if (td->keyboard->left || td->keyboard->right || !td->player->is_onground) { + update_player_input(td->player, td->keyboard); - if (!td->player->is_onground) { - td->player->velocity.y += 1; - } else { - td->player->velocity.y = 1; - td->player->is_onground = false; - } + if (td->player->velocity.x != 0 || td->player->velocity.y != 0) { + /* td->player->velocity = Vector2Normalize(td->player->velocity); - td->player->position = Vector2Add( + */ + td->player->velocity.x = Clamp( + td->player->velocity.x, -MAX_PLAYER_VELOCITY_X, MAX_PLAYER_VELOCITY_X); + td->player->velocity.y = Clamp( + td->player->velocity.y, -MAX_PLAYER_VELOCITY_Y, MAX_PLAYER_VELOCITY_Y); + + Vector2 next_position = Vector2Add( td->player->position, Vector2Scale(td->player->velocity, PLAYER_SPEED * PHYSICS_TICK)); + td->player->velocity = Vector2Scale(td->player->velocity, PLAYER_FRICTION); + + Rectangle player_rect = (Rectangle){.x = next_position.x, + .y = next_position.y, + .width = td->player->dst.width, + .height = td->player->dst.height}; + + td->player->collision = (w_collision){0}; + unsigned int count = 0; + for (size_t i = 0; i < td->chunk_view->len; i++) { + Rectangle block_rect = td->chunk_view->blocks[i].dst; - if (!td->player->is_onground) { - Rectangle player_rect = {td->player->position.x, td->player->position.y, - td->player->dst.width, td->player->dst.height}; - for (size_t i = 0; i < td->chunk_view->len; i++) { - - Rectangle block_rect = td->chunk_view->blocks[i].dst; - if (CheckCollisionRecs(player_rect, block_rect)) { - /* - td->player->position = Vector2Subtract( - td->player->position, - Vector2Scale(td->player->velocity, PLAYER_SPEED * PHYSICS_TICK)); - */ - - if (td->player->position.y + td->player->dst.height >= block_rect.y) { - td->player->is_onground = true; - td->player->position.y = block_rect.y - td->player->dst.height; - td->player->velocity.y = 0; - } - if (td->player->position.x + td->player->dst.width >= block_rect.x && - td->player->position.x <= block_rect.x + block_rect.width) { - td->player->velocity.x = 0; - } + if (CheckCollisionRecs(player_rect, block_rect)) { + + // TODO: implement collision detection + // + // + // check if the collision is on left: + // if left -> set stop on left + // => stop velocity x + // => set collision at left(true) and set right(false) + // => set player position to be the right side of the block + + // etc... + + count++; + if (count >= 3) { break; } } } - td->camera_target = center_camera_on_object( - td->camera, (Rectangle){.x = td->player->position.x, - .y = td->player->position.y, - .width = td->player->dst.width, - .height = td->player->dst.height}); - } - - td->player->animation += PHYSICS_TICK; - td->player->velocity = Vector2Scale(td->player->velocity, 0.9f); - if (abs(td->player->velocity.x) > 0.1f || td->keyboard->key != 0) { - if (td->player->animation > PHYSICS_TICK * 2) { - td->player->animation = 0; - td->player->state = (td->player->state == P_WALK_1) ? P_WALK_2 : P_WALK_1; - } - } else { - if (td->player->animation > PHYSICS_TICK * 12) { - td->player->animation = 0; - td->player->state = (td->player->state == P_IDLE_1) ? P_IDLE_2 : P_IDLE_1; + if (td->player->collision.all == 0) { + td->player->position = next_position; } + td->camera_target = get_camera_target_player(td->player, td->camera); + + LOG("velocity: %f, %f", td->player->velocity.x, td->player->velocity.y); } + + animate_player(td->player, PHYSICS_TICK, td->keyboard->key != 0); clear_keyboard(td->keyboard); } diff --git a/src/core/keyboard.c b/src/core/keyboard.c index c40ca75..eceb60a 100644 --- a/src/core/keyboard.c +++ b/src/core/keyboard.c @@ -3,8 +3,7 @@ void update_keyboard(w_keyboard *kb) { kb->left = IsKeyDown(KEY_LEFT); kb->right = IsKeyDown(KEY_RIGHT); - kb->space = IsKeyDown(KEY_SPACE); - kb->shift = IsKeyDown(KEY_LEFT_SHIFT); + kb->jump = IsKeyDown(KEY_SPACE); } void clear_keyboard(w_keyboard *kb) { kb->key = 0; } diff --git a/src/core/keyboard.h b/src/core/keyboard.h index 6d01db1..7543a2e 100644 --- a/src/core/keyboard.h +++ b/src/core/keyboard.h @@ -4,8 +4,7 @@ #pragma pack(push, 1) typedef union w_keyboard { struct { - unsigned int space : 1; - unsigned int shift : 1; + unsigned int jump : 1; unsigned int left : 1; unsigned int right : 1; }; diff --git a/src/core/view.c b/src/core/view.c index 4a5b82e..e91ae2f 100644 --- a/src/core/view.c +++ b/src/core/view.c @@ -26,3 +26,37 @@ void smooth_rect(Rectangle *box, Rectangle target, float move) { smooth_float(box->x, target.x, move); smooth_float(box->y, target.y, move); } + +Vector2 get_collision_resolution(w_collision *bc, Rectangle self_rect, + Rectangle other_rect) { + Vector2 resolution = VEC_ZERO; + float overlapX = 0.0f, overlapY = 0.0f; + + bc->left = self_rect.x < other_rect.x + other_rect.width && + self_rect.x + self_rect.width > other_rect.x; + bc->right = self_rect.x + self_rect.width > other_rect.x && + self_rect.x < other_rect.x; + bc->top = self_rect.y < other_rect.y + other_rect.height && + self_rect.y + self_rect.height > other_rect.y; + bc->bottom = self_rect.y + self_rect.height > other_rect.y && + self_rect.y < other_rect.y; + + if (bc->left && !bc->right) { + overlapX = other_rect.x + other_rect.width - self_rect.x; + } else if (!bc->left && bc->right) { + overlapX = other_rect.x - (self_rect.x + self_rect.width); + } + if (bc->top && !bc->bottom) { + overlapY = other_rect.y + other_rect.height - self_rect.y; + } else if (!bc->top && bc->bottom) { + overlapY = other_rect.y - (self_rect.y + self_rect.height); + } + + if (fabsf(overlapX) < fabsf(overlapY)) { + resolution.x = overlapX; + } else { + resolution.y = overlapY; + } + + return resolution; +} diff --git a/src/core/view.h b/src/core/view.h index b7f02ea..59e732b 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -1,6 +1,18 @@ #pragma once #include "../stdafx.h" +#pragma pack(push, 1) +typedef struct w_collision { + struct { + bool left : 1; + bool right : 1; + bool top : 1; + bool bottom : 1; + }; + uint8_t all; +} w_collision; +#pragma pack(pop) + #define smooth_float(current, target, speed) \ current = (current < target) ? fmin(current + speed, target) \ : fmax(current - speed, target); @@ -8,5 +20,9 @@ Vector2 center_camera_on_object(Camera2D *camera, Rectangle box); Vector2 center_object_on_camera(Rectangle box, Camera2D *camera); Rectangle get_camera_view(Camera2D *camera); + void smooth_vec(Vector2 *position, Vector2 target, float move); void smooth_rect(Rectangle *box, Rectangle target, float move); + +Vector2 get_collision_resolution(w_collision *bc, Rectangle box, + Rectangle target); diff --git a/src/entities/player.c b/src/entities/player.c new file mode 100644 index 0000000..08dd105 --- /dev/null +++ b/src/entities/player.c @@ -0,0 +1,46 @@ +#include "player.h" + +void animate_player(w_player *player, float dt, bool should_walk) { + player->animation += dt; + if (abs(player->velocity.x) > 0.01f || should_walk) { + if (player->animation > dt * 2) { + player->animation = 0; + player->state = (player->state == P_WALK_1) ? P_WALK_2 : P_WALK_1; + } + } else { + if (player->animation > dt * 12) { + player->animation = 0; + player->state = (player->state == P_IDLE_1) ? P_IDLE_2 : P_IDLE_1; + } + } +} + +void update_player_input(w_player *player, w_keyboard *keyboard) { + if (keyboard->left && !player->collision.left) { + if (player->src.width > 0) { + player->src.width = -player->src.width; + } + player->velocity.x -= 1; + } else if (keyboard->right && !player->collision.right) { + if (player->src.width < 0) { + player->src.width = -player->src.width; + } + player->velocity.x += 1; + } + + /* + if (keyboard->jump && player->collision.bottom) { + player->velocity.y -= 10; + } else if (!player->collision.bottom) { + player->velocity.y += 1; + } + */ +} + +Vector2 get_camera_target_player(w_player *player, Camera2D *camera) { + return center_camera_on_object(camera, + (Rectangle){.x = player->position.x, + .y = player->position.y, + .width = player->dst.width, + .height = player->dst.height}); +} diff --git a/src/entities/player.h b/src/entities/player.h index b90c283..b5edcce 100644 --- a/src/entities/player.h +++ b/src/entities/player.h @@ -1,9 +1,16 @@ #pragma once +#include "../core/keyboard.h" #include "../core/state.h" +#include "../core/view.h" #include "../stdafx.h" #include "../terrain/chunk_view.h" #define PLAYER_SPEED 1000.f +#define PLAYER_JUMP 10.f +#define PLAYER_FRICTION 0.8f +#define MAX_PLAYER_VELOCITY_X 1.f +#define MAX_PLAYER_VELOCITY_Y 10.f + #define PLAYER_SRC_RECT \ (Rectangle) { 0, 0, 8, 16 } @@ -24,7 +31,10 @@ typedef struct w_player { float delay; float animation; - unsigned int nearest_y; - bool is_onground; + w_collision collision; w_playerstate state; } w_player; + +void animate_player(w_player *player, float dt, bool should_walk); +void update_player_input(w_player *player, w_keyboard *keyboard); +Vector2 get_camera_target_player(w_player *player, Camera2D *camera); diff --git a/src/screen/game.c b/src/screen/game.c index fc4c294..a521d38 100644 --- a/src/screen/game.c +++ b/src/screen/game.c @@ -40,23 +40,10 @@ void game_screen(w_state *state) { BeginMode2D(*(td->camera)); smooth_vec(&td->camera->target, td->camera_target, speed); for (unsigned int i = 0; i < td->chunk_view->len; i++) { - - bool is_current = round(td->player->position.x / FULL_CHUNK_W) == - round(td->chunk_view->blocks[i].dst.x / FULL_CHUNK_W); - bool is_hover = round(td->player->position.x / CUBE_W) == - round(td->chunk_view->blocks[i].dst.x / CUBE_W); - DrawTexturePro(block_textures[td->chunk_view->blocks[i].block.type - 1], td->chunk_view->blocks[i].src, - td->chunk_view->blocks[i].dst, VEC_ZERO, 0, - // WHITE); - is_current ? (is_hover ? BLUE : GREEN) - : (is_hover ? GREEN : WHITE)); + td->chunk_view->blocks[i].dst, VEC_ZERO, 0, WHITE); } - /* - DrawRectangleLines(td->player->position.x, td->player->position.y, - td->player->dst.width, td->player->dst.height, RED); - */ EndMode2D(); DrawTexturePro(player_textures[td->player->state], td->player->src, td->player->dst, VEC_ZERO, 0, WHITE); diff --git a/src/terrain/chunk.c b/src/terrain/chunk.c index bd4b377..0bea7d0 100644 --- a/src/terrain/chunk.c +++ b/src/terrain/chunk.c @@ -29,7 +29,7 @@ void *create_chunk_thread(void *arg) #endif // _WIN32 { if (!arg) - return; + return EXIT_FAILURE; LOG("creating chunk"); w_chunk *chunk = arg; diff --git a/wispy-c.vcxproj b/wispy-c.vcxproj index a279cfc..29bb8da 100644 --- a/wispy-c.vcxproj +++ b/wispy-c.vcxproj @@ -331,6 +331,7 @@ +