adding Circuit Python tilemap game
This commit is contained in:
parent
f22cb03215
commit
101e919517
17 changed files with 1068 additions and 0 deletions
90
Tilemap_Game_With_CircuitPython/basic_movement.py
Normal file
90
Tilemap_Game_With_CircuitPython/basic_movement.py
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import board
|
||||
import displayio
|
||||
import adafruit_imageload
|
||||
#from tilegame_assets.controls_helper import controls
|
||||
import ugame
|
||||
|
||||
display = board.DISPLAY
|
||||
player_loc = {"x": 4, "y": 3}
|
||||
|
||||
# Load the sprite sheet (bitmap)
|
||||
sprite_sheet, palette = adafruit_imageload.load("tilegame_assets/castle_sprite_sheet.bmp",
|
||||
bitmap=displayio.Bitmap,
|
||||
palette=displayio.Palette)
|
||||
|
||||
# Create the sprite TileGrid
|
||||
sprite = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=16,
|
||||
tile_height=16,
|
||||
default_tile=0)
|
||||
|
||||
# Create the castle TileGrid
|
||||
castle = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
|
||||
width=10,
|
||||
height=8,
|
||||
tile_width=16,
|
||||
tile_height=16)
|
||||
|
||||
# Create a Group to hold the sprite and add it
|
||||
sprite_group = displayio.Group()
|
||||
sprite_group.append(sprite)
|
||||
|
||||
# Create a Group to hold the castle and add it
|
||||
castle_group = displayio.Group(scale=1)
|
||||
castle_group.append(castle)
|
||||
|
||||
# Create a Group to hold the sprite and castle
|
||||
group = displayio.Group()
|
||||
|
||||
# Add the sprite and castle to the group
|
||||
group.append(castle_group)
|
||||
group.append(sprite_group)
|
||||
|
||||
# Castle tile assignments
|
||||
# corners
|
||||
castle[0, 0] = 3 # upper left
|
||||
castle[9, 0] = 5 # upper right
|
||||
castle[0, 7] = 9 # lower left
|
||||
castle[9, 7] = 11 # lower right
|
||||
# top / bottom walls
|
||||
for x in range(1, 9):
|
||||
castle[x, 0] = 4 # top
|
||||
castle[x, 7] = 10 # bottom
|
||||
# left/ right walls
|
||||
for y in range(1, 7):
|
||||
castle[0, y] = 6 # left
|
||||
castle[9, y] = 8 # right
|
||||
# floor
|
||||
for x in range(1, 9):
|
||||
for y in range(1, 7):
|
||||
castle[x, y] = 7 # floor
|
||||
|
||||
# put the sprite somewhere in the castle
|
||||
sprite.x = 16 * player_loc["x"]
|
||||
sprite.y = 16 * player_loc["y"]
|
||||
|
||||
# Add the Group to the Display
|
||||
display.show(group)
|
||||
|
||||
prev_btn_vals = ugame.buttons.get_pressed()
|
||||
|
||||
while True:
|
||||
cur_btn_vals = ugame.buttons.get_pressed()
|
||||
if not prev_btn_vals & ugame.K_UP and cur_btn_vals & ugame.K_UP:
|
||||
player_loc["y"] = max(1, player_loc["y"]-1)
|
||||
if not prev_btn_vals & ugame.K_DOWN and cur_btn_vals & ugame.K_DOWN:
|
||||
player_loc["y"] = min(6, player_loc["y"]+1)
|
||||
|
||||
if not prev_btn_vals & ugame.K_RIGHT and cur_btn_vals & ugame.K_RIGHT:
|
||||
player_loc["x"] = min(8, player_loc["x"]+1)
|
||||
if not prev_btn_vals & ugame.K_LEFT and cur_btn_vals & ugame.K_LEFT:
|
||||
player_loc["x"] = max(1, player_loc["x"]-1)
|
||||
|
||||
# update the the player sprite position
|
||||
sprite.x = 16 * player_loc["x"]
|
||||
sprite.y = 16 * player_loc["y"]
|
||||
|
||||
# update the previous values
|
||||
prev_btn_vals = cur_btn_vals
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
import board
|
||||
import displayio
|
||||
import adafruit_imageload
|
||||
from tilegame_assets.controls_helper import controls
|
||||
|
||||
display = board.DISPLAY
|
||||
player_loc = {"x":4, "y":3}
|
||||
|
||||
# Load the sprite sheet (bitmap)
|
||||
sprite_sheet, palette = adafruit_imageload.load("tilegame_assets/castle_sprite_sheet_edited.bmp",
|
||||
bitmap=displayio.Bitmap,
|
||||
palette=displayio.Palette)
|
||||
# make the color at 0 index transparent.
|
||||
palette.make_transparent(0)
|
||||
|
||||
# Create the sprite TileGrid
|
||||
sprite = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=16,
|
||||
tile_height=16,
|
||||
default_tile=0)
|
||||
|
||||
# Create the castle TileGrid
|
||||
castle = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
|
||||
width=10,
|
||||
height=8,
|
||||
tile_width=16,
|
||||
tile_height=16)
|
||||
|
||||
# Create a Group to hold the sprite and add it
|
||||
sprite_group = displayio.Group()
|
||||
sprite_group.append(sprite)
|
||||
|
||||
# Create a Group to hold the castle and add it
|
||||
castle_group = displayio.Group(scale=1)
|
||||
castle_group.append(castle)
|
||||
|
||||
# Create a Group to hold the sprite and castle
|
||||
group = displayio.Group()
|
||||
|
||||
# Add the sprite and castle to the group
|
||||
group.append(castle_group)
|
||||
group.append(sprite_group)
|
||||
|
||||
# Castle tile assignments
|
||||
# corners
|
||||
castle[0, 0] = 3 # upper left
|
||||
castle[9, 0] = 5 # upper right
|
||||
castle[0, 7] = 9 # lower left
|
||||
castle[9, 7] = 11 # lower right
|
||||
# top / bottom walls
|
||||
for x in range(1, 9):
|
||||
castle[x, 0] = 4 # top
|
||||
castle[x, 7] = 10 # bottom
|
||||
# left/ right walls
|
||||
for y in range(1, 7):
|
||||
castle[0, y] = 6 # left
|
||||
castle[9, y] = 8 # right
|
||||
# floor
|
||||
for x in range(1, 9):
|
||||
for y in range(1, 7):
|
||||
castle[x, y] = 7 # floor
|
||||
|
||||
# put the sprite somewhere in the castle
|
||||
sprite.x = 16 * player_loc["x"]
|
||||
sprite.y = 16 * player_loc["y"]
|
||||
|
||||
# Add the Group to the Display
|
||||
display.show(group)
|
||||
|
||||
prev_btn_vals = controls.button
|
||||
|
||||
while True:
|
||||
cur_btn_vals = controls.button
|
||||
if not prev_btn_vals.up and cur_btn_vals.up:
|
||||
player_loc["y"] = max(1, player_loc["y"]-1)
|
||||
if not prev_btn_vals.down and cur_btn_vals.down:
|
||||
player_loc["y"] = min(6, player_loc["y"]+1)
|
||||
|
||||
if not prev_btn_vals.right and cur_btn_vals.right:
|
||||
player_loc["x"] = min(8, player_loc["x"]+1)
|
||||
if not prev_btn_vals.left and cur_btn_vals.left:
|
||||
player_loc["x"] = max(1, player_loc["x"]-1)
|
||||
|
||||
# update the the player sprite position
|
||||
sprite.x = 16 * player_loc["x"]
|
||||
sprite.y = 16 * player_loc["y"]
|
||||
|
||||
# update the previous values
|
||||
prev_btn_vals = cur_btn_vals
|
||||
68
Tilemap_Game_With_CircuitPython/basic_rendering.py
Normal file
68
Tilemap_Game_With_CircuitPython/basic_rendering.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import board
|
||||
import displayio
|
||||
import adafruit_imageload
|
||||
|
||||
display = board.DISPLAY
|
||||
|
||||
# Load the sprite sheet (bitmap)
|
||||
sprite_sheet, palette = adafruit_imageload.load("tilegame_assets/castle_sprite_sheet.bmp",
|
||||
bitmap=displayio.Bitmap,
|
||||
palette=displayio.Palette)
|
||||
|
||||
# Create the sprite TileGrid
|
||||
sprite = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=16,
|
||||
tile_height=16,
|
||||
default_tile=0)
|
||||
|
||||
# Create the castle TileGrid
|
||||
castle = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
|
||||
width=10,
|
||||
height=8,
|
||||
tile_width=16,
|
||||
tile_height=16)
|
||||
|
||||
# Create a Group to hold the sprite and add it
|
||||
sprite_group = displayio.Group()
|
||||
sprite_group.append(sprite)
|
||||
|
||||
# Create a Group to hold the castle and add it
|
||||
castle_group = displayio.Group(scale=1)
|
||||
castle_group.append(castle)
|
||||
|
||||
# Create a Group to hold the sprite and castle
|
||||
group = displayio.Group()
|
||||
|
||||
# Add the sprite and castle to the group
|
||||
group.append(castle_group)
|
||||
group.append(sprite_group)
|
||||
|
||||
# Castle tile assignments
|
||||
# corners
|
||||
castle[0, 0] = 3 # upper left
|
||||
castle[9, 0] = 5 # upper right
|
||||
castle[0, 7] = 9 # lower left
|
||||
castle[9, 7] = 11 # lower right
|
||||
# top / bottom walls
|
||||
for x in range(1, 9):
|
||||
castle[x, 0] = 4 # top
|
||||
castle[x, 7] = 10 # bottom
|
||||
# left/ right walls
|
||||
for y in range(1, 7):
|
||||
castle[0, y] = 6 # left
|
||||
castle[9, y] = 8 # right
|
||||
# floor
|
||||
for x in range(1, 9):
|
||||
for y in range(1, 7):
|
||||
castle[x, y] = 7 # floor
|
||||
|
||||
# put the sprite somewhere in the castle
|
||||
sprite.x = 16 * 4
|
||||
sprite.y = 16 * 3
|
||||
|
||||
# Add the Group to the Display
|
||||
display.show(group)
|
||||
while True:
|
||||
pass
|
||||
603
Tilemap_Game_With_CircuitPython/code.py
Normal file
603
Tilemap_Game_With_CircuitPython/code.py
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
import time
|
||||
import random
|
||||
import gc
|
||||
import board
|
||||
import displayio
|
||||
import adafruit_imageload
|
||||
from displayio import Palette
|
||||
|
||||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
from tilegame_assets.controls_helper import controls
|
||||
from tilegame_assets.tiles import TILES
|
||||
from tilegame_assets.tiles import take_item
|
||||
from tilegame_assets.states import *
|
||||
from tilegame_assets.fun_facts import FACTS
|
||||
from tilegame_assets.text_helper import wrap_nicely
|
||||
|
||||
# Direction constants for comparison
|
||||
UP = 0
|
||||
DOWN = 1
|
||||
RIGHT = 2
|
||||
LEFT = 3
|
||||
|
||||
# how long to wait between rendering frames
|
||||
FPS_DELAY = 1 / 60
|
||||
|
||||
# how many tiles can fit on thes screen. Tiles are 16x16 pixels
|
||||
SCREEN_HEIGHT_TILES = 8
|
||||
SCREEN_WIDTH_TILES = 10
|
||||
|
||||
# list of maps in order they should be played
|
||||
MAPS = ["map0.csv", "map1.csv"]
|
||||
|
||||
GAME_STATE = {
|
||||
# hold the map state as it came out of the csv. Only holds non-entities.
|
||||
"ORIGINAL_MAP": {},
|
||||
# hold the current map state as it changes. Only holds non-entities.
|
||||
"CURRENT_MAP": {},
|
||||
# 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": {},
|
||||
# hold the location of the player in tile coordinates
|
||||
"PLAYER_LOC": (0, 0),
|
||||
# list of items the player has in inventory
|
||||
"INVENTORY": [],
|
||||
# how many hearts there are in this map level
|
||||
"TOTAL_HEARTS": 0,
|
||||
# sprite object to draw for the player
|
||||
"PLAYER_SPRITE": None,
|
||||
# size of the map
|
||||
"MAP_WIDTH": 0,
|
||||
"MAP_HEIGHT": 0,
|
||||
# which map level within MAPS we are currently playing
|
||||
"MAP_INDEX": 0,
|
||||
# current state of the state machine
|
||||
"STATE": STATE_PLAYING,
|
||||
}
|
||||
|
||||
# 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 GAME_STATE['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 = []
|
||||
|
||||
# list of entities that need to be on the screen currently based on the camera view
|
||||
NEED_TO_DRAW_ENTITIES = []
|
||||
|
||||
|
||||
# return from GAME_STATE['CURRENT_MAP'] the tile name of the tile of the given coords
|
||||
def get_tile(coords):
|
||||
return GAME_STATE["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[GAME_STATE["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[GAME_STATE["CURRENT_MAP"][tile_coords[0], tile_coords[1]]]["can_walk"]
|
||||
|
||||
print("after funcs {}".format(gc.mem_free()))
|
||||
|
||||
# display object variable
|
||||
display = board.DISPLAY
|
||||
|
||||
# Load the sprite sheet (bitmap)
|
||||
sprite_sheet, palette = adafruit_imageload.load(
|
||||
"tilegame_assets/sprite_sheet.bmp",
|
||||
bitmap=displayio.Bitmap,
|
||||
palette=displayio.Palette,
|
||||
)
|
||||
|
||||
# make green be transparent so entities can be drawn on top of map tiles
|
||||
palette.make_transparent(0)
|
||||
|
||||
# Create the castle TileGrid
|
||||
castle = displayio.TileGrid(
|
||||
sprite_sheet,
|
||||
pixel_shader=palette,
|
||||
width=10,
|
||||
height=8,
|
||||
tile_width=16,
|
||||
tile_height=16,
|
||||
)
|
||||
|
||||
# Create a Group to hold the sprites and add it
|
||||
sprite_group = displayio.Group(max_size=32)
|
||||
|
||||
# Create a Group to hold the castle and add it
|
||||
castle_group = displayio.Group()
|
||||
castle_group.append(castle)
|
||||
|
||||
# Create a Group to hold the sprite and castle
|
||||
group = displayio.Group()
|
||||
|
||||
# Add the sprite and castle to the group
|
||||
group.append(castle_group)
|
||||
group.append(sprite_group)
|
||||
|
||||
|
||||
def load_map(file_name):
|
||||
global ENTITY_SPRITES, CAMERA_VIEW
|
||||
|
||||
# empty the sprite_group
|
||||
for cur_s in ENTITY_SPRITES:
|
||||
sprite_group.remove(cur_s)
|
||||
# remove player sprite
|
||||
try:
|
||||
sprite_group.remove(GAME_STATE["PLAYER_SPRITE"])
|
||||
except:
|
||||
pass
|
||||
|
||||
# reset map and other game state objects
|
||||
GAME_STATE["ORIGINAL_MAP"] = {}
|
||||
GAME_STATE["CURRENT_MAP"] = {}
|
||||
ENTITY_SPRITES = []
|
||||
GAME_STATE["ENTITY_SPRITES_DICT"] = {}
|
||||
CAMERA_VIEW = {}
|
||||
GAME_STATE["INVENTORY"] = []
|
||||
GAME_STATE["TOTAL_HEARTS"] = 0
|
||||
|
||||
# Open and read raw string from the map csv file
|
||||
f = open("tilegame_assets/{}".format(file_name), "r")
|
||||
map_csv_str = f.read()
|
||||
f.close()
|
||||
|
||||
# split the raw string into lines
|
||||
map_csv_lines = map_csv_str.replace("\r", "").split("\n")
|
||||
|
||||
# set the WIDTH and HEIGHT variables.
|
||||
# this assumes the map is rectangular.
|
||||
GAME_STATE["MAP_HEIGHT"] = len(map_csv_lines)
|
||||
GAME_STATE["MAP_WIDTH"] = len(map_csv_lines[0].split(","))
|
||||
|
||||
# loop over each line storing index in y variable
|
||||
for y, line in enumerate(map_csv_lines):
|
||||
# ignore empty line
|
||||
if line != "":
|
||||
# loop over each tile type separated by commas, storing index in x variable
|
||||
for x, tile_name in enumerate(line.split(",")):
|
||||
print("%s '%s'" % (len(tile_name), str(tile_name)))
|
||||
|
||||
# if the tile exists in our main dictionary
|
||||
if tile_name in TILES.keys():
|
||||
|
||||
# if the tile is an entity
|
||||
if (
|
||||
"entity" in TILES[tile_name].keys()
|
||||
and TILES[tile_name]["entity"]
|
||||
):
|
||||
# set the map tiles to floor
|
||||
GAME_STATE["ORIGINAL_MAP"][x, y] = "floor"
|
||||
GAME_STATE["CURRENT_MAP"][x, y] = "floor"
|
||||
|
||||
if tile_name == "heart":
|
||||
GAME_STATE["TOTAL_HEARTS"] += 1
|
||||
|
||||
# if it's the player
|
||||
if tile_name == "player":
|
||||
# Create the sprite TileGrid
|
||||
GAME_STATE["PLAYER_SPRITE"] = displayio.TileGrid(
|
||||
sprite_sheet,
|
||||
pixel_shader=palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=16,
|
||||
tile_height=16,
|
||||
default_tile=TILES[tile_name]["sprite_index"],
|
||||
)
|
||||
|
||||
# set the position of sprite on screen
|
||||
GAME_STATE["PLAYER_SPRITE"].x = x * 16
|
||||
GAME_STATE["PLAYER_SPRITE"].y = y * 16
|
||||
|
||||
# set position in x,y tile coords for reference later
|
||||
GAME_STATE["PLAYER_LOC"] = (x, y)
|
||||
|
||||
# add sprite to the group
|
||||
sprite_group.append(GAME_STATE["PLAYER_SPRITE"])
|
||||
else: # not the player
|
||||
# Create the sprite TileGrid
|
||||
entity_srite = displayio.TileGrid(
|
||||
sprite_sheet,
|
||||
pixel_shader=palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=16,
|
||||
tile_height=16,
|
||||
default_tile=TILES[tile_name]["sprite_index"],
|
||||
)
|
||||
# set the position of sprite on screen
|
||||
# default to off the edge
|
||||
entity_srite.x = -16
|
||||
entity_srite.y = -16
|
||||
|
||||
# add the sprite object to ENTITY_SPRITES list
|
||||
ENTITY_SPRITES.append(entity_srite)
|
||||
# print("setting GAME_STATE['ENTITY_SPRITES_DICT'][%s,%s]" % (x,y))
|
||||
|
||||
# create an entity obj
|
||||
entity_obj = {
|
||||
"entity_sprite_index": len(ENTITY_SPRITES) - 1,
|
||||
"map_tile_name": tile_name,
|
||||
}
|
||||
|
||||
# if there are no entities at this location yet
|
||||
if (x, y) not in GAME_STATE["ENTITY_SPRITES_DICT"]:
|
||||
# create a list and add it to the dictionary at the x,y location
|
||||
GAME_STATE["ENTITY_SPRITES_DICT"][x, y] = [entity_obj]
|
||||
else:
|
||||
# append the entity to the existing list in the dictionary
|
||||
GAME_STATE["ENTITY_SPRITES_DICT"][x, y].append(
|
||||
entity_obj
|
||||
)
|
||||
|
||||
else: # tile is not entity
|
||||
# set the tile_name into MAP dictionaries
|
||||
GAME_STATE["ORIGINAL_MAP"][x, y] = tile_name
|
||||
GAME_STATE["CURRENT_MAP"][x, y] = tile_name
|
||||
|
||||
else: # tile type wasn't found in dict
|
||||
print("tile: %s not found in TILES dict" % tile_name)
|
||||
# add all entity sprites to the group
|
||||
print("appending {} sprites".format(len(ENTITY_SPRITES)))
|
||||
for entity in ENTITY_SPRITES:
|
||||
sprite_group.append(entity)
|
||||
|
||||
|
||||
print("loading map")
|
||||
load_map(MAPS[GAME_STATE["MAP_INDEX"]])
|
||||
|
||||
# Add the Group to the Display
|
||||
display.show(group)
|
||||
|
||||
# variables to store previous value of button state
|
||||
prev_up = False
|
||||
prev_down = False
|
||||
prev_left = False
|
||||
prev_right = False
|
||||
|
||||
|
||||
# helper function returns true if player is allowed to move given direction
|
||||
# based on can_walk property of the tiles next to the player
|
||||
def can_player_move(direction):
|
||||
if direction == UP:
|
||||
tile_above_coords = (
|
||||
GAME_STATE["PLAYER_LOC"][0],
|
||||
GAME_STATE["PLAYER_LOC"][1] - 1,
|
||||
)
|
||||
return TILES[
|
||||
GAME_STATE["CURRENT_MAP"][tile_above_coords[0], tile_above_coords[1]]
|
||||
]["can_walk"]
|
||||
|
||||
if direction == DOWN:
|
||||
tile_below_coords = (
|
||||
GAME_STATE["PLAYER_LOC"][0],
|
||||
GAME_STATE["PLAYER_LOC"][1] + 1,
|
||||
)
|
||||
return TILES[
|
||||
GAME_STATE["CURRENT_MAP"][tile_below_coords[0], tile_below_coords[1]]
|
||||
]["can_walk"]
|
||||
|
||||
if direction == LEFT:
|
||||
tile_left_of_coords = (
|
||||
GAME_STATE["PLAYER_LOC"][0] - 1,
|
||||
GAME_STATE["PLAYER_LOC"][1],
|
||||
)
|
||||
return TILES[
|
||||
GAME_STATE["CURRENT_MAP"][tile_left_of_coords[0], tile_left_of_coords[1]]
|
||||
]["can_walk"]
|
||||
|
||||
if direction == RIGHT:
|
||||
tile_right_of_coords = (
|
||||
GAME_STATE["PLAYER_LOC"][0] + 1,
|
||||
GAME_STATE["PLAYER_LOC"][1],
|
||||
)
|
||||
return TILES[
|
||||
GAME_STATE["CURRENT_MAP"][tile_right_of_coords[0], tile_right_of_coords[1]]
|
||||
]["can_walk"]
|
||||
|
||||
|
||||
# set the appropriate tiles into the CAMERA_VIEW dictionary
|
||||
# based on given starting coords and size
|
||||
def set_camera_view(startX, startY, width, height):
|
||||
global CAMERA_OFFSET_X
|
||||
global CAMERA_OFFSET_Y
|
||||
# set the offset variables for use in other parts of the code
|
||||
CAMERA_OFFSET_X = startX
|
||||
CAMERA_OFFSET_Y = startY
|
||||
|
||||
# loop over the rows and indexes in the desired size section
|
||||
for y_index, y in enumerate(range(startY, startY + height)):
|
||||
# loop over columns and indexes in the desired size section
|
||||
for x_index, x in enumerate(range(startX, startX + width)):
|
||||
# print("setting camera_view[%s,%s]" % (x_index,y_index))
|
||||
try:
|
||||
# set the tile at the current coordinate of the MAP into the CAMERA_VIEW
|
||||
CAMERA_VIEW[x_index, y_index] = GAME_STATE["CURRENT_MAP"][x, y]
|
||||
except KeyError:
|
||||
# if coordinate is out of bounds set it to floor by default
|
||||
CAMERA_VIEW[x_index, y_index] = "floor"
|
||||
|
||||
|
||||
# draw the current CAMERA_VIEW dictionary and the GAME_STATE['ENTITY_SPRITES_DICT']
|
||||
def draw_camera_view():
|
||||
# list that will hold all entities that have been drawn based on their MAP location
|
||||
# any entities not in this list should get moved off the screen
|
||||
drew_entities = []
|
||||
# print(CAMERA_VIEW)
|
||||
|
||||
# loop over y tile coordinates
|
||||
for y in range(0, SCREEN_HEIGHT_TILES):
|
||||
# loop over x tile coordinates
|
||||
for x in range(0, SCREEN_WIDTH_TILES):
|
||||
# tile name at this location
|
||||
tile_name = CAMERA_VIEW[x, y]
|
||||
|
||||
# if tile exists in the main dictionary
|
||||
if tile_name in TILES.keys():
|
||||
# if there are entity(s) at this location
|
||||
if (x + CAMERA_OFFSET_X, y + CAMERA_OFFSET_Y) in GAME_STATE[
|
||||
"ENTITY_SPRITES_DICT"
|
||||
]:
|
||||
# default background for entities is floor
|
||||
castle[x, y] = TILES["floor"]["sprite_index"]
|
||||
|
||||
# if it's not the player
|
||||
if tile_name != "player":
|
||||
# loop over all entities at this location
|
||||
for entity_obj_at_tile in GAME_STATE["ENTITY_SPRITES_DICT"][
|
||||
x + CAMERA_OFFSET_X, y + CAMERA_OFFSET_Y
|
||||
]:
|
||||
# set appropriate x,y screen coordinates
|
||||
# based on tile coordinates
|
||||
ENTITY_SPRITES[
|
||||
int(entity_obj_at_tile["entity_sprite_index"])
|
||||
].x = (x * 16)
|
||||
ENTITY_SPRITES[
|
||||
int(entity_obj_at_tile["entity_sprite_index"])
|
||||
].y = (y * 16)
|
||||
|
||||
# add the index of the entity sprite to the draw_entities
|
||||
# list so we know not to hide it later.
|
||||
drew_entities.append(
|
||||
entity_obj_at_tile["entity_sprite_index"]
|
||||
)
|
||||
|
||||
else: # no entities at this location
|
||||
# set the sprite index of this tile into the CASTLE dictionary
|
||||
castle[x, y] = TILES[tile_name]["sprite_index"]
|
||||
|
||||
else: # tile type not found in main dictionary
|
||||
# default to floor tile
|
||||
castle[x, y] = TILES["floor"]["sprite_index"]
|
||||
|
||||
# if the player is at this x,y tile coordinate accounting for camera offset
|
||||
if GAME_STATE["PLAYER_LOC"] == ((x + CAMERA_OFFSET_X, y + CAMERA_OFFSET_Y)):
|
||||
# set player sprite screen coordinates
|
||||
GAME_STATE["PLAYER_SPRITE"].x = x * 16
|
||||
GAME_STATE["PLAYER_SPRITE"].y = y * 16
|
||||
|
||||
# loop over all entity sprites
|
||||
for index in range(0, len(ENTITY_SPRITES)):
|
||||
# if the sprite wasn't drawn then it's outside the camera view
|
||||
if index not in drew_entities:
|
||||
# hide the sprite by moving it off screen
|
||||
ENTITY_SPRITES[index].x = int(-16)
|
||||
ENTITY_SPRITES[index].y = int(-16)
|
||||
|
||||
|
||||
# variable to store timestamp of last drawn frame
|
||||
last_update_time = 0
|
||||
|
||||
# variables to store movement offset values
|
||||
x_offset = 0
|
||||
y_offset = 0
|
||||
|
||||
|
||||
def show_splash(new_text, color, vertical_offset=18):
|
||||
text_area.text = ""
|
||||
text_area.text = new_text
|
||||
text_area.y = round(text_area.text.count("\n") * vertical_offset / 2)
|
||||
text_area.color = color
|
||||
group.append(splash)
|
||||
|
||||
|
||||
# game message background bmp file
|
||||
with open(
|
||||
"tilegame_assets/game_message_background.bmp", "rb"
|
||||
) as game_message_background:
|
||||
# Make the splash context
|
||||
splash = displayio.Group(max_size=4)
|
||||
|
||||
odb = displayio.OnDiskBitmap(game_message_background)
|
||||
|
||||
bg_grid = displayio.TileGrid(odb, pixel_shader=displayio.ColorConverter())
|
||||
|
||||
splash.append(bg_grid)
|
||||
|
||||
# Text for the message
|
||||
text_group = displayio.Group(max_size=8, scale=1, x=14, y=18)
|
||||
text_area = label.Label(terminalio.FONT, text=" " * 180, color=0xD39AE5)
|
||||
text_group.append(text_area)
|
||||
splash.append(text_group)
|
||||
|
||||
# main loop
|
||||
while True:
|
||||
# set the current button values into variables
|
||||
cur_btn_vals = controls.button
|
||||
cur_up = cur_btn_vals.up
|
||||
cur_down = cur_btn_vals.down
|
||||
cur_right = cur_btn_vals.right
|
||||
cur_left = cur_btn_vals.left
|
||||
cur_a = cur_btn_vals.a
|
||||
|
||||
if GAME_STATE["STATE"] == STATE_WAITING:
|
||||
print(cur_a)
|
||||
if cur_a:
|
||||
GAME_STATE["STATE"] = STATE_PLAYING
|
||||
group.remove(splash)
|
||||
|
||||
if GAME_STATE["STATE"] == STATE_PLAYING:
|
||||
# check for up button press / release
|
||||
if not cur_up and prev_up:
|
||||
if can_player_move(UP):
|
||||
x_offset = 0
|
||||
y_offset = -1
|
||||
|
||||
# check for down button press / release
|
||||
if not cur_down and prev_down:
|
||||
if can_player_move(DOWN):
|
||||
x_offset = 0
|
||||
y_offset = 1
|
||||
|
||||
# check for right button press / release
|
||||
if not cur_right and prev_right:
|
||||
if can_player_move(RIGHT):
|
||||
x_offset = 1
|
||||
y_offset = 0
|
||||
|
||||
# check for left button press / release
|
||||
if not cur_left and prev_left:
|
||||
if can_player_move(LEFT):
|
||||
x_offset = -1
|
||||
y_offset = 0
|
||||
|
||||
# if any offset is not zero then we need to process player movement
|
||||
if x_offset != 0 or y_offset != 0:
|
||||
# variable to store if player is allowed to move
|
||||
can_move = False
|
||||
|
||||
# coordinates the player is moving to
|
||||
moving_to_coords = (
|
||||
GAME_STATE["PLAYER_LOC"][0] + x_offset,
|
||||
GAME_STATE["PLAYER_LOC"][1] + y_offset,
|
||||
)
|
||||
|
||||
# tile name of the spot player is moving to
|
||||
moving_to_tile_name = GAME_STATE["CURRENT_MAP"][
|
||||
moving_to_coords[0], moving_to_coords[1]
|
||||
]
|
||||
|
||||
# if there are entity(s) at spot the player is moving to
|
||||
if moving_to_coords in GAME_STATE["ENTITY_SPRITES_DICT"]:
|
||||
print("found entity(s) where we are moving to")
|
||||
|
||||
# loop over all entities at the location player is moving to
|
||||
for entity_obj in GAME_STATE["ENTITY_SPRITES_DICT"][
|
||||
moving_to_coords
|
||||
]:
|
||||
print("checking entity %s" % entity_obj["map_tile_name"])
|
||||
# if the entity has a before_move behavior function
|
||||
if "before_move" in TILES[entity_obj["map_tile_name"]].keys():
|
||||
print(
|
||||
"calling before_move %s, %s, %s"
|
||||
% (
|
||||
moving_to_coords,
|
||||
GAME_STATE["PLAYER_LOC"],
|
||||
entity_obj,
|
||||
)
|
||||
)
|
||||
# call the before_move behavior function act upon it's result
|
||||
if TILES[entity_obj["map_tile_name"]]["before_move"](
|
||||
moving_to_coords,
|
||||
GAME_STATE["PLAYER_LOC"],
|
||||
entity_obj,
|
||||
GAME_STATE,
|
||||
):
|
||||
# all the movement if it returned true
|
||||
can_move = True
|
||||
else:
|
||||
# break and don't allow movement if it returned false
|
||||
break
|
||||
else: # entity does not have a before_move function
|
||||
# allow movement
|
||||
can_move = True
|
||||
if can_move:
|
||||
# set the player loc variable to the new coords
|
||||
GAME_STATE["PLAYER_LOC"] = moving_to_coords
|
||||
|
||||
else: # no entities at the location player is moving to
|
||||
# set player loc variable to new coords
|
||||
GAME_STATE["PLAYER_LOC"] = moving_to_coords
|
||||
|
||||
# reset movement offset variables
|
||||
y_offset = 0
|
||||
x_offset = 0
|
||||
|
||||
# set previous button values for next iteration
|
||||
prev_up = cur_up
|
||||
prev_down = cur_down
|
||||
prev_right = cur_right
|
||||
prev_left = cur_left
|
||||
|
||||
# current time
|
||||
now = time.monotonic()
|
||||
|
||||
# if it has been long enough based on FPS delay
|
||||
if now > last_update_time + FPS_DELAY:
|
||||
# Set camera to 10x8 centered on the player
|
||||
# Clamped to (0, MAP_WIDTH) and (0, MAP_HEIGHT)
|
||||
set_camera_view(
|
||||
max(
|
||||
min(
|
||||
GAME_STATE["PLAYER_LOC"][0] - 4,
|
||||
GAME_STATE["MAP_WIDTH"] - SCREEN_WIDTH_TILES,
|
||||
),
|
||||
0,
|
||||
),
|
||||
max(
|
||||
min(
|
||||
GAME_STATE["PLAYER_LOC"][1] - 3,
|
||||
GAME_STATE["MAP_HEIGHT"] - SCREEN_HEIGHT_TILES,
|
||||
),
|
||||
0,
|
||||
),
|
||||
10,
|
||||
8,
|
||||
)
|
||||
# draw the camera
|
||||
draw_camera_view()
|
||||
# if player beat this map
|
||||
if GAME_STATE["STATE"] == STATE_MAPWIN:
|
||||
GAME_STATE["MAP_INDEX"] += 1
|
||||
# if player has beaten all maps
|
||||
if GAME_STATE["MAP_INDEX"] >= len(MAPS):
|
||||
GAME_STATE["MAP_INDEX"] = 0
|
||||
GAME_STATE["STATE"] = STATE_WAITING
|
||||
show_splash(
|
||||
"You Win \n =D \nCongratulations. \nStart Over?", 0x29C1CF
|
||||
)
|
||||
load_map(MAPS[GAME_STATE["MAP_INDEX"]])
|
||||
else:
|
||||
# prompt to start next
|
||||
GAME_STATE["STATE"] = STATE_WAITING
|
||||
show_splash(
|
||||
"You beat this level\n =D \nCongratulations. \nStart Next?",
|
||||
0x29C1CF,
|
||||
)
|
||||
load_map(MAPS[GAME_STATE["MAP_INDEX"]])
|
||||
# game over from sparky
|
||||
elif GAME_STATE["STATE"] == STATE_LOST_SPARKY:
|
||||
GAME_STATE["MAP_INDEX"] = 0
|
||||
GAME_STATE["STATE"] = STATE_WAITING
|
||||
game_over_text = "Be careful not to \ntouch Sparky unless \nyou've collected \nenough Mho's.\nStarting Over"
|
||||
show_splash(game_over_text, 0x25AFBB)
|
||||
load_map(MAPS[GAME_STATE["MAP_INDEX"]])
|
||||
# talking to minerva
|
||||
elif GAME_STATE["STATE"] == STATE_MINERVA:
|
||||
GAME_STATE["STATE"] = STATE_WAITING
|
||||
random_fact = random.choice(FACTS)
|
||||
minerva_txt = wrap_nicely("Minerva: {}".format(random_fact), 23)
|
||||
show_splash(minerva_txt, 0xD39AE5, 10)
|
||||
|
||||
# store the last update time
|
||||
last_update_time = now
|
||||
5
Tilemap_Game_With_CircuitPython/readme.md
Normal file
5
Tilemap_Game_With_CircuitPython/readme.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Creating Your First Tilemap Game With CircuitPython
|
||||
|
||||
Respository for an Example Tilemap Game built with Circuit Python for PyGamer, PyBdage, or Pew Pew M4 Devices.
|
||||
|
||||
Tutorial for this proroject is at [https://learn.adafruit.com/creating-your-first-tilemap-game-with-circuit-python/](https://learn.adafruit.com/creating-your-first-tilemap-game-with-circuit-python/)
|
||||
2
Tilemap_Game_With_CircuitPython/requirements.txt
Normal file
2
Tilemap_Game_With_CircuitPython/requirements.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
adafruit_display_text
|
||||
adafruit_imageload
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
13
Tilemap_Game_With_CircuitPython/tilegame_assets/fun_facts.py
Normal file
13
Tilemap_Game_With_CircuitPython/tilegame_assets/fun_facts.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Fun facts to be read to the player by Minerva
|
||||
FACTS = [
|
||||
"The digitalio module lets you read and write HIGH and LOW values with IO pins.",
|
||||
"JSON stands for Javascript Object Notation. It's a language for storing and transfering data.",
|
||||
"PMW stands for pulse width modulation. The pulsio module lets you use PWM pins.",
|
||||
"REPL stands for Read Evaluate Print Loop. You access it by sending ctrl-C via serial.",
|
||||
"Released in 1979 Namco's arcade game Galaxian was the first tile-based video game.",
|
||||
"Python dictionaries can have keys and values of any type! Even functions.",
|
||||
"Circuitpython was initially released July 19, 2017.",
|
||||
"The displayio module was introducted in Circuipython 4.0. It simplified drawing images and text on screens.",
|
||||
"The adafruit_dotstar and neopixel libraries make it easy control dazzling addressable RGB LEDs.",
|
||||
"You can sense human touch on an IO pin with the touchio module."
|
||||
]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
8
Tilemap_Game_With_CircuitPython/tilegame_assets/map0.csv
Normal file
8
Tilemap_Game_With_CircuitPython/tilegame_assets/map0.csv
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
top_left_wall,top_wall,top_wall,top_right_wall,,,top_left_wall,top_wall,top_wall,top_wall,top_right_wall,,,
|
||||
left_wall,player,floor,floor,top_wall,top_wall,floor,floor,floor,right_wall,right_wall,top_wall,top_wall,top_right_wall
|
||||
left_wall,floor,floor,mho,floor,floor,floor,floor,top_wall,right_wall,minerva,floor,sparky,right_wall
|
||||
left_wall,minerva,floor,floor,heart,floor,floor,left_wall,floor,sparky,floor,floor,floor,right_wall
|
||||
left_wall,top_wall,top_wall,sparky,top_wall,top_wall,top_wall,left_wall,floor,right_wall,floor,floor,floor,right_wall
|
||||
left_wall,floor,floor,mho,floor,floor,floor,floor,floor,right_wall,heart,floor,robot,right_wall
|
||||
left_wall,floor,floor,floor,floor,floor,heart,floor,floor,right_wall,right_wall,bottom_wall,bottom_wall,bottom_right_wall
|
||||
bottom_left_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_right_wall,,,
|
||||
|
17
Tilemap_Game_With_CircuitPython/tilegame_assets/map1.csv
Normal file
17
Tilemap_Game_With_CircuitPython/tilegame_assets/map1.csv
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
top_left_wall,top_wall,top_wall,top_right_wall,floor,floor,top_left_wall,top_wall,top_wall,top_wall,top_right_wall,,,
|
||||
left_wall,mho,floor,floor,top_wall,top_wall,minerva,floor,right_wall,floor,heart,top_wall,top_wall,top_right_wall
|
||||
left_wall,floor,player,floor,floor,left_wall,floor,floor,sparky,floor,floor,floor,floor,right_wall
|
||||
left_wall,floor,floor,floor,floor,sparky,floor,floor,right_wall,mho,floor,floor,floor,right_wall
|
||||
left_wall,floor,floor,floor,floor,left_wall,floor,floor,right_wall,top_wall,top_wall,sparky,top_wall,right_wall
|
||||
left_wall,floor,mho,floor,floor,left_wall,floor,floor,right_wall,floor,floor,floor,floor,right_wall
|
||||
left_wall,floor,floor,floor,floor,left_wall,heart,floor,right_wall,floor,floor,floor,mho,right_wall
|
||||
bottom_left_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,heart,floor,floor,right_wall
|
||||
,top_left_wall,top_wall,top_wall,top_wall,top_wall,top_right_wall,floor,floor,floor,left_wall,floor,floor,right_wall
|
||||
,left_wall,robot,floor,floor,floor,sparky,floor,floor,floor,left_wall,heart,floor,right_wall
|
||||
,left_wall,floor,floor,floor,floor,right_wall,floor,floor,floor,sparky,floor,floor,right_wall
|
||||
,left_wall,floor,floor,minerva,floor,right_wall,floor,heart,floor,left_wall,floor,floor,right_wall
|
||||
,left_wall,floor,floor,floor,floor,right_wall,top_wall,top_wall,top_wall,left_wall,floor,floor,right_wall
|
||||
,left_wall,floor,floor,floor,floor,right_wall,floor,floor,floor,left_wall,floor,mho,right_wall
|
||||
,left_wall,floor,floor,floor,floor,sparky,floor,mho,floor,sparky,floor,minerva,right_wall
|
||||
,left_wall,floor,floor,floor,floor,right_wall,floor,floor,floor,left_wall,floor,floor,right_wall
|
||||
,bottom_left_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_wall,bottom_right_wall
|
||||
|
BIN
Tilemap_Game_With_CircuitPython/tilegame_assets/sprite_sheet.bmp
Normal file
BIN
Tilemap_Game_With_CircuitPython/tilegame_assets/sprite_sheet.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4 KiB |
16
Tilemap_Game_With_CircuitPython/tilegame_assets/states.py
Normal file
16
Tilemap_Game_With_CircuitPython/tilegame_assets/states.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# State machine constants
|
||||
|
||||
# playing the game: draw the map, listen for D-pad buttons to move player
|
||||
STATE_PLAYING = 0
|
||||
|
||||
# player beat this map level
|
||||
STATE_MAPWIN = 1
|
||||
|
||||
# waiting for player to press A button to continue
|
||||
STATE_WAITING = 2
|
||||
|
||||
# player lost by touching sparky
|
||||
STATE_LOST_SPARKY = 3
|
||||
|
||||
# minerva shows a fun fact
|
||||
STATE_MINERVA = 4
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
def wrap_nicely(string, max_chars):
|
||||
""" From: https://www.richa1.com/RichardAlbritton/circuitpython-word-wrap-for-label-text/
|
||||
A helper that will return the string with word-break wrapping.
|
||||
:param str string: The text to be wrapped.
|
||||
:param int max_chars: The maximum number of characters on a line before wrapping.
|
||||
"""
|
||||
string = string.replace('\n', '').replace('\r', '') # strip confusing newlines
|
||||
words = string.split(' ')
|
||||
the_lines = []
|
||||
the_line = ""
|
||||
for w in words:
|
||||
if len(the_line+' '+w) <= max_chars:
|
||||
the_line += ' '+w
|
||||
else:
|
||||
the_lines.append(the_line)
|
||||
the_line = w
|
||||
if the_line:
|
||||
the_lines.append(the_line)
|
||||
the_lines[0] = the_lines[0][1:]
|
||||
the_newline = ""
|
||||
for w in the_lines:
|
||||
the_newline += '\n'+w
|
||||
return the_newline
|
||||
132
Tilemap_Game_With_CircuitPython/tilegame_assets/tiles.py
Normal file
132
Tilemap_Game_With_CircuitPython/tilegame_assets/tiles.py
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
from tilegame_assets.states import *
|
||||
|
||||
|
||||
# Minerva before_move. Set game state to STATE_MINERVA
|
||||
def minerva_walk(to_coords, from_coords, entity_obj, GAME_STATE):
|
||||
GAME_STATE['STATE'] = STATE_MINERVA
|
||||
return False
|
||||
|
||||
|
||||
# Sparky before_move. If user does not have a Mho in inventory they lose.
|
||||
# If user does have Mho subtract one from inventory and consume Sparky.
|
||||
def sparky_walk(to_coords, from_coords, entity_obj, GAME_STATE):
|
||||
if GAME_STATE['INVENTORY'].count("mho") > 0:
|
||||
GAME_STATE['INVENTORY'].remove("mho")
|
||||
GAME_STATE['ENTITY_SPRITES_DICT'][to_coords].remove(entity_obj)
|
||||
if len(GAME_STATE['ENTITY_SPRITES_DICT'][to_coords]) == 0:
|
||||
del GAME_STATE['ENTITY_SPRITES_DICT'][to_coords]
|
||||
if (-1, -1) in GAME_STATE['ENTITY_SPRITES_DICT']:
|
||||
GAME_STATE['ENTITY_SPRITES_DICT'][-1, -1].append(entity_obj)
|
||||
else:
|
||||
GAME_STATE['ENTITY_SPRITES_DICT'][-1, -1] = [entity_obj]
|
||||
return True
|
||||
else:
|
||||
GAME_STATE['STATE'] = STATE_LOST_SPARKY
|
||||
return True
|
||||
|
||||
|
||||
# Robot before_move. If user has all Hearts they win the map.
|
||||
def robot_walk(to_coords, from_coords, entity_obj, GAME_STATE):
|
||||
if GAME_STATE['INVENTORY'].count("heart") == GAME_STATE['TOTAL_HEARTS']:
|
||||
GAME_STATE["STATE"] = STATE_MAPWIN
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Remove the item from this location and add it to player inventory.
|
||||
def take_item(to_coords, from_coords, entity_obj, GAME_STATE):
|
||||
print(entity_obj)
|
||||
GAME_STATE['INVENTORY'].append(entity_obj["map_tile_name"])
|
||||
GAME_STATE['ENTITY_SPRITES_DICT'][to_coords].remove(entity_obj)
|
||||
if len(GAME_STATE['ENTITY_SPRITES_DICT'][to_coords]) == 0:
|
||||
del GAME_STATE['ENTITY_SPRITES_DICT'][to_coords]
|
||||
|
||||
if (-1, -1) in GAME_STATE['ENTITY_SPRITES_DICT']:
|
||||
GAME_STATE['ENTITY_SPRITES_DICT'][-1, -1].append(entity_obj)
|
||||
else:
|
||||
GAME_STATE['ENTITY_SPRITES_DICT'][-1, -1] = [entity_obj]
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# main dictionary that maps tile type strings to objects.
|
||||
# each one stores the sprite_sheet index and any necessary
|
||||
# behavioral stats like can_walk or before_move
|
||||
TILES = {
|
||||
# empty strings default to floor and no walk.
|
||||
"": {
|
||||
"sprite_index": 10,
|
||||
"can_walk": False
|
||||
},
|
||||
"floor": {
|
||||
"sprite_index": 10,
|
||||
"can_walk": True
|
||||
},
|
||||
"top_wall": {
|
||||
"sprite_index": 7,
|
||||
"can_walk": False
|
||||
},
|
||||
"top_right_wall": {
|
||||
"sprite_index": 8,
|
||||
"can_walk": False
|
||||
},
|
||||
"top_left_wall": {
|
||||
"sprite_index": 6,
|
||||
"can_walk": False
|
||||
},
|
||||
"bottom_right_wall": {
|
||||
"sprite_index": 14,
|
||||
"can_walk": False
|
||||
},
|
||||
"bottom_left_wall": {
|
||||
"sprite_index": 12,
|
||||
"can_walk": False
|
||||
},
|
||||
"right_wall": {
|
||||
"sprite_index": 11,
|
||||
"can_walk": False
|
||||
},
|
||||
"left_wall": {
|
||||
"sprite_index": 9,
|
||||
"can_walk": False
|
||||
},
|
||||
"bottom_wall": {
|
||||
"sprite_index": 13,
|
||||
"can_walk": False
|
||||
},
|
||||
"robot": {
|
||||
"sprite_index": 1,
|
||||
"can_walk": True,
|
||||
"entity": True,
|
||||
"before_move": robot_walk
|
||||
},
|
||||
"heart": {
|
||||
"sprite_index": 5,
|
||||
"can_walk": True,
|
||||
"entity": True,
|
||||
"before_move": take_item
|
||||
},
|
||||
"mho": {
|
||||
"sprite_index": 2,
|
||||
"can_walk": True,
|
||||
"entity": True,
|
||||
"before_move": take_item
|
||||
},
|
||||
"sparky": {
|
||||
"sprite_index": 4,
|
||||
"can_walk": True,
|
||||
"entity": True,
|
||||
"before_move": sparky_walk
|
||||
},
|
||||
"minerva": {
|
||||
"sprite_index": 3,
|
||||
"can_walk": True,
|
||||
"entity": True,
|
||||
"before_move": minerva_walk
|
||||
},
|
||||
"player": {
|
||||
"sprite_index": 0,
|
||||
"entity": True,
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue