I've only just gotten this working and need to clean it up a bit still but I thought it was neat and wanted to share.
To run the example you need code.py, castle_sprite_sheet.bmp, and map.csv from the files section or the repo. Once you get it working edit the map.csv file with a spreadsheet app or any text editor to change the map around. If you want to take it a step further you can customize the tile stats and behaviors in the TILES dict to invent your own games.
The main code.py has been updated to the latest version and now shows an example of using a map larger than the screen, as well as allowing the player to push other entities.
Code py:
import board
import displayio
import adafruit_imageload
from displayio import Palette
from adafruit_pybadger import PyBadger
import time
# Direction constants for comparison
UP = 0
DOWN = 1
RIGHT = 2
LEFT = 3
# how long to wait between rendering frames
FPS_DELAY = 1/30
# how many tiles can fit on thes screen. Tiles are 16x16
SCREEN_HEIGHT_TILES = 8
SCREEN_WIDTH_TILES = 10
# hold the map state as it came out of the csv. Only holds non-entities.
ORIGINAL_MAP = {}
# hold the current map state if/when it changes. Only holds non-entities.
CURRENT_MAP = {}
# dictionary with tuple keys that map to tile type values
# e.x. {(0,0): "left_wall", (1,1): "floor"}
CAMERA_VIEW = {}
# how far offset the camera is from the CURRENT_MAP
# used to determine where things are at in the camera view vs. the MAP
CAMERA_OFFSET_X = 0
CAMERA_OFFSET_Y = 0
# list of sprite objects, one for each entity
ENTITY_SPRITES = []
# Dictionary with touple keys that map to lists of entity objects.
# Each one has the index of the sprite in the ENTITY_SPRITES list
# and the tile type string
ENTITY_SPRITES_DICT = {}
# list of entities that need to be on the screen currently based on the camera view
NEED_TO_DRAW_ENTITIES = []
# hold the location of the player in tile coordinates
PLAYER_LOC = (0,0)
# return from CURRENT_MAP the tile name of the tile of the given coords
def get_tile(coords):
return CURRENT_MAP[coords[0], coords[1]]
# return from TILES dict the tile object with stats and behavior for the tile at the given coords.
def get_tile_obj(coords):
return TILES[CURRENT_MAP[coords[0], coords[1]]]
# check the can_walk property of the tile at the given coordinates
def is_tile_moveable(tile_coords):
return TILES[CURRENT_MAP[tile_coords[0], tile_coords[1]]]['can_walk']
# behavior function that allows the player to push the entity
def allow_push(to_coords, from_coords, entity_obj):
push_x_offset = 0
push_y_offset = 0
print("inside allow push")
print("%s -> %s" % (from_coords, to_coords))
if to_coords[0] < from_coords[0]:
# moving left
push_x_offset = -1
push_y_offset = 0
elif to_coords[0] > from_coords[0]:
# moving right
push_x_offset = 1
push_y_offset = 0
elif to_coords[1] < from_coords[1]:
# moving up
push_x_offset = 0
push_y_offset = -1
elif to_coords[1] > from_coords[1]:
# moving down
push_x_offset = 0
push_y_offset = 1
# coords where we will be pushing the entity to
push_to_tile_coords = (to_coords[0]+ push_x_offset, to_coords[1]+ push_y_offset)
# check if the entity is allowed to move to there
if is_tile_moveable(push_to_tile_coords):
#print("dict before %s" % ENTITY_SPRITES_DICT)
# check if there are etity(s) at the tile we are trying to push to.
if push_to_tile_coords in ENTITY_SPRITES_DICT:
# append the thing we are pushing to the the list at the new coordinates in the dictionary
ENTITY_SPRITES_DICT[push_to_tile_coords].append(entity_obj)
else:
# create a list with the thing we are pushing and store it in the dictionary
ENTITY_SPRITES_DICT[push_to_tile_coords] = [entity_obj]
# remove the thing we are pushing from it's old location
ENTITY_SPRITES_DICT[to_coords].remove(entity_obj)
# if there are no entities left in the old location
if len(ENTITY_SPRITES_DICT[to_coords]) == 0:
# delete the empty lyst
del ENTITY_SPRITES_DICT[to_coords]
#print("dict...
Read more »
This looks really fun. Thanks for sharing it. I think it would work with the PyGamer with no changes to the code.