intégration de la recherche de chemin super intélligente
This commit is contained in:
parent
5c6f690a98
commit
a235f8f77e
@ -1 +1,11 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
S = 20
|
S = 20
|
||||||
|
|
||||||
|
|
||||||
|
class Direction(Enum):
|
||||||
|
UP = 0
|
||||||
|
DOWN = 1
|
||||||
|
LEFT = 2
|
||||||
|
RIGHT = 3
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
from enum import Enum
|
|
||||||
from random import random, randint
|
from random import random, randint
|
||||||
|
|
||||||
from pygame import Surface, draw, Rect, image
|
from pygame import Surface, draw, Rect, image
|
||||||
|
|
||||||
from engine.entity import Entity
|
from engine.entity import Entity
|
||||||
|
from engine.scene_manager import SceneManager
|
||||||
from engine.resources import res
|
from engine.resources import res
|
||||||
from engine.components.collide_rect import CollideRect
|
from engine.components.collide_rect import CollideRect
|
||||||
from engine.components.sprite import Sprite
|
from engine.components.sprite import Sprite
|
||||||
|
|
||||||
from .common import S
|
from .common import S, Direction
|
||||||
from .pacdot import PacDot
|
from .pacdot import PacDot
|
||||||
|
|
||||||
|
|
||||||
class Direction(Enum):
|
|
||||||
UP = 1
|
|
||||||
DOWN = 2
|
|
||||||
LEFT = 3
|
|
||||||
RIGHT = 4
|
|
||||||
|
|
||||||
|
|
||||||
class Ghost(Entity):
|
class Ghost(Entity):
|
||||||
SPEED = 1
|
SPEED = 1
|
||||||
|
|
||||||
@ -30,14 +23,14 @@ class Ghost(Entity):
|
|||||||
sprite.width, sprite.width),
|
sprite.width, sprite.width),
|
||||||
static=False,
|
static=False,
|
||||||
solid=False,
|
solid=False,
|
||||||
cb=self.on_col)
|
cb=self.cb)
|
||||||
self.add(self.phys)
|
self.add(self.phys)
|
||||||
self.script = Ghost.script
|
self.script = Ghost.script
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
self.direction = Direction(randint(1, 4))
|
self.direction = Direction(randint(0, 3))
|
||||||
|
|
||||||
def on_col(self, c):
|
def cb(self, c):
|
||||||
if not c.solid:
|
if not c.solid:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -63,6 +56,30 @@ class Ghost(Entity):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def script(self):
|
def script(self):
|
||||||
|
# graph = SceneManager().scene.entities['level'].graph
|
||||||
|
|
||||||
|
# cur_node = graph[self.y//S][self.x//S]
|
||||||
|
# # print(self.y//S, self.x//S)
|
||||||
|
# pacman = SceneManager().scene.entities['pacman']
|
||||||
|
# x_dist = pacman.x - self.x
|
||||||
|
# y_dist = pacman.y - self.y
|
||||||
|
# s = 1
|
||||||
|
# p = self.find_shortest_path(graph[pacman.y//S][pacman.x//S])
|
||||||
|
# # print([x[1] for x in p])
|
||||||
|
# cur_dir = p[0][1]
|
||||||
|
# if cur_dir == Direction.UP:
|
||||||
|
# self.phys.vx = 0
|
||||||
|
# self.phys.vy = -1
|
||||||
|
# elif cur_dir == Direction.DOWN:
|
||||||
|
# self.phys.vx = 0
|
||||||
|
# self.phys.vy = 1
|
||||||
|
# elif cur_dir == Direction.LEFT:
|
||||||
|
# self.phys.vx = -1
|
||||||
|
# self.phys.vy = 0
|
||||||
|
# else:
|
||||||
|
# self.phys.vx = 1
|
||||||
|
# self.phys.vy = 0
|
||||||
|
|
||||||
if self.direction == Direction.UP:
|
if self.direction == Direction.UP:
|
||||||
self.phys.vy = -Ghost.SPEED
|
self.phys.vy = -Ghost.SPEED
|
||||||
self.phys.vx = 0
|
self.phys.vx = 0
|
||||||
@ -75,3 +92,20 @@ class Ghost(Entity):
|
|||||||
elif self.direction == Direction.RIGHT:
|
elif self.direction == Direction.RIGHT:
|
||||||
self.phys.vx = Ghost.SPEED
|
self.phys.vx = Ghost.SPEED
|
||||||
self.phys.vy = 0
|
self.phys.vy = 0
|
||||||
|
|
||||||
|
def find_shortest_path(self, final_node):
|
||||||
|
graph = SceneManager().scene.entities['level'].graph
|
||||||
|
cur_node = graph[self.y//S][self.x//S]
|
||||||
|
children = cur_node.children
|
||||||
|
trace = [cur_node] + [x[0] for x in children]
|
||||||
|
paths = [[x] for x in children]
|
||||||
|
while 1:
|
||||||
|
cur_len = len(paths)
|
||||||
|
for path in paths[:cur_len]:
|
||||||
|
for child in path[-1][0].children:
|
||||||
|
if child[0] is not None and child[0] not in trace:
|
||||||
|
trace.append(child[0])
|
||||||
|
paths.append(path + [child])
|
||||||
|
if child[0] == final_node:
|
||||||
|
return path
|
||||||
|
paths = paths[cur_len:]
|
||||||
|
@ -8,10 +8,27 @@ from engine.servers.graphics import GraphicsServer
|
|||||||
from engine.components.collide_rect import CollideRect
|
from engine.components.collide_rect import CollideRect
|
||||||
from engine.components.sprite import Sprite
|
from engine.components.sprite import Sprite
|
||||||
|
|
||||||
from .common import S
|
from .common import S, Direction
|
||||||
from .pacdot import PacDot, EnsmallmentDot
|
from .pacdot import PacDot, EnsmallmentDot
|
||||||
|
|
||||||
|
|
||||||
|
class Node():
|
||||||
|
cpt = 0
|
||||||
|
def __init__(self):
|
||||||
|
self.id = self.__class__.cpt
|
||||||
|
self.__class__.cpt += 1
|
||||||
|
self.neighbors = [None for dir in Direction]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def children(self):
|
||||||
|
children = []
|
||||||
|
for direction in Direction:
|
||||||
|
node = self.neighbors[direction.value]
|
||||||
|
if node is not None:
|
||||||
|
children.append((node, direction))
|
||||||
|
return children
|
||||||
|
|
||||||
|
|
||||||
class Level(Entity):
|
class Level(Entity):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
super().__init__('level')
|
super().__init__('level')
|
||||||
@ -25,6 +42,7 @@ class Level(Entity):
|
|||||||
self.surf.fill((0, 0, 0))
|
self.surf.fill((0, 0, 0))
|
||||||
wall = Surface((S, S)).convert()
|
wall = Surface((S, S)).convert()
|
||||||
wall.fill((0, 0, 255))
|
wall.fill((0, 0, 255))
|
||||||
|
self.graph = [[None for x in range(w)] for y in range(h)]
|
||||||
for x, y in product(range(w), range(h)):
|
for x, y in product(range(w), range(h)):
|
||||||
col = desc.get_at((x, y))
|
col = desc.get_at((x, y))
|
||||||
if col == (0, 0, 255):
|
if col == (0, 0, 255):
|
||||||
@ -36,9 +54,24 @@ class Level(Entity):
|
|||||||
pc.y = y * S
|
pc.y = y * S
|
||||||
self.scene.add(pc)
|
self.scene.add(pc)
|
||||||
PacDot.tot += 1
|
PacDot.tot += 1
|
||||||
|
self.graph[y][x] = Node()
|
||||||
|
elif col == (0, 0, 0) or col == (255, 0, 0):
|
||||||
|
self.graph[y][x] = Node()
|
||||||
elif col == (193, 193, 193):
|
elif col == (193, 193, 193):
|
||||||
pc = EnsmallmentDot()
|
pc = EnsmallmentDot()
|
||||||
pc.x = x * S
|
pc.x = x * S
|
||||||
pc.y = y * S
|
pc.y = y * S
|
||||||
self.scene.add(pc)
|
self.scene.add(pc)
|
||||||
self.add(Sprite(self.surf, 0))
|
self.add(Sprite(self.surf, 0))
|
||||||
|
for y, line in enumerate(self.graph):
|
||||||
|
for x, node in enumerate(line):
|
||||||
|
if node is None:
|
||||||
|
continue
|
||||||
|
node.neighbors[Direction.LEFT.value] = \
|
||||||
|
self.graph[y][(x-1)%w]
|
||||||
|
node.neighbors[Direction.RIGHT.value] = \
|
||||||
|
self.graph[y][(x+1)%w]
|
||||||
|
node.neighbors[Direction.UP.value] = \
|
||||||
|
self.graph[(y-1)%h][x]
|
||||||
|
node.neighbors[Direction.DOWN.value] = \
|
||||||
|
self.graph[(y+1)%h][x]
|
||||||
|
@ -16,9 +16,10 @@ class PacMan(Entity):
|
|||||||
|
|
||||||
def __init__(self, x, y):
|
def __init__(self, x, y):
|
||||||
super().__init__('pacman')
|
super().__init__('pacman')
|
||||||
surf_1 = image.load(res('pacman_1.png')).convert()
|
self.x = x
|
||||||
surf_2 = image.load(res('pacman_2.png')).convert()
|
self.y = y
|
||||||
|
|
||||||
|
# Surface quand on est petit.
|
||||||
self.smol_surf = Surface((S//2, S//2)).convert()
|
self.smol_surf = Surface((S//2, S//2)).convert()
|
||||||
self.smol_surf.fill((0, 0, 0))
|
self.smol_surf.fill((0, 0, 0))
|
||||||
draw.circle(self.smol_surf,
|
draw.circle(self.smol_surf,
|
||||||
@ -26,6 +27,10 @@ class PacMan(Entity):
|
|||||||
(S//4, S//4),
|
(S//4, S//4),
|
||||||
S//4)
|
S//4)
|
||||||
|
|
||||||
|
# Surfaces pour chaque direction, pour chaque état de
|
||||||
|
# l’animation.
|
||||||
|
surf_1 = image.load(res('pacman_1.png')).convert()
|
||||||
|
surf_2 = image.load(res('pacman_2.png')).convert()
|
||||||
self.surf = [[transform.rotate(surf_1, 90),
|
self.surf = [[transform.rotate(surf_1, 90),
|
||||||
transform.rotate(surf_1, -90),
|
transform.rotate(surf_1, -90),
|
||||||
transform.flip(surf_1, True, False),
|
transform.flip(surf_1, True, False),
|
||||||
@ -35,14 +40,18 @@ class PacMan(Entity):
|
|||||||
transform.flip(surf_2, True, False),
|
transform.flip(surf_2, True, False),
|
||||||
surf_2]]
|
surf_2]]
|
||||||
|
|
||||||
|
# État d’animation courant.
|
||||||
self.cur_anim = 0
|
self.cur_anim = 0
|
||||||
|
|
||||||
self.sprite = self.add(Sprite(self.surf[self.cur_anim][0], 2))
|
self.sprite = self.add(Sprite(self.surf[self.cur_anim][0], 2))
|
||||||
|
|
||||||
|
# Rectangle quand on est petit.
|
||||||
self.smol_rect = Rect(self.x, self.y,
|
self.smol_rect = Rect(self.x, self.y,
|
||||||
self.sprite.width//2, self.sprite.width//2)
|
self.sprite.width//2, self.sprite.width//2)
|
||||||
|
|
||||||
self.rect = Rect(self.x, self.y,
|
self.rect = Rect(self.x, self.y,
|
||||||
self.sprite.width, self.sprite.width)
|
self.sprite.width, self.sprite.width)
|
||||||
|
|
||||||
self.phys = CollideRect(self.rect,
|
self.phys = CollideRect(self.rect,
|
||||||
static=False,
|
static=False,
|
||||||
cb=self.cb)
|
cb=self.cb)
|
||||||
@ -50,17 +59,18 @@ class PacMan(Entity):
|
|||||||
self.add(self.phys)
|
self.add(self.phys)
|
||||||
|
|
||||||
self.script = PacMan.update
|
self.script = PacMan.update
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.smol = False
|
self.smol = False
|
||||||
self.smol_since = None
|
self.smol_since = None
|
||||||
|
|
||||||
def cb(self, c):
|
def cb(self, c):
|
||||||
if not isinstance(c.parent, EnsmallmentDot):
|
if not isinstance(c.parent, EnsmallmentDot):
|
||||||
return
|
return
|
||||||
|
# On a mangé une graine de rapetissement.
|
||||||
if not self.smol:
|
if not self.smol:
|
||||||
|
# Décalage au milieu du couloir
|
||||||
self.x += S//4
|
self.x += S//4
|
||||||
self.y += S//4
|
self.y += S//4
|
||||||
|
|
||||||
PacMan.SPEED *= 2
|
PacMan.SPEED *= 2
|
||||||
self.smol_rect.x = self.x
|
self.smol_rect.x = self.x
|
||||||
self.smol_rect.y = self.y
|
self.smol_rect.y = self.y
|
||||||
@ -72,22 +82,24 @@ class PacMan(Entity):
|
|||||||
p = self.phys
|
p = self.phys
|
||||||
s = self.sprite
|
s = self.sprite
|
||||||
|
|
||||||
# Expiration du pouvoir
|
# Expiration du rapetissement.
|
||||||
if self.smol and Game.cur_tick - self.smol_since > 60*2:
|
if self.smol and Game.cur_tick - self.smol_since > 60*2:
|
||||||
|
# On se réaligne dans le couloir.
|
||||||
self.x -= self.x % S
|
self.x -= self.x % S
|
||||||
self.y -= self.y % S
|
self.y -= self.y % S
|
||||||
|
|
||||||
self.rect.x = self.x
|
self.rect.x = self.x
|
||||||
self.rect.y = self.y
|
self.rect.y = self.y
|
||||||
self.phys.rect = self.rect
|
self.phys.rect = self.rect
|
||||||
self.smol = False
|
self.smol = False
|
||||||
PacMan.SPEED = PacMan.SPEED//2
|
PacMan.SPEED = PacMan.SPEED//2
|
||||||
|
|
||||||
# Avance l’animation
|
# Avance l’état d’animation.
|
||||||
if Game.cur_tick % 5 == 0:
|
if Game.cur_tick % 5 == 0:
|
||||||
self.cur_anim += 1
|
self.cur_anim += 1
|
||||||
self.cur_anim %= 2
|
self.cur_anim %= 2
|
||||||
|
|
||||||
# Nouvelle sprite
|
# Choix de la surface en fonction de la direction effective.
|
||||||
if p.vy < 0:
|
if p.vy < 0:
|
||||||
s.surf = self.surf[self.cur_anim][0]
|
s.surf = self.surf[self.cur_anim][0]
|
||||||
elif p.vy > 0:
|
elif p.vy > 0:
|
||||||
@ -102,6 +114,8 @@ class PacMan(Entity):
|
|||||||
|
|
||||||
inputs = key.get_pressed()
|
inputs = key.get_pressed()
|
||||||
if self.smol:
|
if self.smol:
|
||||||
|
# Quand on est petit on n’a pas de maintient de la
|
||||||
|
# vitesse.
|
||||||
p.vx = 0
|
p.vx = 0
|
||||||
p.vy = 0
|
p.vy = 0
|
||||||
if inputs[K_UP]:
|
if inputs[K_UP]:
|
||||||
|
@ -11,9 +11,9 @@ class Lvl0(Scene):
|
|||||||
self.add(Level('lvl0.png'))
|
self.add(Level('lvl0.png'))
|
||||||
self.add(PacMan(S, S))
|
self.add(PacMan(S, S))
|
||||||
self.add(Ghost(S*6, S*2))
|
self.add(Ghost(S*6, S*2))
|
||||||
self.add(Ghost(S*6, S*13))
|
# self.add(Ghost(S*6, S*13))
|
||||||
self.add(Ghost(S*18, S*13))
|
# self.add(Ghost(S*18, S*13))
|
||||||
self.add(Ghost(S*8, S*23))
|
# self.add(Ghost(S*8, S*23))
|
||||||
super().load()
|
super().load()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,171 +0,0 @@
|
|||||||
from engine.scene import Scene
|
|
||||||
|
|
||||||
|
|
||||||
S=20
|
|
||||||
|
|
||||||
|
|
||||||
entities=[]
|
|
||||||
|
|
||||||
|
|
||||||
class PacDot(Entity):
|
|
||||||
s = Surface((S, S))
|
|
||||||
draw.circle(s, (255, 255, 0), (S//2, S//2), S//4)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
CollideRect(self, Rect(0, 0, S, S),
|
|
||||||
static=True, solid=False, cb=self.cb)
|
|
||||||
Sprite(self, PacDot.s, 1)
|
|
||||||
|
|
||||||
def cb(self):
|
|
||||||
self.unregister()
|
|
||||||
|
|
||||||
|
|
||||||
def path(start, tgt, x, y, trace, length):
|
|
||||||
if start == tgt:
|
|
||||||
return length
|
|
||||||
if start is None or trace[y][x]:
|
|
||||||
return False
|
|
||||||
trace[y][x] = True
|
|
||||||
u = path(start.up, tgt, x, y-1, trace, length + 1)
|
|
||||||
d = path(start.down, tgt, x, y+1, trace, length + 1)
|
|
||||||
l = path(start.left, tgt, x-1, y, trace, length + 1)
|
|
||||||
r = path(start.right, tgt, x+1, y, trace, length + 1)
|
|
||||||
best = None
|
|
||||||
for subpath in (u, d, l, r):
|
|
||||||
if subpath and (best is None or subpath < best):
|
|
||||||
best = subpath
|
|
||||||
return best
|
|
||||||
|
|
||||||
|
|
||||||
class Node():
|
|
||||||
cpt = 0
|
|
||||||
def __init__(self):
|
|
||||||
self.id = self.__class__.cpt
|
|
||||||
self.__class__.cpt += 1
|
|
||||||
self.up = None
|
|
||||||
self.down = None
|
|
||||||
self.left = None
|
|
||||||
self.right = None
|
|
||||||
def children(self):
|
|
||||||
children = []
|
|
||||||
for direction in ("up", "down", "left", "right"):
|
|
||||||
node = getattr(self, direction)
|
|
||||||
if node is not None:
|
|
||||||
children.append((node, direction))
|
|
||||||
return children
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
graph = None
|
|
||||||
|
|
||||||
|
|
||||||
class Level(Entity):
|
|
||||||
def __init__(self, path):
|
|
||||||
global graph
|
|
||||||
super().__init__()
|
|
||||||
desc = image.load(res(path))
|
|
||||||
w, h = desc.get_size()
|
|
||||||
GraphicsServer().resize((w * S, h * S))
|
|
||||||
graph = [[None for x in range(w)] for y in range(h)]
|
|
||||||
self.surf = Surface((w * S, h * S)).convert()
|
|
||||||
self.surf.fill((0, 0, 0))
|
|
||||||
wall = Surface((S, S)).convert()
|
|
||||||
wall.fill((0, 0, 255))
|
|
||||||
for x, y in product(range(w), range(h)):
|
|
||||||
col = desc.get_at((x, y))
|
|
||||||
if col == (0, 0, 255):
|
|
||||||
CollideRect(self, Rect(x * S, y * S, S, S))
|
|
||||||
self.surf.blit(wall, (x * S, y * S))
|
|
||||||
elif col == (139, 139, 139):
|
|
||||||
pc = PacDot()
|
|
||||||
pc.x = x * S
|
|
||||||
pc.y = y * S
|
|
||||||
entities.append(pc)
|
|
||||||
graph[y][x] = Node()
|
|
||||||
elif col == (0, 0, 0) or col == (255, 0, 0):
|
|
||||||
graph[y][x] = Node()
|
|
||||||
for y, line in enumerate(graph):
|
|
||||||
for x, node in enumerate(line):
|
|
||||||
if node is None:
|
|
||||||
continue
|
|
||||||
node.left = graph[y][(x-1)%w]
|
|
||||||
node.right = graph[y][(x+1)%w]
|
|
||||||
node.up = graph[(y-1)%h][x]
|
|
||||||
node.down = graph[(y+1)%h][x]
|
|
||||||
Sprite(self, self.surf, 0)
|
|
||||||
|
|
||||||
|
|
||||||
class MovingEntity(Entity):
|
|
||||||
def __init__(self, surf):
|
|
||||||
super().__init__()
|
|
||||||
sprite = Sprite(self, surf, 2)
|
|
||||||
self.phys = CollideRect(
|
|
||||||
self,
|
|
||||||
Rect(self.x, self.y, sprite.width, sprite.width),
|
|
||||||
static=False)
|
|
||||||
|
|
||||||
|
|
||||||
class Ghost(MovingEntity):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(image.load(res('ghost.png')).convert())
|
|
||||||
self.script = Ghost.script
|
|
||||||
|
|
||||||
def script(self):
|
|
||||||
cur_node = graph[self.y//S][self.x//S]
|
|
||||||
print(self.y//S, self.x//S)
|
|
||||||
pacman = SceneManager().scene.entities['pacman']
|
|
||||||
# pacman_node = graph[pacman.y//S][pacman.x//S]
|
|
||||||
x_dist = pacman.x - self.x
|
|
||||||
y_dist = pacman.y - self.y
|
|
||||||
s = 1
|
|
||||||
# self.phys.vx = s if x_dist > 0 else -s
|
|
||||||
# self.phys.vy = s if y_dist > 0 else -s
|
|
||||||
p = self.find_shortest_path(graph[pacman.y//S][pacman.x//S])
|
|
||||||
print([x[1] for x in p])
|
|
||||||
cur_dir = p[0][1]
|
|
||||||
if cur_dir == "up":
|
|
||||||
self.phys.vx = 0
|
|
||||||
self.phys.vy = -1
|
|
||||||
elif cur_dir == "down":
|
|
||||||
self.phys.vx = 0
|
|
||||||
self.phys.vy = 1
|
|
||||||
elif cur_dir == "left":
|
|
||||||
self.phys.vx = -1
|
|
||||||
self.phys.vy = 0
|
|
||||||
else:
|
|
||||||
self.phys.vx = 1
|
|
||||||
self.phys.vy = 0
|
|
||||||
def find_shortest_path(self, final_node):
|
|
||||||
cur_node = graph[self.y//S][self.x//S]
|
|
||||||
# pacman_node = graph[pacman.y//S][pacman.x//S]
|
|
||||||
children = cur_node.children()
|
|
||||||
trace = [cur_node] + [x[0] for x in children]
|
|
||||||
# if self.phys.vx < 0: cur_dir = "left"
|
|
||||||
# elif self.phys.vx > 0: cur_dir = "right"
|
|
||||||
# elif self.phys.vy < 0: cur_dir = "up"
|
|
||||||
# else: cur_dir = "down"
|
|
||||||
paths = [[x] for x in children]
|
|
||||||
while 1:
|
|
||||||
cur_len = len(paths)
|
|
||||||
for path in paths[:cur_len]:
|
|
||||||
for child in path[-1][0].children():
|
|
||||||
if child[0] is not None and child[0] not in trace:
|
|
||||||
trace.append(child[0])
|
|
||||||
paths.append(path + [child])
|
|
||||||
if child[0] == final_node:
|
|
||||||
return path
|
|
||||||
paths = paths[cur_len:]
|
|
||||||
|
|
||||||
class Lvl0(Scene):
|
|
||||||
def load(self):
|
|
||||||
self.add(Level('lvl0.png'))
|
|
||||||
self.add(PacMan(S, S))
|
|
||||||
self.add(Ghost(S*6, S*2))
|
|
||||||
self.add(Ghost(S*6, S*13))
|
|
||||||
self.add(Ghost(S*18, S*13))
|
|
||||||
self.add(Ghost(S*8, S*23))
|
|
||||||
super().load()
|
|
||||||
|
|
||||||
|
|
||||||
scene = Lvl0()
|
|
Reference in New Issue
Block a user