FEAT [Collectibles] - Added Coin item : collectible in map - Coin counter on top of screen - Added custom font for display

This commit is contained in:
ClementHVT
2025-03-31 09:52:53 +02:00
parent 9abdb3be3e
commit 5e5ca57f6f
9 changed files with 134 additions and 11 deletions

BIN
assets/fonts/sanicfont.TTF Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@@ -136,6 +136,7 @@ def main():
background,
checkpoints,
exits,
collectibles,
) = initialize_game(game_resources, level_file)
projectiles.empty()
current_state = PLAYING
@@ -240,6 +241,12 @@ def main():
fps_text = font.render(f"FPS: {fps}", True, (255, 255, 255))
displaysurface.blit(fps_text, (10, 10))
coins_hit = pygame.sprite.spritecollide(P1, collectibles,
False) # Set to False to handle removal in on_collision
for coin in coins_hit:
coin.on_collision() # This will handle the coin removal
P1.collect_coin(displaysurface) # This updates the player's coin counter
P1.draw_dash_cooldown_bar(displaysurface)
pos_text = font.render(
@@ -249,6 +256,7 @@ def main():
P1.draw_dash_cooldown_bar(displaysurface)
P1.draw_lives(displaysurface)
P1.draw_coins(displaysurface)
elif current_state == INFINITE:
# Placeholder for infinite mode

View File

@@ -142,10 +142,16 @@
{
"id": "coin1",
"type": "coin",
"x": 350,
"y": 550,
"value": 10,
"sprite": "assets/map/collectibles/coin.png"
"x": 1220,
"y": 320,
"sprite": "assets/map/collectibles/Sanic_Coin.png"
},
{
"id": "coin2",
"type": "coin",
"x": 400,
"y": 540,
"sprite": "assets/map/collectibles/Sanic_Coin.png"
},
{
"id": "power_up1",

View File

@@ -142,10 +142,16 @@
{
"id": "coin1",
"type": "coin",
"x": 350,
"y": 550,
"value": 10,
"sprite": "assets/map/collectibles/coin.png"
"x": 1220,
"y": 320,
"sprite": "assets/map/collectibles/Sanic_Coin.png"
},
{
"id": "coin2",
"type": "coin",
"x": 400,
"y": 540,
"sprite": "assets/map/collectibles/Sanic_Coin.png"
},
{
"id": "power_up1",

48
src/Entity/Coin.py Normal file
View File

@@ -0,0 +1,48 @@
# src/Entity/Coin.py
import os
from src.Entity.Entity import Entity
import pygame
class Coin(Entity):
def __init__(self, pos, size=(50, 50), color=(255, 215, 0), texturePath=""):
super().__init__(pos=pos, size=size, color=color, texturePath=texturePath)
self.collected = False
# Create initial surface
self.surf = pygame.Surface(size, pygame.SRCALPHA)
# Load and scale the coin texture if provided
if texturePath:
try:
if os.path.exists(texturePath):
texture = pygame.image.load(texturePath).convert_alpha()
self.surf = pygame.transform.scale(texture, size)
print(f"Coin texture loaded successfully at {pos}")
else:
print(f"Coin texture file not found: {texturePath}")
self.draw_fallback(color, size)
except Exception as e:
print(f"Error loading coin texture: {e}")
self.draw_fallback(color, size)
else:
self.draw_fallback(color, size)
# Ensure rect is properly set
self.rect = self.surf.get_rect()
self.rect.topleft = pos
def draw_fallback(self, color, size):
"""Draw a yellow circle as fallback"""
self.surf.fill((0, 0, 0, 0)) # Clear with transparency
pygame.draw.circle(self.surf, color, (size[0] // 2, size[1] // 2), size[0] // 2)
print(f"Drew fallback circle at {self.rect.topleft}")
def on_collision(self):
"""Handle coin collision with player"""
print(self.collected)
if not self.collected:
self.collected = True
print("Coin collected") # Debug line
self.kill() # This removes the coin from all sprite groups

View File

@@ -40,6 +40,9 @@ class Player(Entity):
# Load images
self.load_images()
# Coins amount
self.coins = 0
# Override initial surface if images are loaded
if self.static_image:
self.surf = self.static_image
@@ -291,3 +294,36 @@ class Player(Entity):
start_y,
),
)
def draw_coins(self, surface):
"""Draws the coin counter with icon in the top left corner"""
# Load coin texture (do this in __init__ for better performance)
coin_texture = pygame.image.load("assets/map/collectibles/Sanic_Coin.png").convert_alpha()
coin_size = 30
coin_texture = pygame.transform.scale(coin_texture, (coin_size, coin_size))
# Position for coin display
start_x = 200
start_y = 10
# Draw coin icon
surface.blit(coin_texture, (start_x, start_y))
# Use custom font
try:
font = pygame.font.Font("assets/fonts/sanicfont.ttf", 20)
except:
# Fallback to default font if custom font fails to load
font = pygame.font.Font(None, 20)
coin_text = font.render(f"x{self.coins}", True, (58, 83, 200))
# Position text next to coin icon with small spacing
text_x = start_x + coin_size + 5
text_y = start_y + (coin_size - coin_text.get_height()) // 2 # Vertically center
surface.blit(coin_text, (text_x, text_y))
def collect_coin(self, surface):
"""Increment coin counter when collecting a coin"""
self.coins += 1

View File

@@ -6,7 +6,7 @@ from src.Entity.Player import Player
from src.Entity.Enemy import Enemy
from src.Entity.Checkpoint import Checkpoint
from src.Entity.Exit import Exit
from src.Entity.Coin import Coin
class MapParser:
def __init__(self, game_resources):
@@ -124,9 +124,23 @@ class MapParser:
self.all_sprites.add(enemy)
# Create collectibles (requires Collectible class implementation)
# In MapParser.create_map_objects()
# In MapParser.create_map_objects()
if "collectibles" in map_data:
pass # You'll need to implement collectible creation
print(f"Found {len(map_data['collectibles'])} collectibles")
for collectible_data in map_data["collectibles"]:
if collectible_data["type"] == "coin":
print(f"Creating coin at ({collectible_data['x']}, {collectible_data['y']})")
sprite_path = collectible_data.get("sprite", "")
print(f"Using sprite path: {sprite_path}")
# Create and add the coin
coin = Coin(
pos=(collectible_data["x"], collectible_data["y"]),
texturePath=sprite_path
)
self.collectibles.add(coin)
self.all_sprites.add(coin)
# Create background image
if "background" in map_data:
if os.path.isfile(map_data["background"]):
@@ -151,6 +165,10 @@ class MapParser:
self.checkpoints.add(checkpoint)
self.all_sprites.add(checkpoint)
# At the end of MapParser.create_map_objects()
print(f"Total sprites: {len(self.all_sprites)}")
print(f"Total collectibles: {len(self.collectibles)}")
if "exits" in map_data:
for exit_data in map_data["exits"]:
exit = Exit(

View File

@@ -59,6 +59,7 @@ def initialize_game(game_resources, map_file="map/levels/1.json"):
parser.background,
map_objects["checkpoints"],
exits,
map_objects["collectibles"],
)
@@ -75,7 +76,7 @@ def reset_game_with_checkpoint(map_name, game_resources):
checkpoint_pos = db.get_checkpoint(map_name)
# Initialize game
player, _, platforms, all_sprites, background, checkpoints, exits = initialize_game(
player, _, platforms, all_sprites, background, checkpoints, exits, collectibles = initialize_game(
game_resources, map_name
)