Difference between revisions of "Complete Roguelike Tutorial, using python3+libtcod, part 2 code"
Jump to navigation
Jump to search
Line 281: | Line 281: | ||
<div style="background-color: #EEEEEE; border-style: dotted"><syntaxhighlight lang="python"> | <div style="background-color: #EEEEEE; border-style: dotted"><syntaxhighlight lang="python"> | ||
import | #!/usr/bin/env python | ||
import os | |||
import libtcodpy as tcod | |||
# ###################################################################### | |||
# Game Constants | |||
# ###################################################################### | |||
# Size of the terminal window in characters | |||
SCREEN_WIDTH = 80 # characters wide | |||
SCREEN_HEIGHT = 50 # characters tall | |||
# Size of the map floor (this should fit within the screen width/height) | |||
FLOOR_WIDTH = 80 # characters wide | |||
FLOOR_HEIGHT = 45 # characters tall | |||
LIMIT_FPS = 20 # 20 frames-per-second maximum | |||
REALTIME = False # set True for real-time, False for turn-based | |||
# ###################################################################### | |||
# Exceptions | |||
# ###################################################################### | |||
class GameError(Exception): | |||
"""Base Exception for all game errors""" | |||
class | |||
#this is | class FontError(GameError): | ||
"""Font could not be loaded""" | |||
def __init__(self, x, y | |||
class PositionError(GameError): | |||
"""Position not available""" | |||
# ###################################################################### | |||
# Classes | |||
# ###################################################################### | |||
class Direction(object): | |||
"""Defines direction of movement | |||
Matrix: | |||
-1, -1 | 0, -1 | 1, -1 | |||
-1, 0 | 0, 0 | 1, 0 | |||
-1, 1 | 0, 1 | 1, 1 | |||
| UP | | |||
LEFT | NONE | RIGHT | |||
| DOWN | | |||
NW | NORTH | NE | |||
WEST | NONE | EAST | |||
SW | SOUTH | SE | |||
""" | |||
NONE = (0, 0) | |||
UP = (0, -1) | |||
DOWN = (0, 1) | |||
LEFT = (-1, 0) | |||
RIGHT = (1, 0) | |||
NORTH = UP | |||
NE = (1, -1) | |||
EAST = RIGHT | |||
SE = (1, 1) | |||
SOUTH = DOWN | |||
SW = (-1, 1) | |||
WEST = LEFT | |||
NW = (-1, -1) | |||
class Map(object): | |||
"""A representation of the dungeon map. | |||
Adds extra functionality for iterating over the map and accessing | |||
individual map cells. | |||
Args: | |||
width (int, optional): the width of the floor [default: FLOOR_WIDTH] | |||
height (int, optional): the height of the floor [default: FLOOR_HEIGHT] | |||
""" | |||
def block(self, position): | |||
"""Blocks a position on the map | |||
Args: | |||
position (Position, tuple): the location to block | |||
""" | |||
map_cell = self.__getitem__(position) | |||
map_cell.block() | |||
def unblock(self, position): | |||
"""Unblocks a position on the map | |||
Args: | |||
position (Position, tuple): the location to unblock | |||
""" | |||
map_cell = self.__getitem__(position) | |||
map_cell.unblock() | |||
def __init__(self, width=None, height=None): | |||
self.width = width or FLOOR_WIDTH | |||
self.height = height or FLOOR_HEIGHT | |||
# initialize map | |||
self.map = {} | |||
for y in range(self.height): | |||
for x in range(self.width): | |||
pos = Position(x, y) | |||
cell = MapCell() | |||
self.map[pos] = cell | |||
def __iter__(self): | |||
for y in range(self.height): | |||
for x in range(self.width): | |||
yield x, y, self.__getitem__((x, y)) | |||
def __getitem__(self, key): | |||
value = None | |||
if isinstance(key, Position): | |||
value = self.map[key] | |||
elif isinstance(key, (list, tuple)): | |||
key = Position(*key) | |||
value = self.map[key] | |||
else: | |||
raise PositionError('Invalid position: {}'.format(key)) | |||
return value | |||
class MapCell(object): | |||
"""A representation of a map cell which contains metadata information | |||
related to this specific cell within the map | |||
Args: | |||
blocked (bool, optional): blocks movement [default: False] | |||
block_sight (bool, optional): blocks visual [default: False] | |||
""" | |||
def __init__(self, blocked=None, block_sight=None): | |||
self.blocked = blocked or False | |||
self.block_sight = block_sight or blocked or False | |||
def block(self): | |||
self.blocked = True | |||
self.block_sight = True | |||
def unblock(self): | |||
self.blocked = False | |||
self.block_sight = False | |||
class Object(object): | |||
"""Game object. This is used for any displayable game object such | |||
as the player, a mob, an item, a staircase, etc. | |||
Args: | |||
character (str): the character to display | |||
position (Position): (x, y) the position of the object on the map | |||
color (tcod.Color, optional): (R, G, B) color to use when drawing [default: tcod.white] | |||
""" | |||
def __init__(self, character, position, color=tcod.white): | |||
self.character = character | |||
self.position = position | |||
self.color = color | |||
def clear(self): | |||
"""Erase the character from the console""" | |||
self.draw(' ') | |||
def draw(self, character=None): | |||
"""Controls how the object is displayed on the screen. | |||
Args: | |||
character (str, optional): the character to display [default: self.character] | |||
""" | |||
global con | |||
character = character or self.character | |||
tcod.console_set_default_foreground(con, self.color) | |||
x, y = self.position | |||
tcod.console_put_char(con, x, y, character, tcod.BKGND_NONE) | |||
def move(self, direction): | |||
"""Moves the object in a specific direction. | |||
Modifies the object position. | |||
Args: | |||
direction (Direction, tuple): UP, DOWN, LEFT, RIGHT | |||
""" | |||
self.position += direction | |||
class Position(object): | |||
"""A class to help with position-related math in 2d space | |||
Args: | |||
x (int): the width coordinate value | |||
y (int): the height coordinate value | |||
""" | |||
def __init__(self, x, y): | |||
self.x = x | self.x = x | ||
self.y = y | self.y = y | ||
self. | |||
self. | def __eq__(self, other): | ||
equal = False | |||
def | if isinstance(other, Position): | ||
if self.x == other.x and self.y == other.y: | |||
equal = True | |||
elif isinstance(other, (tuple, list)): | |||
if len(self) == len(other): | |||
if self.x == other[0] and self.y == other[1]: | |||
equal = True | |||
return equal | |||
def __hash__(self): | |||
return hash((self.x, self.y)) | |||
def __iter__(self): | |||
yield self.x | |||
yield self.y | |||
def __len__(self): | |||
return len((self.x, self.y)) | |||
def __add__(self, other): | |||
if isinstance(other, Direction): | |||
dx, dy = other | |||
self.x += dx | self.x += dx | ||
self.y += dy | self.y += dy | ||
elif isinstance(other, (list, tuple)): | |||
def | dx, dy = other | ||
# | if len(other) == len(self): | ||
self.x += dx | |||
self.y += dy | |||
return self | |||
def __repr__(self): | |||
return f'<Position ({self.x}, {self.y})>' | |||
def __str__(self): | |||
return f'({self.x}, {self.y})' | |||
# ###################################################################### | |||
# User Interface Control | |||
# ###################################################################### | |||
def handle_keys(): | |||
"""Handles keyboard input | |||
Updates: | |||
player_x: x coordinate of player position | |||
player_y: y coordinate of player position | |||
Returns: | |||
bool: True if exit the game is requested else False | |||
""" | |||
global player | |||
exit_game = False | |||
# Run with REALTIME or turn-based | |||
if REALTIME: | |||
key = tcod.console_check_for_keypress() | |||
else: | |||
key = tcod.console_wait_for_keypress(True) | |||
if key.vk == tcod.KEY_ENTER and key.lalt: | |||
# Alt+Enter: toggle fullscreen | |||
tcod.console_set_fullscreen(not tcod.console_is_fullscreen()) | |||
elif key.vk == tcod.KEY_ESCAPE: | |||
exit_game = True # exit game | |||
# movement keys | |||
if tcod.console_is_key_pressed(tcod.KEY_UP): | |||
player.move(Direction.UP) | |||
elif tcod.console_is_key_pressed(tcod.KEY_DOWN): | |||
player.move(Direction.DOWN) | |||
elif tcod.console_is_key_pressed(tcod.KEY_LEFT): | |||
player.move(Direction.LEFT) | |||
elif tcod.console_is_key_pressed(tcod.KEY_RIGHT): | |||
player.move(Direction.RIGHT) | |||
return exit_game | |||
# ###################################################################### | |||
# Game | |||
# ###################################################################### | |||
def initialize_game(font_filepath=None, window_title=None, fullscreen=False): | |||
"""Sets up libtcod and creates a window | |||
Updates: | |||
colors: a dictionary of colors used | |||
con: the tcod console | |||
npc: the npc game object | |||
game_objects: a list of game objects | |||
player: the player game object | |||
Args: | |||
font_filepath (str): the path to the font file [default: terminal.png] | |||
window_title (str): the title to display for the game [default: Python3 Tutorial] | |||
""" | |||
global colors, con, game_objects, npc, player | |||
# Setup displayed font | |||
font_filepath = os.path.abspath(font_filepath or 'terminal.png') | |||
font_flags = tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_ASCII_INCOL | |||
if not os.path.exists(font_filepath): | |||
raise FontError("Could not open font file: {}".format(font_filepath)) | |||
tcod.console_set_custom_font(font_filepath, font_flags) | |||
# Setup window | |||
window_title = window_title or 'Python3 Tutorial' | |||
fullscreen = fullscreen or False | |||
tcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, window_title, fullscreen) | |||
# Limit frames per second | |||
tcod.sys_set_fps(LIMIT_FPS) | |||
# Create the console | |||
con = tcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT) | |||
# Setup player's initial position | |||
player_starting_position = Position(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) | |||
player = Object('@', player_starting_position) | |||
npc_starting_position = Position(SCREEN_WIDTH // 2 - 5, SCREEN_HEIGHT // 2) | |||
npc = Object('@', npc_starting_position, color=tcod.yellow) | |||
game_objects = [npc, player] | |||
# Setup some colors | |||
colors = { | |||
'white': tcod.white, | |||
'yellow': tcod.yellow, | |||
'dark wall': tcod.Color(0, 0, 100), | |||
'dark ground': tcod.Color(50, 50, 150), | |||
} | |||
# Create the map | |||
make_map() | |||
def make_map(): | def make_map(): | ||
global map | """Creates the global map | ||
# | Updates: | ||
level: the global map | |||
""" | |||
# This is a "level" rather than a "map" because python has a "map" | |||
# function built-in and we might want to use that function later. | |||
# | global level | ||
level = Map() | |||
# Create some pillars / blocked locations | |||
locations = [ | |||
(30, 22), | |||
(50, 22), | |||
] | |||
for location in locations: | |||
level.block(location) | |||
def render_all(): | def render_all(): | ||
"""Draws map and game objects. | |||
global | |||
Accesses: | |||
colors: dictionary of colors | |||
con: the game console | |||
game_objects: npcs, mobs, player, items, etc. | |||
level: the global map | |||
""" | |||
global colors, level, con, game_objects | |||
wall = colors.get('dark wall') | |||
ground = colors.get('dark ground') | |||
for x, y, cell in level: | |||
if cell.block_sight: | |||
tcod.console_set_char_background(con, x, y, wall, tcod.BKGND_SET) | |||
else: | |||
tcod.console_set_char_background(con, x, y, ground, tcod.BKGND_SET) | |||
for game_object in game_objects: | |||
game_object.draw() | |||
tcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0) | |||
def main(): | |||
global game_objects | |||
initialize_game() | |||
# Game loop | |||
exit_game = False | |||
while not tcod.console_is_window_closed() and exit_game is not True: | |||
render_all() | |||
tcod.console_flush() | |||
for game_object in game_objects: | |||
game_object.clear() | |||
# | # handle keys | ||
exit_game = handle_keys() | |||
if __name__ == '__main__': | |||
main() | |||
</syntaxhighlight></div> | </syntaxhighlight></div> | ||
[[Category:Developing]] | [[Category:Developing]] |
Revision as of 22:15, 15 September 2017
This is part of a series of tutorials; the main page can be found here. |
Generalizing
#!/usr/bin/env python
import os
import libtcodpy as tcod
# ######################################################################
# Game Constants
# ######################################################################
# Size of the terminal window in characters
SCREEN_WIDTH = 80 # characters wide
SCREEN_HEIGHT = 50 # characters tall
LIMIT_FPS = 20 # 20 frames-per-second maximum
REALTIME = False # set True for real-time, False for turn-based
# ######################################################################
# Exceptions
# ######################################################################
class GameError(Exception):
"""Base Exception for all game errors"""
class FontError(GameError):
"""Font could not be loaded"""
# ######################################################################
# Classes
# ######################################################################
class Direction(object):
"""Defines direction of movement
Matrix:
-1, -1 | 0, -1 | 1, -1
-1, 0 | 0, 0 | 1, 0
-1, 1 | 0, 1 | 1, 1
| UP |
LEFT | NONE | RIGHT
| DOWN |
NW | NORTH | NE
WEST | NONE | EAST
SW | SOUTH | SE
"""
NONE = (0, 0)
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)
NORTH = UP
NE = (1, -1)
EAST = RIGHT
SE = (1, 1)
SOUTH = DOWN
SW = (-1, 1)
WEST = LEFT
NW = (-1, -1)
class Object(object):
"""Game object. This is used for any displayable game object such
as the player, a mob, an item, a staircase, etc.
Args:
character (str): the character to display
position (Position): (x, y) the position of the object on the map
color (tcod.Color, optional): (R, G, B) color to use when drawing [default: tcod.white]
"""
def __init__(self, character, position, color=tcod.white):
self.character = character
self.position = position
self.color = color
def clear(self):
"""Erase the character from the console"""
self.draw(' ')
def draw(self, character=None):
"""Controls how the object is displayed on the screen.
Args:
character (str, optional): the character to display [default: self.character]
"""
global con
character = character or self.character
tcod.console_set_default_foreground(con, self.color)
x, y = self.position
tcod.console_put_char(con, x, y, character, tcod.BKGND_NONE)
def move(self, direction):
"""Moves the object in a specific direction.
Modifies the object position.
Args:
direction (Direction, tuple): UP, DOWN, LEFT, RIGHT
"""
self.position += direction
class Position(object):
"""A class to help with position-related math in 2d space
Args:
x (int): the width coordinate value
y (int): the height coordinate value
"""
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
equal = False
if isinstance(other, Position):
if self.x == other.x and self.y == other.y:
equal = True
elif isinstance(other, (tuple, list)):
if len(self) == len(other):
if self.x == other[0] and self.y == other[1]:
equal = True
return equal
def __hash__(self):
return hash((self.x, self.y))
def __iter__(self):
yield self.x
yield self.y
def __len__(self):
return len((self.x, self.y))
def __add__(self, other):
if isinstance(other, Direction):
dx, dy = other
self.x += dx
self.y += dy
elif isinstance(other, (list, tuple)):
dx, dy = other
if len(other) == len(self):
self.x += dx
self.y += dy
return self
def __repr__(self):
return f'<Position ({self.x}, {self.y})>'
def __str__(self):
return f'({self.x}, {self.y})'
# ######################################################################
# User Interface Control
# ######################################################################
def handle_keys():
"""Handles keyboard input
Updates:
player_x: x coordinate of player position
player_y: y coordinate of player position
Returns:
bool: True if exit the game is requested else False
"""
global player
exit_game = False
# Run with REALTIME or turn-based
if REALTIME:
key = tcod.console_check_for_keypress()
else:
key = tcod.console_wait_for_keypress(True)
if key.vk == tcod.KEY_ENTER and key.lalt:
# Alt+Enter: toggle fullscreen
tcod.console_set_fullscreen(not tcod.console_is_fullscreen())
elif key.vk == tcod.KEY_ESCAPE:
exit_game = True # exit game
# movement keys
if tcod.console_is_key_pressed(tcod.KEY_UP):
player.move(Direction.UP)
elif tcod.console_is_key_pressed(tcod.KEY_DOWN):
player.move(Direction.DOWN)
elif tcod.console_is_key_pressed(tcod.KEY_LEFT):
player.move(Direction.LEFT)
elif tcod.console_is_key_pressed(tcod.KEY_RIGHT):
player.move(Direction.RIGHT)
return exit_game
# ######################################################################
# Game
# ######################################################################
def initialize_game(font_filepath=None, window_title=None, fullscreen=False):
"""Sets up libtcod and creates a window
Updates:
player_x: x coordinate of player position
player_y: y coordinate of player position
Args:
font_filepath (str): the path to the font file [default: terminal.png]
window_title (str): the title to display for the game [default: Python3 Tutorial]
"""
global player, con, npc
# Setup displayed font
font_filepath = os.path.abspath(font_filepath or 'terminal.png')
font_flags = tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_ASCII_INCOL
if not os.path.exists(font_filepath):
raise FontError("Could not open font file: {}".format(font_filepath))
tcod.console_set_custom_font(font_filepath, font_flags)
# Setup window
window_title = window_title or 'Python3 Tutorial'
fullscreen = fullscreen or False
tcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, window_title, fullscreen)
# Limit frames per second
tcod.sys_set_fps(LIMIT_FPS)
# Create the console
con = tcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
# Setup player's initial position
player_starting_position = Position(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
player = Object('@', player_starting_position)
npc_starting_position = Position(SCREEN_WIDTH // 2 - 5, SCREEN_HEIGHT // 2)
npc = Object('@', npc_starting_position, color=tcod.yellow)
def main():
global player, npc
initialize_game()
objects = [npc, player]
# Game loop
exit_game = False
while not tcod.console_is_window_closed() and exit_game is not True:
tcod.console_set_default_foreground(0, tcod.white)
for game_object in objects:
game_object.draw()
tcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
tcod.console_flush()
for game_object in objects:
game_object.clear()
# handle keys
exit_game = handle_keys()
if __name__ == '__main__':
main()
The Map
#!/usr/bin/env python
import os
import libtcodpy as tcod
# ######################################################################
# Game Constants
# ######################################################################
# Size of the terminal window in characters
SCREEN_WIDTH = 80 # characters wide
SCREEN_HEIGHT = 50 # characters tall
# Size of the map floor (this should fit within the screen width/height)
FLOOR_WIDTH = 80 # characters wide
FLOOR_HEIGHT = 45 # characters tall
LIMIT_FPS = 20 # 20 frames-per-second maximum
REALTIME = False # set True for real-time, False for turn-based
# ######################################################################
# Exceptions
# ######################################################################
class GameError(Exception):
"""Base Exception for all game errors"""
class FontError(GameError):
"""Font could not be loaded"""
class PositionError(GameError):
"""Position not available"""
# ######################################################################
# Classes
# ######################################################################
class Direction(object):
"""Defines direction of movement
Matrix:
-1, -1 | 0, -1 | 1, -1
-1, 0 | 0, 0 | 1, 0
-1, 1 | 0, 1 | 1, 1
| UP |
LEFT | NONE | RIGHT
| DOWN |
NW | NORTH | NE
WEST | NONE | EAST
SW | SOUTH | SE
"""
NONE = (0, 0)
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)
NORTH = UP
NE = (1, -1)
EAST = RIGHT
SE = (1, 1)
SOUTH = DOWN
SW = (-1, 1)
WEST = LEFT
NW = (-1, -1)
class Map(object):
"""A representation of the dungeon map.
Adds extra functionality for iterating over the map and accessing
individual map cells.
Args:
width (int, optional): the width of the floor [default: FLOOR_WIDTH]
height (int, optional): the height of the floor [default: FLOOR_HEIGHT]
"""
def block(self, position):
"""Blocks a position on the map
Args:
position (Position, tuple): the location to block
"""
map_cell = self.__getitem__(position)
map_cell.block()
def unblock(self, position):
"""Unblocks a position on the map
Args:
position (Position, tuple): the location to unblock
"""
map_cell = self.__getitem__(position)
map_cell.unblock()
def __init__(self, width=None, height=None):
self.width = width or FLOOR_WIDTH
self.height = height or FLOOR_HEIGHT
# initialize map
self.map = {}
for y in range(self.height):
for x in range(self.width):
pos = Position(x, y)
cell = MapCell()
self.map[pos] = cell
def __iter__(self):
for y in range(self.height):
for x in range(self.width):
yield x, y, self.__getitem__((x, y))
def __getitem__(self, key):
value = None
if isinstance(key, Position):
value = self.map[key]
elif isinstance(key, (list, tuple)):
key = Position(*key)
value = self.map[key]
else:
raise PositionError('Invalid position: {}'.format(key))
return value
class MapCell(object):
"""A representation of a map cell which contains metadata information
related to this specific cell within the map
Args:
blocked (bool, optional): blocks movement [default: False]
block_sight (bool, optional): blocks visual [default: False]
"""
def __init__(self, blocked=None, block_sight=None):
self.blocked = blocked or False
self.block_sight = block_sight or blocked or False
def block(self):
self.blocked = True
self.block_sight = True
def unblock(self):
self.blocked = False
self.block_sight = False
class Object(object):
"""Game object. This is used for any displayable game object such
as the player, a mob, an item, a staircase, etc.
Args:
character (str): the character to display
position (Position): (x, y) the position of the object on the map
color (tcod.Color, optional): (R, G, B) color to use when drawing [default: tcod.white]
"""
def __init__(self, character, position, color=tcod.white):
self.character = character
self.position = position
self.color = color
def clear(self):
"""Erase the character from the console"""
self.draw(' ')
def draw(self, character=None):
"""Controls how the object is displayed on the screen.
Args:
character (str, optional): the character to display [default: self.character]
"""
global con
character = character or self.character
tcod.console_set_default_foreground(con, self.color)
x, y = self.position
tcod.console_put_char(con, x, y, character, tcod.BKGND_NONE)
def move(self, direction):
"""Moves the object in a specific direction.
Modifies the object position.
Args:
direction (Direction, tuple): UP, DOWN, LEFT, RIGHT
"""
self.position += direction
class Position(object):
"""A class to help with position-related math in 2d space
Args:
x (int): the width coordinate value
y (int): the height coordinate value
"""
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
equal = False
if isinstance(other, Position):
if self.x == other.x and self.y == other.y:
equal = True
elif isinstance(other, (tuple, list)):
if len(self) == len(other):
if self.x == other[0] and self.y == other[1]:
equal = True
return equal
def __hash__(self):
return hash((self.x, self.y))
def __iter__(self):
yield self.x
yield self.y
def __len__(self):
return len((self.x, self.y))
def __add__(self, other):
if isinstance(other, Direction):
dx, dy = other
self.x += dx
self.y += dy
elif isinstance(other, (list, tuple)):
dx, dy = other
if len(other) == len(self):
self.x += dx
self.y += dy
return self
def __repr__(self):
return f'<Position ({self.x}, {self.y})>'
def __str__(self):
return f'({self.x}, {self.y})'
# ######################################################################
# User Interface Control
# ######################################################################
def handle_keys():
"""Handles keyboard input
Updates:
player_x: x coordinate of player position
player_y: y coordinate of player position
Returns:
bool: True if exit the game is requested else False
"""
global player
exit_game = False
# Run with REALTIME or turn-based
if REALTIME:
key = tcod.console_check_for_keypress()
else:
key = tcod.console_wait_for_keypress(True)
if key.vk == tcod.KEY_ENTER and key.lalt:
# Alt+Enter: toggle fullscreen
tcod.console_set_fullscreen(not tcod.console_is_fullscreen())
elif key.vk == tcod.KEY_ESCAPE:
exit_game = True # exit game
# movement keys
if tcod.console_is_key_pressed(tcod.KEY_UP):
player.move(Direction.UP)
elif tcod.console_is_key_pressed(tcod.KEY_DOWN):
player.move(Direction.DOWN)
elif tcod.console_is_key_pressed(tcod.KEY_LEFT):
player.move(Direction.LEFT)
elif tcod.console_is_key_pressed(tcod.KEY_RIGHT):
player.move(Direction.RIGHT)
return exit_game
# ######################################################################
# Game
# ######################################################################
def initialize_game(font_filepath=None, window_title=None, fullscreen=False):
"""Sets up libtcod and creates a window
Updates:
colors: a dictionary of colors used
con: the tcod console
npc: the npc game object
game_objects: a list of game objects
player: the player game object
Args:
font_filepath (str): the path to the font file [default: terminal.png]
window_title (str): the title to display for the game [default: Python3 Tutorial]
"""
global colors, con, game_objects, npc, player
# Setup displayed font
font_filepath = os.path.abspath(font_filepath or 'terminal.png')
font_flags = tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_ASCII_INCOL
if not os.path.exists(font_filepath):
raise FontError("Could not open font file: {}".format(font_filepath))
tcod.console_set_custom_font(font_filepath, font_flags)
# Setup window
window_title = window_title or 'Python3 Tutorial'
fullscreen = fullscreen or False
tcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, window_title, fullscreen)
# Limit frames per second
tcod.sys_set_fps(LIMIT_FPS)
# Create the console
con = tcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
# Setup player's initial position
player_starting_position = Position(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
player = Object('@', player_starting_position)
npc_starting_position = Position(SCREEN_WIDTH // 2 - 5, SCREEN_HEIGHT // 2)
npc = Object('@', npc_starting_position, color=tcod.yellow)
game_objects = [npc, player]
# Setup some colors
colors = {
'white': tcod.white,
'yellow': tcod.yellow,
'dark wall': tcod.Color(0, 0, 100),
'dark ground': tcod.Color(50, 50, 150),
}
# Create the map
make_map()
def make_map():
"""Creates the global map
Updates:
level: the global map
"""
# This is a "level" rather than a "map" because python has a "map"
# function built-in and we might want to use that function later.
global level
level = Map()
# Create some pillars / blocked locations
locations = [
(30, 22),
(50, 22),
]
for location in locations:
level.block(location)
def render_all():
"""Draws map and game objects.
Accesses:
colors: dictionary of colors
con: the game console
game_objects: npcs, mobs, player, items, etc.
level: the global map
"""
global colors, level, con, game_objects
wall = colors.get('dark wall')
ground = colors.get('dark ground')
for x, y, cell in level:
if cell.block_sight:
tcod.console_set_char_background(con, x, y, wall, tcod.BKGND_SET)
else:
tcod.console_set_char_background(con, x, y, ground, tcod.BKGND_SET)
for game_object in game_objects:
game_object.draw()
tcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
def main():
global game_objects
initialize_game()
# Game loop
exit_game = False
while not tcod.console_is_window_closed() and exit_game is not True:
render_all()
tcod.console_flush()
for game_object in game_objects:
game_object.clear()
# handle keys
exit_game = handle_keys()
if __name__ == '__main__':
main()