2024-10-22 14:15:06 +00:00
|
|
|
# Example file showing a basic pygame "game loop"
|
|
|
|
import pygame
|
|
|
|
import math
|
|
|
|
import csv
|
2024-10-23 06:39:17 +00:00
|
|
|
import random
|
2024-10-22 14:15:06 +00:00
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
2024-10-23 06:39:17 +00:00
|
|
|
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) -> 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 = 6
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2024-10-22 14:15:06 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
2024-10-23 06:39:17 +00:00
|
|
|
def draw_villager(self):
|
|
|
|
screen.blit(pnj.sprite, (540-player.x + pnj.x - pnj.sprite.get_rect().centerx, 360-player.y + pnj.y - pnj.sprite.get_rect().centery))
|
|
|
|
|
2024-10-22 14:15:06 +00:00
|
|
|
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))
|
|
|
|
|
2024-10-23 06:39:17 +00:00
|
|
|
self.draw_villager()
|
2024-10-22 14:15:06 +00:00
|
|
|
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()
|
2024-10-23 06:39:17 +00:00
|
|
|
pnj = Pnj(800, 900, "assets/MiniPeasant.png", "south", Waypoint("H"))
|
2024-10-22 14:15:06 +00:00
|
|
|
|
|
|
|
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
|
2024-10-23 06:39:17 +00:00
|
|
|
pnj.avance()
|
2024-10-22 14:15:06 +00:00
|
|
|
|
|
|
|
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()
|