import pygame import random from src.settings import ( ITEM_SPAWN_INTERVAL, ITEM_SHOPPING_TIMER, ITEM_SIZE, COLOR_HP_BAR_YELLOW, COLOR_HP_BAR_BG ) class Item: def __init__(self, x, y, item_type): self.x = x self.y = y self.item_type = item_type self.cost = random.randint(5, 10) # collision rect for player (2 times item size for width and height) self.rect = pygame.Rect(self.x, self.y, ITEM_SIZE, ITEM_SIZE) # timer to store time when item appeared self.spawn_time = pygame.time.get_ticks() # try to load sprite with item type try: path = f"assets/items/{item_type}.png" self.image = pygame.image.load(path).convert_alpha() self.image = pygame.transform.scale(self.image, (ITEM_SIZE, ITEM_SIZE)) except Exception as e: print(f"Error loading item sprite {item_type}: {e}") self.image = None # to check if the time ran out to buy the item def is_expired(self): return pygame.time.get_ticks() - self.spawn_time >= ITEM_SHOPPING_TIMER # cam offset to convert world coordinates to screen coordinates def draw(self, screen, cam_x, cam_y): draw_x = self.x - cam_x draw_y = self.y - cam_y if self.image is not None: screen.blit(self.image, (draw_x, draw_y)) else: # fallback using settings colors # coffee brown, beer yellow if self.item_type == "coffee": color = (120, 70, 30) else: color = COLOR_HP_BAR_YELLOW draw_rect = (draw_x, draw_y, ITEM_SIZE, ITEM_SIZE) pygame.draw.rect(screen, color, draw_rect) pygame.draw.rect(screen, COLOR_HP_BAR_BG, draw_rect, 2) def get_cost(self): return self.cost # try 50 times to find a free position to spawn item def _random_position(room_rect, blocked_rects): attempts = 0 max_attempts = 50 while attempts < max_attempts: # generate random x/y coordinates with room boundaries # * 2 to have a margin to walls x = random.randint(room_rect.left + ITEM_SIZE, room_rect.right - ITEM_SIZE * 2) y = random.randint(room_rect.top + ITEM_SIZE, room_rect.bottom - ITEM_SIZE * 2) # create a rect at this position for testing collision test_rect = pygame.Rect(x, y, ITEM_SIZE, ITEM_SIZE) blocked = False for b in blocked_rects: if test_rect.colliderect(b): blocked = True break # if position is not blocked, return the position if not blocked: return x, y attempts += 1 # no spot after 50 attempts -> return return None class ItemManager: def __init__(self): self.items = [] self.last_spawn_time = pygame.time.get_ticks() # remove expired items and spawn new ones def update(self, room_rect, blocked_rects): now = pygame.time.get_ticks() remaining_items = [] for item in self.items: if item.is_expired() == False: remaining_items.append(item) # replace the old list with the new temp_list self.items = remaining_items # spawn logic for new items if room_rect is not None: if now - self.last_spawn_time >= ITEM_SPAWN_INTERVAL: pos = _random_position(room_rect, blocked_rects) if pos is not None: x, y = pos item_type = random.choice(["coffee", "beer"]) self.items.append(Item(x, y, item_type)) self.last_spawn_time = now # check if player press "e" to buy def check_collect(self, player_rect, keys): if keys[pygame.K_e]: for item in self.items: if player_rect.colliderect(item.rect): return item return None # delete item from list after buying it def remove_item(self, item): if item in self.items: self.items.remove(item) # draw all active items def draw(self, screen, cam_x, cam_y): for item in self.items: item.draw(screen, cam_x, cam_y) # clear items when changing room def clear(self): self.items = [] self.last_spawn_time = pygame.time.get_ticks()