séance TD + générer carte depuis image - modèle Gimp présent - instructions couleurs (lel) présente - todo: pareil avec padots - facile, maintenant on pourra collisions
This commit is contained in:
parent
a8c79b1c47
commit
13d579fa45
3
iteration_2_voulue_par_prof.txt
Normal file
3
iteration_2_voulue_par_prof.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
1- afficher pacman dans fenêtre
|
||||||
|
2- gérer déplacements sans sortir de la fenêtre (sans forcément être dans le labyrinthe) -
|
||||||
|
des murs autour avec notre gestion de collision
|
BIN
pacmap.xcf
Normal file
BIN
pacmap.xcf
Normal file
Binary file not shown.
BIN
pacmap_empty.png
Normal file
BIN
pacmap_empty.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 571 B |
BIN
pacmap_maze1.png
Normal file
BIN
pacmap_maze1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
pacmap_maze1.xcf
Normal file
BIN
pacmap_maze1.xcf
Normal file
Binary file not shown.
9
pacmap_rule.txt
Normal file
9
pacmap_rule.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
chaque mur (sauf le mur extérieur) est d'épaisseur 2 minimum, peut être espacé par des FIT
|
||||||
|
codage RGB:
|
||||||
|
GRD 0 0 0
|
||||||
|
GCF 255 0 255
|
||||||
|
WAL 0 0 255
|
||||||
|
GSD 0 255 0
|
||||||
|
GWL 0 255 255
|
||||||
|
TPT 255 0 0
|
||||||
|
FIT 255 255 255
|
118
src/carte.py
118
src/carte.py
@ -1,118 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from enum import IntEnum
|
|
||||||
|
|
||||||
class DotTile(IntEnum):
|
|
||||||
NDT = 0 # no dot
|
|
||||||
SPD = 1 # small pac-dot
|
|
||||||
BPD = 2 # big pac-dot
|
|
||||||
|
|
||||||
class PhysTile(IntEnum):
|
|
||||||
GRD = 0 # ground
|
|
||||||
WAL = 1 # wall
|
|
||||||
GSD = 2 # ghost door
|
|
||||||
TPT = 3 # teleporter tile
|
|
||||||
FIT = 4 # fully inaccessible tile
|
|
||||||
# ghost-cell ground as FIT ? verify no pac-dot here
|
|
||||||
|
|
||||||
class Map:
|
|
||||||
"""
|
|
||||||
Pacman maps size is 28×31
|
|
||||||
"""
|
|
||||||
|
|
||||||
width = 28
|
|
||||||
height = 31
|
|
||||||
|
|
||||||
def __init__(self, physic_map = [], dots_map = []):
|
|
||||||
"""
|
|
||||||
physic_map is the array containing elements:
|
|
||||||
0: ground tile
|
|
||||||
1: wall
|
|
||||||
2: ghost door
|
|
||||||
3: teleporter (no need to precise which to go because we assume it will
|
|
||||||
be at the opposite map tile)
|
|
||||||
4: fully inaccessible tile (basically tiles that represent the "in-wall"
|
|
||||||
space)
|
|
||||||
|
|
||||||
dots_map is a layer on top of the physic_map of the same dimension which contains
|
|
||||||
0: no dot
|
|
||||||
1: small pac-dot
|
|
||||||
2: big pac-dot
|
|
||||||
"""
|
|
||||||
self.phys_map = phys_map # in the first part we assume phys_map is correct and no need to verify
|
|
||||||
self.dots_map = dots_map
|
|
||||||
self.intersect_map = [] # TODO - the layer which contains intersections pre-calculated
|
|
||||||
|
|
||||||
|
|
||||||
def verify(self, phys_map, dots_map) -> boolean:
|
|
||||||
"""
|
|
||||||
This method will verify if a given map is valid or not
|
|
||||||
Return True if correct else False
|
|
||||||
|
|
||||||
we will assume
|
|
||||||
there are only:
|
|
||||||
- 1 ghost door
|
|
||||||
- 4 big pac-dots
|
|
||||||
- 240 pac-dots
|
|
||||||
|
|
||||||
Each ground tile must have at least 2 ground tile neighboors because
|
|
||||||
there is no dead-end tile in pac-man
|
|
||||||
Each dot must be on a ground tile (not even a teleporter one)
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not (len(phys_map) == len(dots_map) == 31):
|
|
||||||
return False
|
|
||||||
|
|
||||||
for i in range(len(phys_map)):
|
|
||||||
if not (len(phys_map[i]) == len(dots_map[i]) == 28):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 1 ghost door verification
|
|
||||||
if sum(sub_arr.count(PhysTile.GSD) for sub_arr in phys_map) != 1:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# # 4 big pac dots
|
|
||||||
if sum(sub_arr.count(DotTile.BPD) for sub_arr in dots_map) != 4:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# # 240 small pac-dots
|
|
||||||
if sum(sub_arr.count(DotTile.SPD) for sub_arr in dots_map) != 240:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# dots are only in ground tile
|
|
||||||
for row in range(len(phys_map)):
|
|
||||||
for col in range(len(phys_map[0])):
|
|
||||||
if dots_map[row][col] and phys_map[row][col]: # no dot = 0; ground = 0
|
|
||||||
return False
|
|
||||||
|
|
||||||
# odd number of teleporter tiles
|
|
||||||
teleporter_count = sum(sub_arr.count(PhysTile.TPT) for sub_arr in phys_map)
|
|
||||||
if teleporter_count % 2:
|
|
||||||
return False
|
|
||||||
|
|
||||||
edges = phys_map[0][1:] + phys_map[height-1][1:] + [sub[0] for sub in phys_map] + [sub[width-1] for sub in phys_map][1:-1]
|
|
||||||
|
|
||||||
# must verify teleporters are on edges
|
|
||||||
teleporter_count -= edges.count(PhysTile.TPT)
|
|
||||||
if teleporter_count: # not all teleporters are on edges
|
|
||||||
return False
|
|
||||||
|
|
||||||
### ATTENTION - we need to verify teleporters are in front of the other
|
|
||||||
|
|
||||||
# no ground tile on border
|
|
||||||
if any(PhysTile.GRD in edges):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# now we have to verify there is no dead-end ground tile
|
|
||||||
for col in range(1, width-1):
|
|
||||||
for row in range(1, height-1):
|
|
||||||
cpt = 0
|
|
||||||
for x, y in ((0, 1), (1, 0), (-1, 0), (0, -1)):
|
|
||||||
if list[row+y][col+x] in (PhysTile.GRD, PhysTile.TPT, PhysTile.BPD, PhysTile.SPD):
|
|
||||||
cpt += 1
|
|
||||||
if cpt == 2:
|
|
||||||
break
|
|
||||||
if cpt < 2:
|
|
||||||
return False
|
|
||||||
# we have to verify if there is only 1 connexity component of (PhysTile.GRD, PhysTile.TPT, PhysTile.BPD, PhysTile.SPD)
|
|
||||||
|
|
||||||
return True
|
|
25
src/pacman.py
Normal file → Executable file
25
src/pacman.py
Normal file → Executable file
@ -31,6 +31,7 @@ class Pacman:
|
|||||||
self.next_direction = Direction.R
|
self.next_direction = Direction.R
|
||||||
self.super_power = 0 # Counter of super pacdots in effect (> 0 means super power is active)
|
self.super_power = 0 # Counter of super pacdots in effect (> 0 means super power is active)
|
||||||
self.ghost_combo = 0
|
self.ghost_combo = 0
|
||||||
|
self.size = (1.8, 1.8) # size related to tile size
|
||||||
|
|
||||||
def matrix_position(self):
|
def matrix_position(self):
|
||||||
return (int(self.position[0]), int(self.position[1]))
|
return (int(self.position[0]), int(self.position[1]))
|
||||||
@ -38,16 +39,18 @@ class Pacman:
|
|||||||
def has_super_power(self):
|
def has_super_power(self):
|
||||||
return self.super_power > 0
|
return self.super_power > 0
|
||||||
|
|
||||||
def eat_pacdot(self, map):
|
def eat_pacdot(self, dot_map):
|
||||||
global score
|
global score
|
||||||
global pacdot_counter
|
global pacdot_counter
|
||||||
map.dots_map[self.matrix_position()[0]][self.matrix_position()[1]] = pacmap.DotTile.NDT
|
dot_map.dots_map[self.matrix_position()[0]][self.matrix_position()[1]] = pacmap.DotTile.NDT
|
||||||
pacdot_counter -= 1
|
pacdot_counter -= 1
|
||||||
score += 10
|
score += 10
|
||||||
|
if pacdot_counter == 0:
|
||||||
|
game_over("win")
|
||||||
|
|
||||||
def eat_super_pacdot(self, map):
|
def eat_super_pacdot(self, dot_map):
|
||||||
global score
|
global score
|
||||||
map.dots_map[self.matrix_position()[0]][self.matrix_position()[1]] = pacmap.DotTile.NDT
|
dot_map.dots_map[self.matrix_position()[0]][self.matrix_position()[1]] = pacmap.DotTile.NDT
|
||||||
score += 50
|
score += 50
|
||||||
self.super_power += 1
|
self.super_power += 1
|
||||||
|
|
||||||
@ -62,26 +65,26 @@ class Pacman:
|
|||||||
self.ghost_combo = 0
|
self.ghost_combo = 0
|
||||||
#os._exit(0)
|
#os._exit(0)
|
||||||
|
|
||||||
def eat_fruit(self, fruit, map):
|
def eat_fruit(self, fruit, dot_map):
|
||||||
global score
|
global score
|
||||||
map.dots_map[self.matrix_position()[0]][self.matrix_position()[1]] = pacmap.DotTile.NDT
|
dot_map.dots_map[self.matrix_position()[0]][self.matrix_position()[1]] = pacmap.DotTile.NDT
|
||||||
score += fruit.score
|
score += fruit.score
|
||||||
|
|
||||||
def eat_ghost(self, ghost):
|
def eat_ghost(self, ghost):
|
||||||
global score
|
global score
|
||||||
ghost.despawn_and_respawn()
|
ghost.despawn_and_respawn()
|
||||||
self.ghost_combo += 1
|
self.ghost_combo += 1
|
||||||
score += (2 ^ self.ghost_combo) * 100
|
score += (2 ** self.ghost_combo) * 100
|
||||||
|
|
||||||
def get_eaten(self, map):
|
def get_eaten(self, dot_map):
|
||||||
global lives
|
global lives
|
||||||
#TODO score loss ?
|
#TODO score loss ?
|
||||||
self.position = map.spawn_point #TODO
|
self.position = dot_map.spawn_point #TODO
|
||||||
lives -= 1
|
lives -= 1
|
||||||
if lives <= 0:
|
if lives < 0: # à vérifier
|
||||||
game_over()
|
game_over()
|
||||||
|
|
||||||
def game_over():
|
def game_over(status = "lose"):
|
||||||
#TODO
|
#TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
from PIL import Image
|
||||||
|
import os
|
||||||
|
|
||||||
class DotTile(IntEnum):
|
class DotTile(IntEnum):
|
||||||
NDT = 0 # no dot
|
NDT = 0 # no dot
|
||||||
SPD = 1 # small pac-dot
|
SPD = 1 # small pac-dot
|
||||||
BPD = 2 # big pac-dot
|
BPD = 2 # big pac-dot
|
||||||
|
FRT = 3 # fruit
|
||||||
|
|
||||||
class PhysTile(IntEnum):
|
class PhysTile(IntEnum):
|
||||||
GRD = 0 # ground
|
GRD = 0 # ground
|
||||||
WAL = 1 # wall
|
WAL = 1 # wall
|
||||||
GSD = 2 # ghost door
|
GSD = 2 # ghost door
|
||||||
TPT = 3 # teleporter tile
|
GWL = 3 # ghost cell wall
|
||||||
FIT = 4 # fully inaccessible tile
|
GCF = 4 # ghost cell floor
|
||||||
|
TPT = 5 # teleporter tile
|
||||||
|
FIT = 6 # fully inaccessible tile
|
||||||
# ghost-cell ground as FIT ? verify no pac-dot here
|
# ghost-cell ground as FIT ? verify no pac-dot here
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
@ -20,11 +25,11 @@ class Map:
|
|||||||
Pacman maps size is 28×31
|
Pacman maps size is 28×31
|
||||||
"""
|
"""
|
||||||
|
|
||||||
width = 28
|
width = 28 * 2 + 1
|
||||||
height = 31
|
height = 31 * 2 + 1
|
||||||
tile_size = 16 # tile subdivision for dynamic movement
|
# tile_size = 16 # tile subdivision for dynamic movement
|
||||||
|
|
||||||
def __init__(self, phys_map = [], dots_map = []):
|
def __init__(self, phys_map = [], dots_map = [], maze_img_file=""):
|
||||||
"""
|
"""
|
||||||
physic_map is the array containing elements:
|
physic_map is the array containing elements:
|
||||||
0: ground tile
|
0: ground tile
|
||||||
@ -40,6 +45,11 @@ class Map:
|
|||||||
1: small pac-dot
|
1: small pac-dot
|
||||||
2: big pac-dot
|
2: big pac-dot
|
||||||
"""
|
"""
|
||||||
|
if maze_img_file and os.path.isfile(maze_img_file):
|
||||||
|
try:
|
||||||
|
self.phys_map = decode_map(maze_img_file)
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
self.phys_map = phys_map # in the first part we assume phys_map is correct and no need to verify
|
self.phys_map = phys_map # in the first part we assume phys_map is correct and no need to verify
|
||||||
self.dots_map = dots_map
|
self.dots_map = dots_map
|
||||||
self.intersect_map = [] # TODO - the layer which contains intersections pre-calculated
|
self.intersect_map = [] # TODO - the layer which contains intersections pre-calculated
|
||||||
@ -158,3 +168,26 @@ def connex(matrix, x=-1, y=-1):
|
|||||||
if any(tile in (PhysTile.GRD, PhysTile.TPT) for row in temp for tile in row):
|
if any(tile in (PhysTile.GRD, PhysTile.TPT) for row in temp for tile in row):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def decode_map(img_file):
|
||||||
|
img = Image.open(img_file)
|
||||||
|
dictionnary = {
|
||||||
|
(0 , 0, 0): PhysTile.GRD,
|
||||||
|
(255, 0, 255): PhysTile.GCF,
|
||||||
|
(0 , 0, 255): PhysTile.WAL,
|
||||||
|
(0 , 255, 0): PhysTile.GSD,
|
||||||
|
(0 , 255, 255): PhysTile.GWL,
|
||||||
|
(255, 0, 0): PhysTile.TPT,
|
||||||
|
(255, 255, 0): PhysTile.FIT,
|
||||||
|
}
|
||||||
|
data = list(img.getdata())
|
||||||
|
matrix = []
|
||||||
|
for row in range(img.height):
|
||||||
|
matrix.append([])
|
||||||
|
for col in range(img.width):
|
||||||
|
try:
|
||||||
|
tile = dictionnary[data[col + row*img.width][:3]] # avoid alpha component
|
||||||
|
except:
|
||||||
|
raise ValueError("Pixel " + str(col) + "," + str(row) + " is invalid")
|
||||||
|
matrix[-1].append(tile)
|
||||||
|
return matrix
|
13
src/test_load_picture.py
Executable file
13
src/test_load_picture.py
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from pacmap import decode_map
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
matrix = decode_map(sys.argv[1])
|
||||||
|
else:
|
||||||
|
matrix = decode_map("../pacmap_maze1.png")
|
||||||
|
for row in matrix:
|
||||||
|
print()
|
||||||
|
for el in row:
|
||||||
|
print(el.value, end=' ')
|
Reference in New Issue
Block a user