# Example file showing a basic pygame "game loop" import pygame import math import csv import random # pygame setup pygame.init() screen = pygame.display.set_mode((1080,720)) clock = pygame.time.Clock() running = True dt = 0 player_sprite = pygame.Rect(100,100,50,50) mur = pygame.Rect(500,100,100,100) class Waypoint: def __init__(self, name: str) -> None: self.name = name match name.capitalize(): case "A": self.x = 800 self.y = 900 self.connection = ("B", "H") case "B": self.x = 1575 self.y = 900 self.connection = ("A", "E", "C") case "C": self.x = 2500 self.y = 900 self.connection = ("B", "D") case "D": self.x = 2500 self.y = 1600 self.connection = ("C", "E", "F") case "E": self.x = 1575 self.y = 1600 self.connection = ("B", "D", "G") case "F": self.x = 2500 self.y = 2200 self.connection = ("D", "G") case "G": self.x = 1575 self.y = 2200 self.connection = ("H", "E", "F") case "H": self.x = 800 self.y = 2200 self.connection = ("A", "G") def get_new_connected(self)-> object: letter = random.choice(self.connection) return Waypoint(letter) def get_direction(self, pointA: object, pointB: object)-> str: a = pointA.name b = pointB.name if (a == "H" and b == "A") or (a == "G" and b == "E") or (a == "E" and b == "B") or (a == "F" and b == "D") or (a == "D" and b == "C"): return "north" elif (a == "A" and b == "H") or (a == "E" and b == "G") or (a == "B" and b == "E") or (a == "D" and b == "F") or (a == "C" and b == "D"): return "south" elif (a == "A" and b == "B") or (a == "B" and b == "C") or (a == "E" and b == "D") or (a == "H" and b == "G") or (a == "G" and b == "F"): return "east" elif (a == "B" and b == "A") or (a == "C" and b == "B") or (a == "D" and b == "E") or (a == "G" and b == "H") or (a == "F" and b == "G"): return "west" else: raise Exception("crash: POINT A and B impossible") class Pnj: def __init__(self, x: int, y: int, sprite_path: str, direction: str, objectif: Waypoint, speed: int) -> None: self.x = x self.y = y self.sprite = pygame.transform.scale_by(pygame.image.load(sprite_path), 3.0) self.direction = direction self.objectif = objectif self.speed = speed def avance(self): ''' Vérifie que l'objectif n'est pas atteint et avance le pnj dans la direction ''' if self.check_objectif(): return else: match self.direction: case "north": self.y -= self.speed case "south": self.y += self.speed case "east": self.x += self.speed case "west": self.x -= self.speed case _: pass def check_objectif(self): """ Vérifie que l'objectif n'est pas atteint et renvoie true si un l'est, s'occupe aussi de réassigner un nouvel objectig """ match self.direction: case "north": if self.y <= self.objectif.y: new_objectif = self.objectif.get_new_connected() self.direction = self.objectif.get_direction(self.objectif, new_objectif) self.objectif = new_objectif return True case "south": if self.y >= self.objectif.y: new_objectif = self.objectif.get_new_connected() self.direction = self.objectif.get_direction(self.objectif, new_objectif) self.objectif = new_objectif return True case "east": if self.x >= self.objectif.x: new_objectif = self.objectif.get_new_connected() self.direction = self.objectif.get_direction(self.objectif, new_objectif) self.objectif = new_objectif return True case "west": if self.x <= self.objectif.x: new_objectif = self.objectif.get_new_connected() self.direction = self.objectif.get_direction(self.objectif, new_objectif) self.objectif = new_objectif return True return False class Village: def __init__(self, nb_pnj: int) -> None: self.liste_pnj = [] for i in range(nb_pnj): start_waypoint = Waypoint(random.choice(("A", "B", "C", "D", "E", "F", "G", "H"))) objective_waypoint = start_waypoint.get_new_connected() self.liste_pnj.append(Pnj(start_waypoint.x, start_waypoint.y, "assets/pnj/pnj"+str(random.randint(1,8))+".png", start_waypoint.get_direction(start_waypoint, objective_waypoint), objective_waypoint, random.randint(1, 4))) def ajouter_pnj_random(self)-> None: pass def update_pnj(self)-> None: for p in self.liste_pnj: p.avance() def get_village_sprites(self)->list: village_sprites = [] for p in self.liste_pnj: village_sprites.append((p.x, p.y, p.sprite)) return village_sprites class Player: def __init__(self)-> None: self.x = 800 self.y = 900 self.mov_speed = 8 self.rotate_speed = 5 self.angle = 90 def rotate(self, angle: math.degrees)-> None: self.angle += angle*self.rotate_speed def move(self, mov: int)-> None: new_x = self.x + self.mov_speed*mov*math.cos(math.radians(self.angle)) new_y = self.y + self.mov_speed*mov*math.sin(math.radians(self.angle)) if(game.test_collision(pygame.Rect(new_x-50, new_y-50, 100, 100), game.collisions) == False): self.x = new_x self.y = new_y elif(game.test_collision(pygame.Rect(self.x-50, new_y-50, 100, 100), game.collisions) == False): self.y = new_y elif(game.test_collision(pygame.Rect(new_x-50, self.y-50, 100, 100), game.collisions) == False): self.x = new_x class Game: def __init__(self): self.is_paused = False pygame.font.init() self.font = pygame.font.SysFont('Comic Sans MS', 30) self.load_sprites() self.load_collisions() def load_sprites(self): self.perso_sprite = pygame.image.load("assets/perso_sprite.png") self.map_sprite = pygame.image.load("assets/map3.png") def load_collisions(self): self.collisions = [] with open('assets/collisions.csv', 'r', newline='') as file: reader = csv.DictReader(file) for row in reader: self.collisions.append(pygame.Rect(float(row["starting_point_x"]), float(row["starting_point_y"]), float(row["len_x"]), float(row["len_y"]))) def test_collision(self, objet: pygame.Rect, l_collisions) -> bool: for col in l_collisions: if objet.colliderect(col): return True return False def display_debug_text(self): angle_surface = self.font.render("angle: "+str(player.angle), False, (0, 0, 0)) x_surface = self.font.render("x: "+str(player.x), False, (0, 0, 0)) y_surface = self.font.render("y: "+str(player.y), False, (0, 0, 0)) screen.blit(angle_surface, (0,0)) screen.blit(x_surface, (0,30)) screen.blit(y_surface, (0,60)) #pygame.draw.rect(screen, "blue",pygame.Rect(player.x-50, player.y-50, 100, 100)) def check_input(self): keys = pygame.key.get_pressed() if keys[pygame.K_z]: _ = player.move(1) if keys[pygame.K_s]: _ = player.move(-1) if keys[pygame.K_q]: player.rotate(-1) if keys[pygame.K_d]: player.rotate(1) def draw_player(self): #pygame.draw.rect(screen, "red", pygame.Rect(player.x, player.y, 50, 50)) img = pygame.transform.rotozoom(self.perso_sprite, -player.angle-90, 0.2) screen.blit(img, (540-img.get_rect().centerx, 360-img.get_rect().centery)) def draw_village(self): for s in village.get_village_sprites(): screen.blit(s[2], (540-player.x + s[0] - s[2].get_rect().centerx, 360-player.y + s[1] - s[2].get_rect().centery)) def display_all(self): # fill the screen with a color to wipe away anything from last frame screen.fill("purple") screen.blit(self.map_sprite, (540-player.x, 360-player.y)) self.draw_village() self.draw_player() # We display it at the end so it's on top of all self.display_debug_text() # flip() the display to put your work on screen pygame.display.flip() player = Player() game = Game() #pnj = Pnj(800, 900, "assets/MiniPeasant.png", "south", Waypoint("H"), 3) village = Village(20) while running: # poll for events # pygame.QUIT event means the user clicked X to close your window for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # make all the pnj move and do their pnj stuff village.update_pnj() game.check_input() game.display_all() # limits FPS to 60 # dt is delta time in seconds since last frame, used for framerate- # independent physics. dt = clock.tick(60) / 1000 pygame.quit()