#include #include #include #include #include "pacman.h" #include "collision.h" #include "import_resources.h" #define PACMAN_SPEED 261 #define PACMAN_SIDE 40 #define EDGE_TURN_LIMIT 5 extern const Uint8* keyboard; SDL_Rect* get_colliding_tile_raw(SDL_Rect*, struct map* map); SDL_Rect* get_colliding_tile(struct pacman* pacman, struct map* map); void rect_step_one_pixel(SDL_Rect* r, enum facing); void init_pacman(struct pacman* pacman, struct pacman_init* init) { for(int i = 0; i < 4; i++) init_animation(&pacman->animations[i], &(struct animation_init){ .spritesheet_texture = character_spritesheet, .initial_angle = 90.0 * i, .initial_frame_count = 3, .initial_frame_times = (float[]){0.05, 0.05, 0.05}, .initial_frames = (SDL_Rect[]) { { .x = 0, .y = 285, .w = 180, .h = 195 }, { .x = 240, .y = 285, .w = 180, .h = 195 }, { .x = 465, .y = 285, .w = 195, .h = 195 } } }); pacman->facing = init->initial_facing; pacman->xpos = init->initial_xpos; pacman->ypos = init->initial_ypos; } void handle_pacman_input(struct pacman* pacman, struct map* map) { SDL_Rect r = { .x = pacman->xpos, .y = pacman->ypos, .w = PACMAN_SIDE, .h = PACMAN_SIDE }; if(keyboard[SDL_SCANCODE_UP] && pacman->facing != FACING_UP) { r.y--; for(int i = 0; i < EDGE_TURN_LIMIT + 1; i++) { if(get_colliding_tile_raw(&r, map) == NULL) { pacman->xpos = r.x; pacman->facing = FACING_UP; break; } rect_step_one_pixel(&r, pacman->facing); } } else if(keyboard[SDL_SCANCODE_DOWN] && pacman->facing != FACING_DOWN) { r.y++; for(int i = 0; i < EDGE_TURN_LIMIT + 1; i++) { if(get_colliding_tile_raw(&r, map) == NULL) { pacman->xpos = r.x; pacman->facing = FACING_DOWN; break; } rect_step_one_pixel(&r, pacman->facing); } } else if(keyboard[SDL_SCANCODE_LEFT] && pacman->facing != FACING_LEFT) { r.x--; for(int i = 0; i < EDGE_TURN_LIMIT + 1; i++) { if(get_colliding_tile_raw(&r, map) == NULL) { pacman->ypos = r.y; pacman->facing = FACING_LEFT; break; } rect_step_one_pixel(&r, pacman->facing); } } else if(keyboard[SDL_SCANCODE_RIGHT] && pacman->facing != FACING_RIGHT) { r.x++; for(int i = 0; i < EDGE_TURN_LIMIT + 1; i++) { if(get_colliding_tile_raw(&r, map) == NULL) { pacman->ypos = r.y; pacman->facing = FACING_RIGHT; break; } rect_step_one_pixel(&r, pacman->facing); } } } void update_pacman(struct pacman* pacman, float dt, struct map* map) { handle_pacman_input(pacman, map); if(pacman->facing == FACING_UP) { pacman->ypos -= PACMAN_SPEED * dt; SDL_Rect* colliding_tile = get_colliding_tile(pacman, map); if(colliding_tile != NULL) { pacman->ypos = colliding_tile->y + colliding_tile->h; } else { update_animation(&pacman->animations[pacman->facing], dt); } } else if(pacman->facing == FACING_DOWN) { pacman->ypos += PACMAN_SPEED * dt; SDL_Rect* colliding_tile = get_colliding_tile(pacman, map); if(colliding_tile != NULL) { pacman->ypos = colliding_tile->y - PACMAN_SIDE; } else { update_animation(&pacman->animations[pacman->facing], dt); } } else if(pacman->facing == FACING_LEFT) { pacman->xpos -= PACMAN_SPEED * dt; SDL_Rect* colliding_tile = get_colliding_tile(pacman, map); if(colliding_tile != NULL) { pacman->xpos = colliding_tile->x + colliding_tile->w; } else { update_animation(&pacman->animations[pacman->facing], dt); } } else if(pacman->facing == FACING_RIGHT) { pacman->xpos += PACMAN_SPEED * dt; SDL_Rect* colliding_tile = get_colliding_tile(pacman, map); if(colliding_tile != NULL) { pacman->xpos = colliding_tile->x - PACMAN_SIDE; } else { update_animation(&pacman->animations[pacman->facing], dt); } } } void draw_pacman(struct demo* demo, const struct pacman* pacman) { const struct animation* current_animation = &pacman->animations[pacman->facing]; SDL_Rect d_rect = { .x = pacman->xpos, .y = pacman->ypos, .w = PACMAN_SIDE, .h = PACMAN_SIDE }; draw_animation(demo, current_animation, &d_rect); } SDL_Rect* get_colliding_tile(struct pacman* pacman, struct map* map) { SDL_Rect r = (SDL_Rect){ .x = pacman->xpos, .y = pacman->ypos, .w = PACMAN_SIDE, .h = PACMAN_SIDE }; return get_colliding_tile_raw(&r, map); } SDL_Rect* get_colliding_tile_raw(SDL_Rect* r, struct map* map) { for(int i = 0; i < map->collider_count; i++) { if(is_colliding(r, &map->colliders[i])) { return &map->colliders[i]; } } return NULL; } void rect_step_one_pixel(SDL_Rect* r, enum facing facing) { switch(facing) { case FACING_UP: r->y--; break; case FACING_DOWN: r->y++; break; case FACING_LEFT: r->x--; break; case FACING_RIGHT: r->x++; break; } }