I am currently working on 2D game which is using text as a textures in python. The main idea for this game is to collect the treasure and try to escape the ghost aka monster. After lots of struggle I finally added movement system for player and monster. Everything is working like it should as coordinates are changing properly (function info() will show them), however my map does not update and i have no idea how can i update it.
Map is 12x12
#map generation
map_width = 12
map_height = 12
player_view = 1
map = [([1] * map_width)] + ([([1] + ([0] * (map_width - 2)) + [1]) for _ in range(map_height - 2)]) + [([1] * map_width)]
def print_map():
for row in map:
print(*row, sep='\t')
print("\n")
Generation of “objects” like player, monster and treasure. During the player generation there will be generation of the vision along.
#player generation + vision
player = {
"x_p":random.randint(1,map_width - 2),
"y_p":random.randint(1,map_height - 2),
}
map[player["y_p"]][player["x_p"]] = ‘😑’
for i,row in enumerate(map[player["y_p"]- player_view :player["y_p"]+1 + player_view]):
for j,element in enumerate(row[player["x_p"]- player_view :player["x_p"]+1 + player_view]):
if (element == 0):
map[player["y_p"] - player_view + i][player["x_p"] - player_view +j]='🕯'
#monster generation
monster = {
'y_m':random.randint(1, map_width - 2),
}
possible_x = []
for i,e in enumerate(map[monster['y_m']]):
if e == 0:
possible_x.append(i)
monster['x_m'] = random.choice(possible_x)
map[monster["y_m"]][monster["x_m"]]='👻'
#treasure generation
treasure = {
'y_t':random.randint(1, map_width - 2),
}
possible_x = []
for i,e in enumerate(map[treasure['y_t']]):
if e == 0:
possible_x.append(i)
treasure['x_t'] = random.choice(possible_x)
map[treasure["y_t"]][treasure["x_t"]]='💰'
All of the functions which are used in program
#printing info about characters, map dimensions and icons used
def info():
print('\n')
#print_map()
#print('\n')
print('Map dimentions are',map_width, 'x', map_height, '(including walls!)\n')
print('Player -',player, 'Icon used:',player_character, '\n')
print('Monster -',monster, 'Icon used: 👻.\n')
print('Treasure -',treasure, 'Icon used: 💰.\n')
print('Player vision value is', player_view,', and is represented with icon: 🕯.\n')
print('Other icons used, 0 as empty area and 1 as walls. \n')
#generating number 1 or -1 randomly in order to select direction of monster movement
def monster_random_values():
exclude = [0]
movement_value = random.randint(-1,1)
return my_custom_random() if movement_value in exclude else movement_value
And finally the movement system for player and monster
loop = True
while loop:
# movment system
movment_choice = input('Please select your movment choice - [W,A,S,D]\nIf you want to exit press [Q]\n')
if movment_choice == 'W' or movment_choice == 'w':
print_map()
player['y_p'] = (player['y_p'] + 1)
#print(map[player['y_p']])
info()
elif movment_choice == 'A' or movment_choice == 'a':
player['x_p'] = (player['x_p'] - 1)
#print(map[player['x_p']])
info()
elif movment_choice == 'S' or movment_choice == 's':
player['y_p'] = (player['y_p'] - 1)
#print(map[player['y_p']])
info()
elif movment_choice == 'D' or movment_choice == 'd':
player['x_p'] = (player['x_p'] + 1)
#print(player['x_p'])
info()
elif movment_choice == 'Q':
print('Thank you for playing the game!\n See you soon!')
loop = False
else:
print('ERROR! Please select one of the options in the question')
#monster movment
possible_movment = random.randint(1, 3)
if possible_movment == 1:
monster['y_m'] = (monster['y_m'] + monster_random_values())
monster['x_m'] = (monster['x_m'] + monster_random_values())
elif possible_movment == 2:
monster['y_m'] = (monster['y_m'] + monster_random_values())
elif possible_movment == 3:
monster['x_m'] = (monster['x_m'] + monster_random_values())
info()
I hope that it is clear. If it will not work properly i will sent a full version of a code.
Thank you for help!
First, map
is a python builtin. It is advised not to use it as a variable name.
Second, I'd make the map creation a function and use the object returned by it.
Here's a sample code using set
and procedural generation of the game map. Using operations of sets we will keep them from overlapping objects in the map. I will be using a tuple
for positions.
import random
BORDER = '1'
def create_map(map_width, map_height, num_treasures=1):
locations = set((i, j) for i in range(map_height) for j in range(map_width)) # All available board coordinates
player = (random.randint(1, map_width - 2), random.randint(1, map_height - 2)) # Player position
locations = locations.difference({player}) # Remove player position from available positions
border = ({(0, i) for i in range(map_width)}.union({(map_height - 1, i) for i in range(map_width)})).union(
{(i, 0) for i in range(map_height)}.union({(i, map_height - 1) for i in range(map_height)})) # All borders
locations = locations.difference(border) # Remove border from available locations
vision = {(player[0] + dx, player[1] + dy) for dx in [-1, 0, 1] for dy in [-1, 0, 1]}.intersection(
locations) # 3 x 3 vision box. Player is not used since its location is not available in locations
monster = random.choice(list(locations)) # Monster location selected randomly from available locations
locations = locations.difference({monster}) # Remove monster from available locations
treasures = set([]) # Do the same thing as monster with treasures in a loop
for i in range(num_treasures):
treasure = random.choice(list(locations))
treasures.add(treasure)
locations.remove(treasure)
my_map = list(list([0] * map_width) for _ in range(map_height)) # Empty map
my_map[player[0]][player[1]] = '😑' # Set player
my_map[monster[0]][monster[1]] = '👻' # Set monster
for x, y in border: # Set border
my_map[x][y] = BORDER
for x, y in vision: # Set vision
my_map[x][y] = '🕯'
for x, y in treasures: # Set treasures
my_map[x][y] = '💰'
return my_map, player, monster, treasures
Lastly, I don't see any updates happening in the game while
loop. You can do this using another function.
def move(my_map, player, player_move):
# Legal move inputs
if player_move in ['a', 'A']:
player_move = (0, -1)
vision_remove = [(-1, 1), (0, 1), (1, 1)]
elif player_move in ['w', 'W']:
player_move = (-1, 0)
vision_remove = [(1, -1), (1, 0), (1, 1)]
elif player_move in ['d', 'D']:
player_move = (0, 1)
vision_remove = [(-1, -1), (0, -1), (1, -1)]
elif player_move in ['s', 'S']:
player_move = (1, 0)
vision_remove = [(-1, -1), (-1, 0), (-1, 1)]
else:
return False, my_map, player
neighbors = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
# New position
x = player[0] + player_move[0]
y = player[1] + player_move[1]
if my_map[x][y] != BORDER: # Can't move into borders
my_map[player[0]][player[1]] = 0
my_map[x][y] = '😑'
# Update vision while keeping treasure, ghost, border icons
for dx, dy in vision_remove: # Remove old vision
value = my_map[player[0] + dx][player[1] + dy]
my_map[player[0] + dx][player[1] + dy] = 0 if value == '🕯' else value
for dx, dy in neighbors: # Add new vision
value = my_map[x + dx][y + dy]
my_map[x + dx][y + dy] = '🕯' if value == 0 else value
return True, my_map, (x, y)
return False, my_map, player
Some of the helper functions:
def to_string(my_map):
return '\n'.join('\t'.join(str(x) for x in y) for y in my_map)
def print_map(my_map):
print(to_string(my_map))
The move function doesn't detect picking up treasure, walking into ghosts as it is. Those need to be added.
The main loop would look something like this:
my_map, player, monster, treasures = create_map(12, 12, 3)
updated = True
while True:
# movement system
if updated:
updated = False
print_map(my_map)
movement_choice = input('Please select your movment choice - [W,A,S,D]\nIf you want to exit press [Q]\n')
if movement_choice in ['q', 'Q']:
print('Thank you for playing the game!\n See you soon!')
break
if movement_choice not in ['w', 'W', 'a', 'A', 's', 'S', 'd', 'D']:
print('ERROR! Please select one of the options in the question')
updated, my_map, player = move(my_map, player, movement_choice)
hit, my_map, monster = move_monster(my_map, monster)
if hit:
print('Oh no! The monster got you.')
print_map(my_map)
break
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.