ini commit
This commit is contained in:
commit
a19d8a5cda
4 changed files with 205 additions and 0 deletions
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# PYSOKOBAN
|
174
main.py
Normal file
174
main.py
Normal file
|
@ -0,0 +1,174 @@
|
|||
import os
|
||||
|
||||
from pynput import keyboard
|
||||
|
||||
from maps import levels, logo
|
||||
|
||||
# TODO: reset option with point loss
|
||||
# TODO: actually give points
|
||||
# TODO: only allow 3 resets then gameover
|
||||
# TODO: win + loss screens (just simple text under map or something)
|
||||
# TODO: ^^ maybe cute emojis for win and loss screens
|
||||
# TODO: Create more maps
|
||||
|
||||
STATS = {
|
||||
'lives': 3,
|
||||
'points': 0,
|
||||
'total_moves': 0,
|
||||
'level_moves': {}
|
||||
}
|
||||
|
||||
|
||||
class Map:
|
||||
def __init__(self, level=1):
|
||||
self.level = level
|
||||
self.level_map = levels[self.level - 1]
|
||||
self.map_array = []
|
||||
self.storage_locations = []
|
||||
|
||||
self.listener = None
|
||||
|
||||
self.player_x = None
|
||||
self.player_y = None
|
||||
self.previous_element = ' '
|
||||
|
||||
self.win = False
|
||||
self.break_condition = True
|
||||
|
||||
def generate_map_array(self):
|
||||
STATS['level_moves'][self.level] = 0
|
||||
|
||||
level_array = self.level_map.split('\n')
|
||||
|
||||
for idx, line in enumerate(level_array):
|
||||
if idx == 0 or idx == len(level_array) - 1:
|
||||
continue
|
||||
|
||||
row_elements = list(line)
|
||||
|
||||
if '@' in row_elements:
|
||||
self.player_y = idx - 1
|
||||
self.player_x = row_elements.index('@')
|
||||
|
||||
if '.' in row_elements:
|
||||
for xidx, element in enumerate(row_elements):
|
||||
if element == '.':
|
||||
self.storage_locations.append((idx-1, xidx))
|
||||
|
||||
self.map_array.append(row_elements)
|
||||
|
||||
def display(self):
|
||||
os.system('clear')
|
||||
for storage_location in self.storage_locations:
|
||||
if self.map_array[storage_location[0]][storage_location[1]] == ' ':
|
||||
self.map_array[storage_location[0]][storage_location[1]] = '.'
|
||||
print(logo)
|
||||
print(f' lvl: {self.level} | mvs: {STATS["level_moves"][self.level]} | pts: {STATS["points"]}')
|
||||
for row in self.map_array:
|
||||
print('\t', ''.join(row))
|
||||
|
||||
if self.win:
|
||||
print('\n\n NICE! Press [w] to continue!')
|
||||
else:
|
||||
print('\n\n h = ← | j = ↓ | k = ↑ | l = →')
|
||||
|
||||
def on_release(self, key):
|
||||
self.listener = None
|
||||
if 'char' in dir(key):
|
||||
if key.char == 'h':
|
||||
self.move('left')
|
||||
if key.char == 'l':
|
||||
self.move('right')
|
||||
if key.char == 'j':
|
||||
self.move('down')
|
||||
if key.char == 'k':
|
||||
self.move('up')
|
||||
if self.win:
|
||||
if key.char == 'w':
|
||||
self.break_condition = False
|
||||
|
||||
return False
|
||||
|
||||
def wait_for_input(self):
|
||||
with keyboard.Listener(on_release=self.on_release) as self.listener:
|
||||
self.listener.join()
|
||||
|
||||
def move(self, direction):
|
||||
STATS['level_moves'][self.level] += 1
|
||||
STATS['total_moves'] += 1
|
||||
|
||||
tmp_player_x = self.player_x
|
||||
tmp_player_y = self.player_y
|
||||
|
||||
if direction == 'right' or direction == 'left':
|
||||
|
||||
if direction == 'right':
|
||||
tmp_player_x += 1
|
||||
else:
|
||||
tmp_player_x -= 1
|
||||
|
||||
if direction == 'up' or direction == 'down':
|
||||
if direction == 'down':
|
||||
tmp_player_y += 1
|
||||
else:
|
||||
tmp_player_y -= 1
|
||||
|
||||
future_position = self.map_array[tmp_player_y][tmp_player_x]
|
||||
|
||||
if future_position not in ['#']:
|
||||
can_move = True
|
||||
if future_position == '0':
|
||||
future_position = ' '
|
||||
can_move = self.push_boulder(tmp_player_y, tmp_player_x, direction)
|
||||
|
||||
if can_move:
|
||||
self.map_array[self.player_y][self.player_x] = self.previous_element
|
||||
self.previous_element = future_position
|
||||
self.map_array[tmp_player_y][tmp_player_x] = '@'
|
||||
self.player_x = tmp_player_x
|
||||
self.player_y = tmp_player_y
|
||||
|
||||
def push_boulder(self, tmp_player_y, tmp_player_x, direction):
|
||||
tmp_boulder_x = tmp_player_x
|
||||
tmp_boulder_y = tmp_player_y
|
||||
|
||||
if direction == 'right' or direction == 'left':
|
||||
|
||||
if direction == 'right':
|
||||
tmp_boulder_x += 1
|
||||
else:
|
||||
tmp_boulder_x -= 1
|
||||
|
||||
if direction == 'up' or direction == 'down':
|
||||
if direction == 'down':
|
||||
tmp_boulder_y += 1
|
||||
else:
|
||||
tmp_boulder_y -= 1
|
||||
|
||||
future_position = self.map_array[tmp_boulder_y][tmp_boulder_x]
|
||||
|
||||
if future_position not in ['#', '0']:
|
||||
self.map_array[tmp_boulder_y][tmp_boulder_x] = '0'
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_win_condition(self):
|
||||
self.win = True
|
||||
for yidx, line in enumerate(self.map_array):
|
||||
for xidx, element in enumerate(line):
|
||||
if element == '0':
|
||||
if (yidx, xidx) not in self.storage_locations:
|
||||
self.win = False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for level in range(len(levels)):
|
||||
m = Map(level + 1)
|
||||
m.generate_map_array()
|
||||
while m.break_condition:
|
||||
m.display()
|
||||
m.wait_for_input()
|
||||
m.check_win_condition()
|
||||
|
||||
os.system('clear')
|
26
maps.py
Normal file
26
maps.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
logo = '''
|
||||
█▀█ █▄█ █▀ █▀█ █▄▀ █▀█ █▄▄ ▄▀█ █▄░█
|
||||
█▀▀ ░█░ ▄█ █▄█ █░█ █▄█ █▄█ █▀█ █░▀█
|
||||
'''
|
||||
|
||||
level_1 = '''
|
||||
#############
|
||||
# #
|
||||
#@ 0 . #
|
||||
# #
|
||||
#############
|
||||
'''
|
||||
|
||||
level_2 = '''
|
||||
#############
|
||||
#. #
|
||||
#@ 00 . #
|
||||
# #
|
||||
#############
|
||||
'''
|
||||
|
||||
levels = [
|
||||
level_1,
|
||||
level_2
|
||||
]
|
||||
|
4
requirements.txt
Normal file
4
requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
evdev==1.9.2
|
||||
pynput==1.8.1
|
||||
python-xlib==0.33
|
||||
six==1.17.0
|
Loading…
Reference in a new issue