mirror of
https://github.com/BreizhHardware/project_sanic.git
synced 2026-01-18 16:47:25 +01:00
FEAT [Collectibles] - Added Coin item : collectible in map - Coin counter on top of screen - Added custom font for display
This commit is contained in:
BIN
assets/fonts/sanicfont.TTF
Normal file
BIN
assets/fonts/sanicfont.TTF
Normal file
Binary file not shown.
BIN
assets/map/collectibles/Sanic_Coin.png
Normal file
BIN
assets/map/collectibles/Sanic_Coin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 168 KiB |
8
main.py
8
main.py
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
48
src/Entity/Coin.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user