diff --git a/src/gamestates/overworld.py b/src/gamestates/overworld.py index 3695082..80de12b 100644 --- a/src/gamestates/overworld.py +++ b/src/gamestates/overworld.py @@ -4,12 +4,16 @@ import controls import gamestate import math -from objects import BalthasarRenderer, OverworldMap, DIR_UP, DIR_LEFT, DIR_DOWN, DIR_RIGHT +from objects import BalthasarRenderer, OverworldMap, TestObject, DIR_UP, DIR_LEFT, DIR_DOWN, DIR_RIGHT, B_SPRITE_HEIGHT WALK_SPEED = 48 balthasar = BalthasarRenderer() overworld = OverworldMap() +objects = [ + TestObject(0,16), + balthasar +] btrans_active = False btrans_timer = 0 @@ -17,6 +21,28 @@ btrans_sound = None BTRANS_PULSE_DUR = 0.25 BTRANS_DURATION = 0.75 +def aabb_check(left1, bottom1, right1, top1, + left2, bottom2, right2, top2): + return ( + left1 < right2 and + right1 > left2 and + bottom1 < top2 and + top1 > bottom2 + ) + +def get_feet_aabb(world_x, world_y, width, height): + """Returns the world-space AABB of the feet collision box.""" + feet_offset_y = (B_SPRITE_HEIGHT - height) / 2 + box_center_y = world_y - feet_offset_y + + left = world_x - (width / 2) + right = world_x + (width / 2) - 1 + bottom = box_center_y - (height / 2) + top = box_center_y + (height / 2) - 1 + + return left, bottom, right, top + + def start_battle(battle_id): global btrans_active, btrans_timer, btrans_sound gamestate.gamestates["battle"].battle_id = battle_id @@ -78,19 +104,26 @@ def update(game, dt): walking = True balthasar.set_walking(walking) + cur_x, cur_y = overworld.get_player_world_pos(game) + balthasar.y = cur_y if walking: - # Get current world position - cur_x, cur_y = overworld.get_player_world_pos(game) - - # Define collision box dimensions for Balthasar (e.g., 12 width, 10 height at feet) box_w = 12 - box_h = 10 + box_h = 14 # Test and apply X movement independently (Slide on walls) if dx != 0: next_x = cur_x + dx - if overworld.is_box_walkable(next_x, cur_y, box_w, box_h): + feet_aabb = get_feet_aabb(next_x, cur_y, box_w, box_h) + can_move = False + if overworld.is_box_walkable(*feet_aabb): + can_move = True + + for o in objects: + if aabb_check(*feet_aabb, *o.get_aabb()): + can_move = False + + if can_move: overworld.scroll_x -= dx # Note: scroll moves inverse to world pos change # Re-fetch current world pos after potential X movement update @@ -99,10 +132,22 @@ def update(game, dt): # Test and apply Y movement independently if dy != 0: next_y = cur_y + dy - if overworld.is_box_walkable(cur_x, next_y, box_w, box_h): + feet_aabb = get_feet_aabb(cur_x, next_y, box_w, box_h) + can_move = False + if overworld.is_box_walkable(*feet_aabb): + can_move = True + + for o in objects: + if aabb_check(*feet_aabb, *o.get_aabb()): + can_move = False + + if can_move: overworld.scroll_y -= dy # Note: scroll moves inverse to world pos change # !!! CHATGPT VÉGE !!! def draw(game): overworld.render(game) - balthasar.render(game) + + trans = overworld.get_translation(game) + for o in sorted(objects, key=lambda o: o.y, reverse=True): + o.render(game, trans) \ No newline at end of file diff --git a/src/objects.py b/src/objects.py index c9d005c..8225cc2 100644 --- a/src/objects.py +++ b/src/objects.py @@ -17,6 +17,10 @@ class BalthasarRenderer: self.direction = DIR_UP self.walking = False self.anim_timer = 0 + self.x = 0 + self.y = 0 + self.w = B_SPRITE_WIDHT + self.h = B_SPRITE_HEIGHT def set_direction(self, direction): self.direction = direction @@ -26,12 +30,15 @@ class BalthasarRenderer: if walking == False: self.anim_timer = 0 + def get_aabb(self): + return 0, 0, 0, 0 + def update(self): self.anim_timer += 1 if self.anim_timer > 30: self.anim_timer = 0 - def render(self, game): + def render(self, game, _): sprite_h = self.direction if self.direction < 3 else 2 sprite_v = 1 if (self.walking and self.anim_timer <= 15) else 0 flip_h = self.direction == DIR_LEFT @@ -106,22 +113,15 @@ class OverworldMap: return OVERWORLD_MAP[OVERWORLD_HEIGHT - 1 - tile_y][tile_x] return None # Out of bounds / wall - def is_box_walkable(self, world_x, world_y, width, height): + def is_box_walkable(self, left, bottom, right, top): """Checks if a bounding box (e.g., player's feet) is entirely on walkable tiles.""" - feet_offset_y = (B_SPRITE_HEIGHT - height) / 2 - box_center_y = world_y - feet_offset_y - - left = world_x - (width / 2) - right = world_x + (width / 2) - 1 - bottom = box_center_y - (height / 2) - top = box_center_y + (height / 2) - 1 # Check the four corners of the bounding box corners = [ (left, bottom), (right, bottom), (left, top), - (right, top) + (right, top), ] for cx, cy in corners: @@ -129,23 +129,43 @@ class OverworldMap: tile_y = int(cy // OVERWORLD_TILE_HEIGHT) # Check map bounds - if not (0 <= tile_x < OVERWORLD_WIDTH and 0 <= tile_y < OVERWORLD_HEIGHT): + if not ( + 0 <= tile_x < OVERWORLD_WIDTH and + 0 <= tile_y < OVERWORLD_HEIGHT + ): return False # Out of bounds is a wall return True # !!! CHATGPT VÉGE !!! - + def get_translation(self, game): + return ( + self.scroll_x + (game.screen_width / 2) - ((OVERWORLD_WIDTH * OVERWORLD_TILE_WIDTH) / 2), + self.scroll_y + (game.screen_height / 2) - ((OVERWORLD_HEIGHT * OVERWORLD_TILE_HEIGHT) / 2) + ) def render(self, game): for s in self.sprites: arcade.draw_texture_rect( s[0], - s[1].move( - self.scroll_x + (game.screen_width / 2) - ((OVERWORLD_WIDTH * OVERWORLD_TILE_WIDTH) / 2), - self.scroll_y + (game.screen_height / 2) - ((OVERWORLD_HEIGHT * OVERWORLD_TILE_HEIGHT) / 2) - ), + s[1].move(*self.get_translation(game)), pixelated=True ) +# Teszt objektum +class TestObject: + def __init__(self, x, y): + self.x = x + self.y = y + self.w = 16 + self.h = 16 + + def get_aabb(self): + return self.x, self.y, self.x + self.w, self.y + self.h + + def render(self, game, translation): + arcade.draw_rect_filled( + arcade.LBWH(self.x, self.y, 16, 16).move(*translation), + arcade.color.PURPLE, + )