Files
rrttm/src/objects.py
2026-10-17 11:37:15 +02:00

203 lines
6.7 KiB
Python

import assets
import arcade
# Main character renderer
DIR_DOWN = 0
DIR_UP = 1
DIR_RIGHT = 2
DIR_LEFT = 3
B_SPRITE_WIDHT = 16
B_SPRITE_HEIGHT = 24
B_SPRITE_WALKING = 3
class BalthasarRenderer:
def __init__(self, x, y):
self.direction = DIR_UP
self.walking = False
self.anim_timer = 0
self.interactive = False
self.x = x
self.y = y
self.w = B_SPRITE_WIDHT
self.h = B_SPRITE_HEIGHT
def set_direction(self, direction):
self.direction = direction
def set_walking(self, walking):
self.walking = walking
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, _):
sprite_h = self.direction if self.direction < 3 else 2
sprite_v = ((self.anim_timer // 15) + 1) if self.walking else 0
flip_h = self.direction == DIR_LEFT
sprite = assets.sprites["balthasar"].get_texture(arcade.LBWH(B_SPRITE_WIDHT*sprite_h, B_SPRITE_HEIGHT*sprite_v, B_SPRITE_WIDHT, B_SPRITE_HEIGHT))
arcade.draw_texture_rect(
sprite.flip_horizontally() if flip_h else sprite,
arcade.LBWH((game.screen_width / 2) - (B_SPRITE_WIDHT / 2), (game.screen_height / 2) - (B_SPRITE_HEIGHT / 2), B_SPRITE_WIDHT, B_SPRITE_HEIGHT),
pixelated=True
)
# Overworld Map
OVERWORLD_LB_X = 0
OVERWORLD_LB_Y = 0
OVERWORLD_TILE_WIDTH = 16
OVERWORLD_TILE_HEIGHT = 16
OVERWORLD_WIDTH = 12
OVERWORLD_HEIGHT = 12
OVERWORLD_MAP = [
[9, 9, 9, 5, 3, 3, 3, 3, 6, 9, 9, 9],
[9, 9, 5, 0, 0, 0, 0, 0, 0, 6, 9, 9],
[9, 5, 0, 0, 0, 0, 0, 0, 0, 0, 6, 9],
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
[7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8],
[9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9],
[9, 9, 7, 0, 0, 0, 0, 0, 0, 8, 9, 9],
[9, 9, 9, 7, 4, 4, 4, 4, 8, 9, 9, 9],
]
class OverworldMap:
def __init__(self):
self.sprites = []
self.scroll_x = 0
self.scroll_y = 0
x = 0
y = len(OVERWORLD_MAP)
for row in OVERWORLD_MAP:
y -= 1
for tile in row:
self.sprites.append([
assets.sprites["overworld"].get_texture(
arcade.LBWH((tile % 4) * OVERWORLD_TILE_WIDTH, (tile // 4) * OVERWORLD_TILE_HEIGHT,
OVERWORLD_TILE_WIDTH, OVERWORLD_TILE_HEIGHT)
),
arcade.LBWH(
(x * OVERWORLD_TILE_WIDTH),
(y * OVERWORLD_TILE_HEIGHT),
OVERWORLD_TILE_WIDTH,
OVERWORLD_TILE_HEIGHT
)
])
x += 1
x = 0
# !!! CHATGPT !!!
def get_player_world_pos(self, game):
"""Calculates the player's world pixel position based on scroll."""
base_offset_x = (game.screen_width / 2) - ((OVERWORLD_WIDTH * OVERWORLD_TILE_WIDTH) / 2)
base_offset_y = (game.screen_height / 2) - ((OVERWORLD_HEIGHT * OVERWORLD_TILE_HEIGHT) / 2)
# Player pixel position in the world coordinate space
player_world_x = (game.screen_width / 2) - base_offset_x - self.scroll_x
player_world_y = (game.screen_height / 2) - base_offset_y - self.scroll_y
return player_world_x, player_world_y
def set_player_world_pos(self, game, target_x, target_y):
"""Sets the player's world position by adjusting the scroll offsets."""
half_world_width = (OVERWORLD_WIDTH * OVERWORLD_TILE_WIDTH) / 2
half_world_height = (OVERWORLD_HEIGHT * OVERWORLD_TILE_HEIGHT) / 2
# Reverse the math from get_player_world_pos to solve for scroll_x and scroll_y
self.scroll_x = half_world_width - target_x
self.scroll_y = half_world_height - target_y
def get_tile_at(self, world_x, world_y):
"""Returns the map tile ID at a given world pixel position."""
tile_x = int(world_x // OVERWORLD_TILE_WIDTH)
tile_y = int(world_y // OVERWORLD_TILE_HEIGHT)
# Check bounds
if 0 <= tile_x < OVERWORLD_WIDTH and 0 <= tile_y < OVERWORLD_HEIGHT:
return OVERWORLD_MAP[OVERWORLD_HEIGHT - 1 - tile_y][tile_x]
return None # Out of bounds / wall
def is_box_walkable(self, left, bottom, right, top):
"""Checks if a bounding box (e.g., player's feet) is entirely on walkable tiles."""
# Check the four corners of the bounding box
corners = [
(left, bottom),
(right, bottom),
(left, top),
(right, top),
]
for cx, cy in corners:
tile_x = int(cx // OVERWORLD_TILE_WIDTH)
tile_y = int(cy // OVERWORLD_TILE_HEIGHT)
# Check map bounds
if not (
0 <= tile_x < OVERWORLD_WIDTH and
0 <= tile_y < OVERWORLD_HEIGHT
):
return False # Out of bounds is a wall
tile_id = OVERWORLD_MAP[OVERWORLD_HEIGHT - 1 - tile_y][tile_x]
if tile_id > 8:
return False
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.get_translation(game)),
pixelated=True
)
# Csata Szobor
PODIUM_WIDTH = 48
PODIUM_HEIGHT = 32
class BattlePodium:
def __init__(self, x, y, battle_id):
self.x = x
self.y = y
self.w = PODIUM_WIDTH
self.h = PODIUM_HEIGHT
self.interactive = True
self.battle = battle_id
self.texture = assets.sprites["podium"].get_texture(arcade.LBWH(battle_id * PODIUM_WIDTH, 0, PODIUM_WIDTH, PODIUM_HEIGHT))
def get_aabb(self):
return self.x, self.y, self.x + self.w, self.y + self.h
def render(self, game, translation):
arcade.draw_texture_rect(
self.texture,
arcade.LBWH(self.x, self.y, self.w, self.h).move(*translation),
pixelated=True
)
def on_interact(self, start_battle_func, delete_obj_func):
start_battle_func(self.battle)
delete_obj_func(self)