#include "main.h" #include "entity.h" #include "input.h" #include "tilemap.h" #include #define from_fixed(a) (a / 16) #define to_fixed(a) (a * 16) #define SIZE 8 #define ACCELERATION 1 #define FRICTION 2 #define MAX_SPEED 12 #define GRAVITY 1 #define JUMP 30 enum { PLAYER_NONE, PLAYER_IDLE, PLAYER_WALK, PLAYER_JUMP, PLAYER_FALL, }; enum { PLAYER_A_IDLE, PLAYER_A_IDLE2, PLAYER_A_WALK, PLAYER_A_WALK2, PLAYER_A_WALK3, PLAYER_A_WALK4, PLAYER_A_JUMP, PLAYER_A_FALL, PLAYER_A_FALL2, }; struct anim player_anims[] = { {PLAYER_A_IDLE2, {0, 0, 16, 16}, 300}, {PLAYER_A_IDLE, {0, 32, 16, 16}, 2}, {PLAYER_A_WALK2, {0, 0, 16, 16}, 6}, {PLAYER_A_WALK3, {16, 0, 16, 16}, 6}, {PLAYER_A_WALK4, {32, 0, 16, 16}, 6}, {PLAYER_A_WALK, {48, 0, 16, 16}, 6}, {PLAYER_A_JUMP, {16, 0, 16, 16}, 300}, {PLAYER_A_FALL2, {32, 0, 16, 16}, 15}, {PLAYER_A_FALL2, {48, 0, 16, 16}, 15}, }; static int move(struct entity *self) { int on_ground = false; int dx = (input_right(input_now) - input_left(input_now)) * ACCELERATION; self->velocity.x += dx; if (dx == 0) { if (self->velocity.x < -FRICTION) { self->velocity.x += FRICTION; } else if (self->velocity.x > FRICTION) { self->velocity.x -= FRICTION; } else { self->velocity.x = 0; } } if (self->velocity.x > MAX_SPEED) { self->velocity.x = MAX_SPEED; } else if (self->velocity.x < -MAX_SPEED) { self->velocity.x = -MAX_SPEED; } self->x += self->velocity.x; if (collision_solid(tilemap_area(tilemap, from_fixed(self->x), from_fixed(self->y), from_fixed(self->x) + SIZE, from_fixed(self->y) + SIZE))) { if (self->velocity.x < 0) { self->x += to_fixed(8) - ((self->x) % to_fixed(8)); // left } else if (self->velocity.x == 0) { //fputs("what?\n", stderr); } else { self->x -= ((self->x + to_fixed(SIZE)) % to_fixed(8)); // right } self->velocity.x = 0; } if (self->velocity.x < 0) { self->facing = -1; } else if (self->velocity.x > 0) { self->facing = +1; } self->velocity.y += GRAVITY; self->y += self->velocity.y; //self->y += (input_down(input_now) - input_up(input_now)) * 8; if (collision_solid(tilemap_area(tilemap, from_fixed(self->x), from_fixed(self->y), from_fixed(self->x) + SIZE, from_fixed(self->y) + SIZE))) { if (self->velocity.y < 0) { self->y += to_fixed(8) - ((self->y) % to_fixed(8)); // up self->velocity.y = 0; } else if (self->velocity.y == 0) { //fputs("what?\n", stderr); } else { self->y -= ((self->y + to_fixed(SIZE)) % to_fixed(8)); // down self->velocity.y = to_fixed(1); // crazy but it works on_ground = true; } } self->hitbox.left = self->x; self->hitbox.right = self->x + SIZE; self->hitbox.top = self->y; self->hitbox.bottom = self->y + SIZE; return on_ground; } void anim(struct entity *self, unsigned anim) { self->anim = player_anims[anim]; } static int player_update(struct entity *self) { switch (self->state) { case PLAYER_IDLE: if (move(self) == false) { anim(self, PLAYER_A_FALL); self->state = PLAYER_FALL; } if (input_right(input_now) - input_left(input_now)) { anim(self, PLAYER_A_WALK); self->state = PLAYER_WALK; } if (input_a(input_now)) { self->velocity.y = -JUMP; anim(self, PLAYER_A_JUMP); self->state = PLAYER_JUMP; } break; case PLAYER_WALK: if (move(self) == false) { anim(self, PLAYER_A_FALL); self->state = PLAYER_FALL; } if (!(input_right(input_now) - input_left(input_now))) { anim(self, PLAYER_A_IDLE); self->state = PLAYER_IDLE; } if (input_a(input_now)) { self->velocity.y = -JUMP; anim(self, PLAYER_A_JUMP); self->state = PLAYER_JUMP; } break; case PLAYER_JUMP: if (!input_a(input_now)) { self->velocity.y /= 2; anim(self, PLAYER_A_FALL); self->state = PLAYER_FALL; } if (self->velocity.y > 0) { anim(self, PLAYER_A_FALL); self->state = PLAYER_FALL; } if (move(self) == true) { anim(self, PLAYER_A_IDLE); self->state = PLAYER_IDLE; } break; case PLAYER_FALL: if (move(self) == true) { anim(self, PLAYER_A_IDLE); self->state = PLAYER_IDLE; } break; } self->anim.length--; if (self->anim.length == 0) { anim(self, self->anim.frame); } return 0; } static int player_hurt(struct entity *self, int damage) { return 0; } static int player_draw(struct entity *self, int camX, int camY) { SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_Rect rect = self->anim.rect; if (self->facing == -1) { rect.y += 16; } SDL_RenderCopy(renderer, self->texture, &rect, &(SDL_Rect) {from_fixed(self->x) - camX - 4, from_fixed(self->y) - camY - 4, 16, 16}); return 0; } struct entity *player_new(void) { player[0] = (struct entity) { .update = player_update, .hurt = player_hurt, .draw = player_draw, .x = 0, .y = 0, .velocity = {.x = 0, .y = 0}, .hitbox = { 0, 0, 0, 0, }, .state = PLAYER_IDLE, .hp = 3, .timer = 0, .facing = 1, .iframes = 0, .texture = NULL, .ext = NULL, }; anim(player, PLAYER_A_IDLE); player[0].texture = res_get_texture("fywi").data; return player + 0; } int player_property(struct entity *const restrict self, char const *const restrict property, char const *const restrict value) { if (strcmp(property, "x") == 0) { self->x = to_fixed(atoi(value)); } else if (strcmp(property, "y") == 0) { self->y = to_fixed(atoi(value)); } else { return 1; } return 0; }