Massive static code cleanup
- Translating comments - Flake8 & Pylint checking - Adjust variable name consistency - Rename tiles filename (and adds files)
130
conf.py
|
@ -5,60 +5,78 @@ Licence: `GNU GPL v3` GNU GPL v3: http://www.gnu.org/licenses/
|
|||
|
||||
This file is part of [_ocp3_ project](https://github.com/freezed/ocp3)
|
||||
"""
|
||||
from math import floor
|
||||
import pygame
|
||||
import math
|
||||
|
||||
# CONFIGURATION
|
||||
ELEMENT_LIST = [
|
||||
{'symbol': 'n', 'name': 'needle', 'cross': True, 'ressurect': False, 'collect': True, 'tile': 'img/3-blue-transp-30.png'},
|
||||
{'symbol': 't', 'name': 'tube', 'cross': True, 'ressurect': False, 'collect': True, 'tile': 'img/1-blue-transp-30.png'},
|
||||
{'symbol': 'e', 'name': 'ether', 'cross': True, 'ressurect': False, 'collect': True, 'tile': 'img/2-blue-transp-30.png'},
|
||||
{'symbol': 'E', 'name': 'exit', 'cross': False, 'ressurect': False, 'collect': False, 'tile': 'img/g-orange-transp-30.png'},
|
||||
{'symbol': ' ', 'name': 'void', 'cross': True, 'ressurect': True, 'collect': False, 'tile': 'img/blue-white-30.png'},
|
||||
{'symbol': '.', 'name': 'wall', 'cross': False, 'ressurect': False, 'collect': False, 'tile': 'img/transp-30.png'},
|
||||
{'symbol': 'X', 'name': 'player', 'cross': False, 'ressurect': False, 'collect': False, 'tile': 'img/player-30.png'},
|
||||
{'symbol': '\n', 'name': 'nlin', 'cross': False, 'ressurect': False, 'collect': False, 'tile': False},
|
||||
]
|
||||
ELEMENTS = (
|
||||
{
|
||||
'symbol': 'n', 'name': 'needle', 'cross': True,
|
||||
'ressurect': False, 'collect': True, 'tile': 'img/3-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': 't', 'name': 'tube', 'cross': True,
|
||||
'ressurect': False, 'collect': True, 'tile': 'img/1-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': 'e', 'name': 'ether', 'cross': True,
|
||||
'ressurect': False, 'collect': True, 'tile': 'img/2-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': 'E', 'name': 'exit', 'cross': False,
|
||||
'ressurect': False, 'collect': False, 'tile': 'img/g-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': ' ', 'name': 'void', 'cross': True,
|
||||
'ressurect': True, 'collect': False, 'tile': 'img/void-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': '.', 'name': 'wall', 'cross': False,
|
||||
'ressurect': False, 'collect': False, 'tile': 'img/wall-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': 'X', 'name': 'player', 'cross': False,
|
||||
'ressurect': False, 'collect': False, 'tile': 'img/player-30.png'
|
||||
},
|
||||
{
|
||||
'symbol': '\n', 'name': 'nlin', 'cross': False,
|
||||
'ressurect': False, 'collect': False, 'tile': False
|
||||
},
|
||||
)
|
||||
|
||||
# Possible returns of a move, keep the «ok» at the end
|
||||
MOVE_STATUS = ['looser', 'wall', 'winner', 'collect', 'ok']
|
||||
MOVE_STATUS_MSG = {
|
||||
'looser': "Vous vous êtes fait assommé! Pour endormir le garde, il manqait: {}.\nPerdu!",
|
||||
'wall': "Le déplacement est stoppé par un mur.",
|
||||
'winner': "Gagné! Vous avez endormis le garde avec votre seringue.",
|
||||
'collect': "Vous ramassez l'objet «{}»",
|
||||
'ok': "Jusqu'ici, tout va bien…"
|
||||
}
|
||||
|
||||
CELL_SIZE_PX = 30 # Size of the tiles, in pixels
|
||||
MAZE_SIZE_TIL = 15 # Size of a map, in tiles
|
||||
FONT_SIZE = math.floor(0.9 * CELL_SIZE_PX)
|
||||
CELL_SIZE = 30 # Size of the tiles, in pixels
|
||||
MAZE_SIZE = 15 # Size of a map, in tiles
|
||||
BLACK = (0, 0, 0)
|
||||
BLUE = (0, 0, 128)
|
||||
GREEN = (0, 255, 0)
|
||||
WHITE = (255, 255, 255)
|
||||
|
||||
# Messages
|
||||
CAPTION = "OCP3, a pygame maze"
|
||||
CAPTION = "OCP3, a maze based on pygame"
|
||||
ERR_MAP = "ERR_MAP: «{}»"
|
||||
HEADER_MESSAGES = {
|
||||
HEAD_MESSAGES = {
|
||||
'title': "Welcome in OCP3.",
|
||||
'status': "Use arrow keys to play, any other key to quit.",
|
||||
'items': "Items: {}/{}",
|
||||
}
|
||||
MSG_COLLECT = "You pick «{}»"
|
||||
MSG_END = "End of game, press a key to quit."
|
||||
MSG_LOSER = "You lose! You were missing: {}."
|
||||
MSG_OK = "…"
|
||||
MSG_QUIT = "You decide to quit the game"
|
||||
MSG_WALL = "That's a wall!"
|
||||
MSG_WINNER = "Cogratulations! You asleep the guard."
|
||||
|
||||
# Files
|
||||
BACKGROUND_IMG = 'img/zebra-800.png'
|
||||
BACKGRND_FILE = 'img/back-800.png'
|
||||
MAP_FILE = '01.map'
|
||||
UNKNOWN_TILE = 'img/unknown-30.png'
|
||||
UNKNOWN_FILE = 'img/unknown-30.png'
|
||||
|
||||
# Constant calculation
|
||||
HEADER_HEIGHT = (2 * CELL_SIZE_PX)
|
||||
WINDOW_SIZE_PX_W = CELL_SIZE_PX * MAZE_SIZE_TIL
|
||||
WINDOW_SIZE_PX_H = WINDOW_SIZE_PX_W + HEADER_HEIGHT
|
||||
WIN_DIM = (WINDOW_SIZE_PX_W, WINDOW_SIZE_PX_H)
|
||||
FONT_SIZE = floor(0.9 * CELL_SIZE)
|
||||
HEAD_SIZE_H = (2 * CELL_SIZE)
|
||||
WIN_SIZE_W = CELL_SIZE * MAZE_SIZE
|
||||
WIN_SIZE_H = WIN_SIZE_W + HEAD_SIZE_H
|
||||
WIN_DIM = (WIN_SIZE_W, WIN_SIZE_H)
|
||||
|
||||
|
||||
# FUNCTIONS
|
||||
|
@ -66,7 +84,7 @@ WIN_DIM = (WINDOW_SIZE_PX_W, WINDOW_SIZE_PX_H)
|
|||
|
||||
def elmt_val(kval, ksel, vsel, nline=False):
|
||||
"""
|
||||
Return value(s) from ELEMENT_LIST
|
||||
Return value(s) from ELEMENTS
|
||||
|
||||
:param str kval: key of the value returned
|
||||
:param str ksel: key of the selection criteria
|
||||
|
@ -74,53 +92,59 @@ def elmt_val(kval, ksel, vsel, nline=False):
|
|||
:param bool/int nline: Default False, return value(s) in a list,
|
||||
use a int() to return the `n` value from the list
|
||||
|
||||
:return str/bool/…:
|
||||
"""
|
||||
try:
|
||||
if nline is False:
|
||||
return (element[kval] for element in ELEMENT_LIST if element[ksel] == vsel)
|
||||
return (element[kval] for element in ELEMENTS
|
||||
if element[ksel] == vsel)
|
||||
else:
|
||||
return [element[kval] for element in ELEMENT_LIST if element[ksel] == vsel][nline]
|
||||
return [element[kval] for element in ELEMENTS
|
||||
if element[ksel] == vsel][nline]
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
|
||||
def maze_draw(WINDOW, map_string):
|
||||
""" Take a map string and generate a graphic maze """
|
||||
def maze_draw(surface, map_string):
|
||||
"""
|
||||
Take a map string and generate a graphic maze
|
||||
|
||||
:param obj surface: a pygame surface object
|
||||
:param str map_string: map modelized in a string
|
||||
"""
|
||||
back_tiles = []
|
||||
for cell, element in enumerate(map_string):
|
||||
img = elmt_val('tile', 'symbol', element, 0)
|
||||
|
||||
if img is False:
|
||||
back_tiles.append(pygame.image.load(UNKNOWN_TILE).convert())
|
||||
back_tiles.append(pygame.image.load(UNKNOWN_FILE).convert())
|
||||
else:
|
||||
back_tiles.append(pygame.image.load(img).convert_alpha())
|
||||
|
||||
x = (cell % MAZE_SIZE_TIL) * CELL_SIZE_PX
|
||||
y = (cell // MAZE_SIZE_TIL) * CELL_SIZE_PX + HEADER_HEIGHT
|
||||
WINDOW.blit(back_tiles[cell], (x, y))
|
||||
x = (cell % MAZE_SIZE) * CELL_SIZE
|
||||
y = (cell // MAZE_SIZE) * CELL_SIZE + HEAD_SIZE_H
|
||||
surface.blit(back_tiles[cell], (x, y))
|
||||
|
||||
# Refresh
|
||||
pygame.display.flip()
|
||||
|
||||
|
||||
def set_header(WINDOW, messages):
|
||||
def set_header(surface, messages):
|
||||
"""
|
||||
Set the header message on the window
|
||||
|
||||
:param obj WINDOWS: display object
|
||||
:param obj surface: surface surfaceect
|
||||
:param list/str messages: list of messages per place
|
||||
"""
|
||||
pygame.draw.rect(WINDOW, BLACK, (0, 0, WINDOW_SIZE_PX_W, HEADER_HEIGHT))
|
||||
pygame.draw.rect(surface, BLACK, (0, 0, WIN_SIZE_W, HEAD_SIZE_H))
|
||||
|
||||
FONT = pygame.font.Font(None, FONT_SIZE)
|
||||
|
||||
h_title = FONT.render(str(messages['title']), True, BLUE, WHITE)
|
||||
h_status = FONT.render(str(messages['status']), True, WHITE, BLACK)
|
||||
h_items = FONT.render(str(messages['items']), True, GREEN, BLACK)
|
||||
h_title = FONT.render(messages['title'], True, BLUE, WHITE)
|
||||
h_status = FONT.render(messages['status'], True, WHITE, BLACK)
|
||||
h_items = FONT.render(messages['items'], True, GREEN, BLACK)
|
||||
|
||||
h_items_pos = h_items.get_rect(topright=(WINDOW_SIZE_PX_W, 0))
|
||||
h_items_pos = h_items.get_rect(topright=(WIN_SIZE_W, 0))
|
||||
|
||||
WINDOW.blit(h_title, (0, 0))
|
||||
WINDOW.blit(h_status, (0, CELL_SIZE_PX))
|
||||
WINDOW.blit(h_items, h_items_pos)
|
||||
surface.blit(h_title, (0, 0))
|
||||
surface.blit(h_status, (0, CELL_SIZE))
|
||||
surface.blit(h_items, h_items_pos)
|
||||
|
|
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 874 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 226 B |
After Width: | Height: | Size: 160 B |
19
main.py
|
@ -12,30 +12,28 @@ details
|
|||
"""
|
||||
import pygame
|
||||
from pygame.locals import (
|
||||
K_UP, K_DOWN, K_RIGHT, K_LEFT, KEYDOWN, QUIT, RESIZABLE
|
||||
K_UP, K_DOWN, K_RIGHT, K_LEFT, KEYDOWN, QUIT
|
||||
)
|
||||
from map import Map
|
||||
from conf import BACKGROUND_IMG, CAPTION, MAP_FILE, HEADER_HEIGHT, maze_draw, MSG_END, MSG_QUIT, set_header, WIN_DIM
|
||||
from conf import (
|
||||
BACKGRND_FILE, CAPTION, MAP_FILE, HEAD_SIZE_H, maze_draw,
|
||||
MSG_END, MSG_QUIT, set_header, WIN_DIM
|
||||
)
|
||||
|
||||
# Constant calculation
|
||||
GAME_KEYS = [K_UP, K_DOWN, K_RIGHT, K_LEFT]
|
||||
|
||||
pygame.init()
|
||||
WINDOW = pygame.display.set_mode(WIN_DIM, RESIZABLE)
|
||||
WINDOW = pygame.display.set_mode(WIN_DIM)
|
||||
pygame.display.set_caption(CAPTION)
|
||||
WINDOW.blit(pygame.image.load(BACKGROUND_IMG).convert(), (0, HEADER_HEIGHT))
|
||||
WINDOW.blit(pygame.image.load(BACKGRND_FILE).convert(), (0, HEAD_SIZE_H))
|
||||
|
||||
# Loading map
|
||||
MAP_GAME = Map(MAP_FILE)
|
||||
|
||||
# Header messaging
|
||||
set_header(WINDOW, MAP_GAME.status_message)
|
||||
|
||||
# Draw maze
|
||||
maze_draw(WINDOW, MAP_GAME.map_print().replace('\n', ''))
|
||||
|
||||
pygame.time.Clock().tick(25)
|
||||
# Game loop
|
||||
# pygame.time.Clock().tick(25)
|
||||
last_wait = True
|
||||
while MAP_GAME.status:
|
||||
for event in pygame.event.get():
|
||||
|
@ -59,6 +57,7 @@ MAP_GAME.status_message['title'] = MSG_END
|
|||
set_header(WINDOW, MAP_GAME.status_message)
|
||||
pygame.display.flip()
|
||||
|
||||
# Loop for last messag before exit
|
||||
while last_wait:
|
||||
for event in pygame.event.get():
|
||||
if event.type == KEYDOWN:
|
||||
|
|
123
map.py
|
@ -8,7 +8,10 @@ This file is part of [_ocp3_ project](https://github.com/freezed/ocp3)
|
|||
import os
|
||||
import random
|
||||
from pygame.locals import K_UP, K_DOWN, K_RIGHT, K_LEFT
|
||||
from conf import elmt_val, ERR_MAP, MOVE_STATUS_MSG, HEADER_MESSAGES, MAZE_SIZE_TIL
|
||||
from conf import (
|
||||
elmt_val, ERR_MAP, MSG_COLLECT, MSG_LOSER, MSG_OK,
|
||||
MSG_WALL, MSG_WINNER, HEAD_MESSAGES, MAZE_SIZE
|
||||
)
|
||||
|
||||
|
||||
class Map:
|
||||
|
@ -35,22 +38,24 @@ class Map:
|
|||
:rtype map: str()
|
||||
:return: None
|
||||
"""
|
||||
# Chargement du fichier carte choisi
|
||||
# Loading map file
|
||||
if os.path.isfile(map_file) is True:
|
||||
with open(map_file, "r") as map_data:
|
||||
|
||||
# translate to a splited lines string list
|
||||
# Translate to a splited lines string list
|
||||
map_in_a_list = map_data.read().splitlines()
|
||||
|
||||
# map line number
|
||||
if len(map_in_a_list) == MAZE_SIZE_TIL:
|
||||
self._COLUM = MAZE_SIZE_TIL + 1
|
||||
self._LINES = MAZE_SIZE_TIL
|
||||
# Map line number
|
||||
if len(map_in_a_list) == MAZE_SIZE:
|
||||
self._COLUM = MAZE_SIZE + 1
|
||||
self._LINES = MAZE_SIZE
|
||||
self._MAXIM = (self._COLUM * self._LINES) - 1
|
||||
# Add map checking here
|
||||
|
||||
# ++ Add other map checks here ++
|
||||
|
||||
# Constructing square map
|
||||
map_in_a_list = [self.check_line(line) for line in map_in_a_list]
|
||||
map_in_a_list = [self.check_line(line)
|
||||
for line in map_in_a_list]
|
||||
self._map_in_a_string = '\n'.join(map_in_a_list)
|
||||
|
||||
# Player's initial position
|
||||
|
@ -59,44 +64,54 @@ class Map:
|
|||
)
|
||||
|
||||
# Element under player at start
|
||||
self._element_under_player = elmt_val('symbol', 'name', 'void', 0)
|
||||
self._element_under_player = elmt_val(
|
||||
'symbol', 'name', 'void', 0
|
||||
)
|
||||
|
||||
# Place collectables on the map
|
||||
for symbol_to_place in elmt_val('symbol', 'collect', True):
|
||||
position = random.choice([idx for (idx, value) in enumerate(self._map_in_a_string) if value == elmt_val('symbol', 'name', 'void', 0)])
|
||||
position = random.choice(
|
||||
[idx for (idx, value) in enumerate(
|
||||
self._map_in_a_string
|
||||
) if value == elmt_val(
|
||||
'symbol', 'name', 'void', 0
|
||||
)])
|
||||
self.place_element(symbol_to_place, pos=position)
|
||||
|
||||
self.status = True
|
||||
self.collected_items = []
|
||||
self.collected_items_num = 0
|
||||
self.MAX_ITEMS = sum(1 for _ in elmt_val('name', 'collect', True))
|
||||
self.MAX_ITEMS = sum(
|
||||
1 for _ in elmt_val('name', 'collect', True)
|
||||
)
|
||||
self.status_message = {}
|
||||
self.status_message['title'] = HEADER_MESSAGES['title']
|
||||
self.status_message['status'] = HEADER_MESSAGES['status']
|
||||
self.status_message['items'] = HEADER_MESSAGES['items'].format(self.collected_items_num, self.MAX_ITEMS)
|
||||
self.status_message['title'] = HEAD_MESSAGES['title']
|
||||
self.status_message['status'] = HEAD_MESSAGES['status']
|
||||
self.status_message['items'] \
|
||||
= HEAD_MESSAGES['items'].format(
|
||||
self.collected_items_num, self.MAX_ITEMS
|
||||
)
|
||||
|
||||
else:
|
||||
self.status = False
|
||||
print(ERR_MAP.format("maplines: " + str(len(map_in_a_list))))
|
||||
|
||||
# Erreur de chargement du fichier
|
||||
# File error
|
||||
else:
|
||||
self.status = False
|
||||
print(ERR_MAP.format(':'.join(["mapfile", map_file])))
|
||||
|
||||
def map_print(self):
|
||||
""" Affiche la carte avec la position de jeu courante """
|
||||
""" Return a string of the map state """
|
||||
return self._map_in_a_string
|
||||
|
||||
def move_to(self, pressed_key):
|
||||
"""
|
||||
Deplace le plyr sur la carte
|
||||
Move the player on the map
|
||||
|
||||
:param str pressed_key: mouvement souhaite
|
||||
:return int: une cle de la constante MOVE_STATUS
|
||||
:param str pressed_key: direction (pygame const)
|
||||
"""
|
||||
# supprime le plyr de son emplacement actuel et on replace
|
||||
# l'elements «dessous»
|
||||
# Replace player on the map by the under-element
|
||||
self._map_in_a_string = self._map_in_a_string.replace(
|
||||
elmt_val('symbol', 'name', 'player', 0),
|
||||
self._element_under_player
|
||||
|
@ -115,50 +130,66 @@ class Map:
|
|||
elif pressed_key == K_LEFT:
|
||||
next_position = self._player_position - 1
|
||||
|
||||
# TODO nove instruction to __init__
|
||||
self._element_under_player = elmt_val('symbol', 'name', 'void', 0)
|
||||
|
||||
# Traitement en fonction de la case du prochain pas
|
||||
# Next position treatment
|
||||
if next_position >= 0 and next_position <= self._MAXIM:
|
||||
next_char = self._map_in_a_string[next_position]
|
||||
|
||||
if next_char == elmt_val('symbol', 'name', 'void', 0):
|
||||
self._player_position = next_position
|
||||
self.status_message['status'] = MOVE_STATUS_MSG['ok']
|
||||
self.status_message['status'] = MSG_OK
|
||||
|
||||
elif next_char in elmt_val('symbol', 'collect', True):
|
||||
self._player_position = next_position
|
||||
self._element_under_player = elmt_val('symbol', 'name', 'void', 0)
|
||||
self.collected_items.append(elmt_val('name', 'symbol', next_char, 0))
|
||||
self._element_under_player = elmt_val(
|
||||
'symbol', 'name', 'void', 0
|
||||
)
|
||||
self.collected_items.append(
|
||||
elmt_val('name', 'symbol', next_char, 0)
|
||||
)
|
||||
self.collected_items_num += 1
|
||||
self.status_message['status'] = MOVE_STATUS_MSG['collect'].format(elmt_val('name', 'symbol', next_char, 0))
|
||||
self.status_message['items'] = HEADER_MESSAGES['items'].format(self.collected_items_num, self.MAX_ITEMS)
|
||||
self.status_message['status'] = MSG_COLLECT.format(
|
||||
elmt_val('name', 'symbol', next_char, 0)
|
||||
)
|
||||
self.status_message['items'] \
|
||||
= HEAD_MESSAGES['items'].format(
|
||||
self.collected_items_num, self.MAX_ITEMS
|
||||
)
|
||||
|
||||
elif next_char == elmt_val('symbol', 'name', 'exit', 0):
|
||||
self.status = False
|
||||
if sorted(self.collected_items) == sorted(elmt_val('name', 'collect', True)):
|
||||
self.status_message['status'] = MOVE_STATUS_MSG['winner']
|
||||
if sorted(self.collected_items) == sorted(
|
||||
elmt_val('name', 'collect', True)
|
||||
):
|
||||
self.status_message['status'] = MSG_WINNER
|
||||
else:
|
||||
missed_item_flist = ', '.join((item for item in elmt_val('name', 'collect', True) if item not in self.collected_items))
|
||||
self.status_message['status'] = MOVE_STATUS_MSG['looser'].format(missed_item_flist)
|
||||
missed_item_flist = ', '.join(
|
||||
(item for item in elmt_val(
|
||||
'name', 'collect', True
|
||||
) if item not in self.collected_items)
|
||||
)
|
||||
self.status_message['status'] = MSG_LOSER.format(
|
||||
missed_item_flist
|
||||
)
|
||||
|
||||
else: # wall, door or nline
|
||||
self.status_message['status'] = MOVE_STATUS_MSG['wall']
|
||||
else: # wall or nline
|
||||
self.status_message['status'] = MSG_WALL
|
||||
else:
|
||||
self.status_message['status'] = MOVE_STATUS_MSG['wall']
|
||||
self.status_message['status'] = MSG_WALL
|
||||
|
||||
# place le plyr sur sa nouvelle position
|
||||
# Set the player on position
|
||||
self.place_element(elmt_val('symbol', 'name', 'player', 0))
|
||||
|
||||
def place_element(self, element, **kwargs):
|
||||
"""
|
||||
Place l'element sur la carte.
|
||||
Set an element on the map
|
||||
|
||||
La position est celle de l'attribut self._player_position au
|
||||
moment de l'appel.
|
||||
The position used is in ._player_position attribute
|
||||
Used for player and void after collecting items
|
||||
|
||||
Utilise pour place le plyrt et remettre les portes.
|
||||
|
||||
:param str element: element a placer sur la carte
|
||||
:param str element: the string of the element to place
|
||||
"""
|
||||
# FIXME cannot find a way to define default value to the
|
||||
# method's arguments with class attributes
|
||||
|
@ -177,12 +208,12 @@ class Map:
|
|||
@staticmethod
|
||||
def check_line(line):
|
||||
"""
|
||||
Checks if a line has a good length, fill it if it's too small,
|
||||
truncate if it's too long
|
||||
Checks if a line has a good length (configured in MAZE_SIZE const).
|
||||
Fill it if it's too small, truncate if it's too long.
|
||||
"""
|
||||
differance = MAZE_SIZE_TIL - len(str(line))
|
||||
differance = MAZE_SIZE - len(str(line))
|
||||
if differance < 0:
|
||||
return line[:MAZE_SIZE_TIL]
|
||||
return line[:MAZE_SIZE]
|
||||
elif differance > 0:
|
||||
return line + (differance * elmt_val('symbol', 'name', 'void', 0))
|
||||
else:
|
||||
|
|