Skip to content

Commit

Permalink
Restructuration du déplacement du joueur et conv
Browse files Browse the repository at this point in the history
Préparation au support des textures en diagonales (#12)
Résolution de #14
Avancée sur #5
  • Loading branch information
antoinech2 committed Dec 12, 2021
1 parent a9f1242 commit 746aa17
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 74 deletions.
File renamed without changes.
27 changes: 14 additions & 13 deletions src/dialogue.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-


"""
Gestion des dialogues entre le joueur et les NPC
"""


import pygame as pg
import sqlite3 as sql
import numpy as np


class Dialogue():
DATABASE_LOCATION = "res/text/dialogues.db"
IMAGE_LOCATION = "res/textures/talk_box_next.png"

TEXT_POSITION = (30, 100)

def __init__(self, game, npc):
self.game = game
self.current_npc = npc

#Etat
self.is_writing = True
self.game.player.is_talking = True

#Graphique
self.talk_box_surf = pg.image.load(self.IMAGE_LOCATION).convert()
self.talk_box_x = int(self.talk_box_surf.get_width()*0.75)
self.talk_box_y = int(self.talk_box_surf.get_height()*0.75)
self.talk_box_img = pg.transform.scale(self.talk_box_surf, (self.talk_box_x, self.talk_box_y))
self.talk_box_img.set_colorkey([255, 255, 255])
self.tw_sound = pg.mixer.Sound(
"res/sounds/sound_effect/typewriter.wav")

#BDD
self.db_connexion = sql.connect(self.DATABASE_LOCATION)
self.db_cursor = self.db_connexion.cursor()

#Gestion de l'affichage partiel du texte
self.lettre_cooldown = 5
self.current_npc = npc
self.current_text = "" # text actuel
self.current_text_id = -1 # id du text actuel
self.current_letter_id = -1 # lettre actuelle
Expand All @@ -41,11 +47,6 @@ def __init__(self, game, npc):
#Police
self.font = pg.font.SysFont("comic sans ms", 16)


self.tw_sound = pg.mixer.Sound(
"res/sounds/sound_effect/typewriter.wav")
self.is_writing = True
self.game.player.is_talking = True
self.new_line()

def close(self):
Expand All @@ -67,7 +68,7 @@ def next_dialogue(self):
if self.is_writing:
self.is_writing = False
self.current_letter_id = -1
self.ecrire(self.current_text,30,100)
self.ecrire(self.current_text, self.TEXT_POSITION)
else:
self.new_line()

Expand All @@ -90,16 +91,16 @@ def new_letter(self):
"""Affiche une nouvelle lettre du texte"""
if self.current_letter_id < len(self.current_text) - 1:
self.current_letter_id += 1
self.ecrire(self.current_text[:self.current_letter_id+1], 30, 100)
self.ecrire(self.current_text[:self.current_letter_id+1], self.TEXT_POSITION)
pg.mixer.Sound.play(self.tw_sound)
else:
self.current_letter_id = -1
self.is_writing = False

def ecrire(self, texte, x, y, color=(0, 0, 0)):
def ecrire(self, texte, pos, color=(0, 0, 0)):
"""Affiche le texte sur le cadre de dialogue"""
text_affiche = self.font.render(texte, False, color)
self.talk_box_img.blit(text_affiche, (x, y))
self.talk_box_img.blit(text_affiche, pos)

def show_talk_box(self):
"""Affichage graphique de la boîte"""
Expand Down
12 changes: 7 additions & 5 deletions src/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,25 @@ def __init__(self):

self.tick_count = 0

#Objets associés
self.player = player.Player(0, 0, self)
self.map_manager = maps.MapManager(self.screen, self)
self.dialogue = None

def tick(self):
"""Fonction principale de calcul du tick"""
inputs.handle_pressed_key(self)
self.map_manager.update()
self.map_manager.tick()
self.map_manager.draw()
self.player.update_player()
if self.dialogue != None:
self.dialogue.update()

def run(self):

"""Boucle principale"""
clock = pg.time.Clock()

running = True

while running:

self.tick()
pg.display.flip() # update l'ecran

Expand All @@ -47,6 +46,9 @@ def run(self):
running = False
elif event.type == pg.KEYDOWN:
inputs.handle_key_down_event(self, event)

self.tick_count += 1
if self.tick_count % 60 == 0:
print("Running...", self.tick_count/60, end="\r")
clock.tick(60) # 60 fps psk ça va trop vite
pg.quit()
2 changes: 2 additions & 0 deletions src/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import pygame as pg

def handle_pressed_key(game):
"""Transmet toutes les touches préssées"""
pressed = pg.key.get_pressed() #Gestion des touches du clavier
# On envoie le statut des 4 touches de déplacement pour être traité
game.player.move([pressed[pg.K_UP], pressed[pg.K_RIGHT], pressed[pg.K_DOWN], pressed[pg.K_LEFT]], pressed[pg.K_RCTRL] or pressed[pg.K_LCTRL])

def handle_key_down_event(game, event):
"""Transmet l'évènement d'une toucher qui vient d'être pressée"""
if event.key == pg.K_SPACE: # si Espace est pressée
if game.dialogue == None:
game.map_manager.npc_manager.check_talk()
Expand Down
31 changes: 17 additions & 14 deletions src/maps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pygame as pg
import pytmx, pyscroll
from dataclasses import dataclass
Expand Down Expand Up @@ -31,11 +32,23 @@ class MapManager : # aka le Patron ou bien Le Contre-Maître
def __init__ (self,screen,game):
self.game = game
self.screen = screen
self.maps = dict() # les dictionnaires c'est bien, surtout pour y ranger des cates

#Etat
self.current_map = "carte" # La map à charger par défault ( mais sert aussi d'indicateur sur la map actuellement utilisée)
self.current_music = "titleVer2" # resp musique

self.maps = dict() # les dictionnaires c'est bien, surtout pour y ranger des cates
self.music_manager() # lancement de la musique
# référencement des différentes cartes (voir fonction d'après)

self.register_all_maps()

#Objets associés
self.npc_manager = npc.NpcManager(self)

self.teleport_player("spawn_1") # Tp le j au spawn de base ( soit ici celui de carte.tmx)

def register_all_maps(self):
# référencement des différentes cartes (voir fonction d'après)
self.register_map("niv_1", "spring",
portals =[
Portal (from_world = "niv_1", origin_point = "to_main", to_world = "carte", next_point = "spawn_lycée"),
Expand Down Expand Up @@ -80,11 +93,6 @@ def __init__ (self,screen,game):
Portal (from_world = "i109", origin_point = "to_niv1", to_world = "niv_1", next_point = "exit_i109")
])

self.teleport_player("spawn_1") # Tp le j au spawn de base ( soit ici celui de carte.tmx)

self.npc_manager = npc.NpcManager(self)


def check_collision(self):
'condition de colision'
# aux portals
Expand All @@ -100,19 +108,14 @@ def check_collision(self):
self.npc_manager = npc.NpcManager(self)
self.teleport_player(copy_portal.next_point) # on téléporte le j sur le spawn d'arriver
self.music_manager() # le Dj fait son taf ( TODO : peut être metttre un décompte pour changer de musique moins brusquement)
# aux murs
for sprite in self.get_group().sprites():
if sprite.feet.collidelist(self.get_walls()) > -1:
sprite.move_back()

def teleport_player(self, name):
'tp le joueur sur les coordonées de l objet name'
point = self.get_object(name)
self.game.player.position[0] = point.x # réaffectation des coordonées
self.game.player.position[1] = point.y
self.game.player.save_location() # pour éviter les bugs de loop de tp

def register_map (self, name_map , name_music, portals = [] ):
def register_map(self, name_map , name_music, portals = [] ):
'enregistre une carte sur le ditionnaire self.maps de la classe MapManager'

# chargement normal des elts d'une carte sur Tiled
Expand Down Expand Up @@ -165,7 +168,7 @@ def draw(self):
self.get_group().draw(self.screen)
self.get_group().center(self.game.player.rect.center)

def update(self):
def tick(self):
'appelée, elle met à jour les elts suivants'
self.get_group().update()
self.check_collision()
9 changes: 7 additions & 2 deletions src/npc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class NpcManager():
def __init__(self, map):
self.npc_group = pg.sprite.Group()
self.map = map

#On charge les Npc de la map
for npc in NPC_LIST:
if npc["map"] == map.current_map:
new_npc = Npc(map, npc["id"], npc["coords"])
Expand All @@ -26,12 +28,15 @@ def check_talk(self):


class Npc(pg.sprite.Sprite):
TEXTURE_FILE_LOCATION = 'res/textures/player.png'

def __init__(self, map, id, coords):
super().__init__()
self.map = map
self.id = id
self.sprite_sheet = pg.image.load('res/textures/player.png')
#self.dialogue = self.game.dialogue

#Graphique
self.sprite_sheet = pg.image.load(self.TEXTURE_FILE_LOCATION)
self.image = pg.Surface([32, 32]) # creation d'une image
self.image.set_colorkey([0, 0, 0]) # transparence
self.rect = self.image.get_rect() # rectangle autour du joueur
Expand Down
116 changes: 76 additions & 40 deletions src/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,107 @@

class Player(pg.sprite.Sprite):

TEXTURE_FILE_LOCATION = 'res/textures/player.png'

SPEED_NORMALISATION = 1/(2**0.5)
BASE_WALK_SPEED = 1.5 #Vitesse du joueur sans multiplicateur (en m/frame)
SPRINT_WALK_SPEED_MULTIPLIER = 1.75 #Multiplicateur de vitesse en cas de sprint
WALK_ANIMATION_COOLDOWN = 8 #Cooldown entre deux changements d'animations (en frames)
SPRINT_ANIMATION_COOLDOWN = 3 #Cooldown entre deux changements d'animations (en frames)

ANIMATION_DICT = {
"1,1" : "down-right",
"1,0" : "right",
"0,1" : "down",
"1,-1" : "up-right",
"0,-1" : "up",
"-1,1" : "down-left",
"-1,0" : "left",
"-1,-1" : "up-left"}

def __init__(self, x, y, game):
super().__init__()
self.game = game

#Etat
self.is_animated = False
self.is_sprinting = False
self.is_talking = False
self.sprite_sheet = pg.image.load('res/textures/player.png')

self.position = [x, y]

#Graphique
self.sprite_sheet = pg.image.load(self.TEXTURE_FILE_LOCATION)
self.image = self.get_image(0, 0) # en bas par défaut
self.image.set_colorkey([0, 0, 0]) # transparence
self.rect = self.image.get_rect() # rectangle autour du joueur
self.position = [x, y]
self.feet = pg.Rect(0, 0, self.rect.width * 0.5, 12)
self.old_position = self.position.copy()
self.images = {
'down': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
'left': [self.get_image(0, 32), self.get_image(32, 32), self.get_image(64, 32)],
'right': [self.get_image(0, 64), self.get_image(32, 64), self.get_image(64, 64)],
'up': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)]
}

self.current_sprite = 0

def change_animation(self, sens): # change l'image en fonction du sens 'sens'
self.image = self.images[sens][int(self.current_sprite)]
self.IMAGES = {
'down': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
'down-left': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
'down-right': [self.get_image(0, 0), self.get_image(32, 0), self.get_image(64, 0)],
'left': [self.get_image(0, 32), self.get_image(32, 32), self.get_image(64, 32)],
'right': [self.get_image(0, 64), self.get_image(32, 64), self.get_image(64, 64)],
'up': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)],
'up-left': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)],
'up-right': [self.get_image(0, 96), self.get_image(32, 96), self.get_image(64, 96)]
}


def change_animation(self, direction): # change l'image en fonction du sens 'sens'
animation = self.ANIMATION_DICT[str(direction[0])+","+str(direction[1])]
self.image = self.IMAGES[animation][int(self.current_sprite)]
self.image.set_colorkey([0, 0, 0]) # transparence

def is_colliding(self):
return True if self.feet.collidelist(self.game.map_manager.get_walls()) > -1 else False

def move(self, list_directions, sprinting):
if not self.is_talking:
number_directions = list_directions.count(True)
speed_multiplier = self.SPRINT_WALK_SPEED_MULTIPLIER if sprinting else 1
self.is_sprinting = True if sprinting else False
speed_normalisation = self.SPEED_NORMALISATION if number_directions == 2 else 1
self.is_animated = False if number_directions in [0,4] else True
if list_directions[0]: #Haut
self.position[1] -= self.BASE_WALK_SPEED*speed_multiplier*speed_normalisation
self.change_animation('up')
if list_directions[1]: #Droite
self.position[0] += self.BASE_WALK_SPEED*speed_multiplier*speed_normalisation
self.change_animation('right')
if list_directions[2]: #Bas
self.position[1] += self.BASE_WALK_SPEED*speed_multiplier*speed_normalisation
self.change_animation('down')
if list_directions[3]: #Gauche
self.position[0] -= self.BASE_WALK_SPEED*speed_multiplier*speed_normalisation
self.change_animation('left')
if list_directions.count(True) > 0:
if not self.is_talking:
speed_multiplier = self.SPRINT_WALK_SPEED_MULTIPLIER if sprinting else 1
self.is_sprinting = True if sprinting else False
deplacement = [0, 0]
if list_directions[0]: #Haut
deplacement[1] -= 1
if list_directions[1]: #Droite
deplacement[0] += 1
if list_directions[2]: #Bas
deplacement[1] += 1
if list_directions[3]: #Gauche
deplacement[0] -= 1

if deplacement[0] != 0 or deplacement[1] != 0:

if deplacement[0] != 0 and deplacement[1] != 0:
speed_normalisation = self.SPEED_NORMALISATION
else:
speed_normalisation = 1

for coord_id in [0, 1]:
self.position[coord_id] += deplacement[coord_id]*self.BASE_WALK_SPEED*speed_multiplier*speed_normalisation
self.rect.topleft = self.position
self.feet.midbottom = self.rect.midbottom

# Si il y a collision, on annule le dernier déplacement
if self.is_colliding():
self.position[coord_id] -= deplacement[coord_id]*self.BASE_WALK_SPEED*speed_multiplier*speed_normalisation

self.rect.topleft = self.position
self.feet.midbottom = self.rect.midbottom
else:
self.is_animated = True
self.change_animation(deplacement)
else:
self.is_animated = False

def update(self): # mettre à jour la position
self.rect.topleft = self.position
self.feet.midbottom = self.rect.midbottom

animation_cooldown = self.SPRINT_ANIMATION_COOLDOWN if self.is_sprinting else self.WALK_ANIMATION_COOLDOWN
if self.is_animated == True:
self.current_sprite = (int(self.game.tick_count/animation_cooldown) % 3)
Expand All @@ -70,14 +117,3 @@ def get_image(self, x, y):
image = pg.Surface([32, 32])
image.blit(self.sprite_sheet, (0, 0), (x, y, 32, 32))
return image

def save_location(self):
self.old_position = self.position.copy()

def update_player(self): # est appelée à chaques tick
self.save_location()

def move_back(self):
self.position = self.old_position
self.rect.topleft = self.position
self.feet.midbottom = self.rect.midbottom

0 comments on commit 746aa17

Please sign in to comment.