[Tutor] Issue With a Python Game
John Bochicchio
luckytsukune at gmail.com
Sat Apr 13 15:13:07 CEST 2013
I have a question about a game I am making. I finished the overall code,
but keep getting errors when I try to play. This is my most common error:
C:\Users\John\Documents\Python Games\Noah>python nickeladventuredemo.py
Traceback (most recent call last):
File "nickeladventuredemo.py", line 451, in <module>
main()
File "nickeladventuredemo.py", line 78, in main
levels = readLevelsFile('levels.txt')
File "nickeladventuredemo.py", line 371, in readLevelsFile
assert startx != None and starty!= None, 'Level %s (around line %s) in
%s i
s missing a "@" or "+" to mark the start point.' % (levelNum+1, lineNum,
filenam
e)
AssertionError: Level 1 (around line 10) in levels.txt is missing a "@" or
"+" t
o mark the start point.
The Code:
import random, sys, copy, os, pygame
from pygame.locals import *
FPS = 30
WINWIDTH = 800
WINHEIGHT = 600
HALF_WINWIDTH = int(WINWIDTH / 2)
HALF_WINHEIGHT = int(WINHEIGHT / 2)
TILEWIDTH = 50
TILEHEIGHT = 85
TILEFLOORHEIGHT = 45
CAM_MOVE_SPEED = 5
OUTSIDE_DECORATION_PCT = 20
BRIGHTBLUE = ( 0, 170, 255)
WHITE = (255, 255, 255)
BGCOLOR = BRIGHTBLUE
TEXTCOLOR = WHITE
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
def main():
global FPSCLOCK, DISPLAYSURF, IMAGESDICT, TILEMAPPING,
OUTSIDECOMAPPING, BASICFONT, PLAYERIMAGES, currentImage
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINWIDTH, WINHEIGHT))
pygame.display.set_caption('Noah Nickel Adventure!')
BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
IMAGESDICT = {'uncovered goal': pygame.image.load('RedSelector.png'),
'covered goal': pygame.image.load('Selector.png'),
'star': pygame.image.load('Star.png'),
'corner': pygame.image.load('Wall Block Tall.png'),
'wall': pygame.image.load('Wood Block Tall.png'),
'inside floor': pygame.image.load('Plain Block.png'),
'outside floor': pygame.image.load('Grass Block.png'),
'title': pygame.image.load('star_title.png'),
'solved': pygame.image.load('star_solved.png'),
'princess': pygame.image.load('princess.png'),
'boy': pygame.image.load('boy.png'),
'catgirl': pygame.image.load('catgirl.png'),
'horngirl': pygame.image.load('horngirl.png'),
'pinkgirl': pygame.image.load('pinkgirl.png'),
'rock': pygame.image.load('Rock.png'),
'short tree': pygame.image.load('Tree_Short.png'),
'tall tree': pygame.image.load('Tree_Tall.png'),
'ugly tree': pygame.image.load('Tree_Ugly.png')}
TILEMAPPING = {'X': IMAGESDICT['corner'],
'#': IMAGESDICT['wall'],
'o': IMAGESDICT['inside floor'],
' ': IMAGESDICT['outside floor']}
OUTSIDECOMAPPING = {'1': IMAGESDICT['rock'],
'2': IMAGESDICT['short tree'],
'3': IMAGESDICT['tall tree'],
'4': IMAGESDICT['ugly tree']}
#Super important to remember:
#DEAR GOD REMEMBER THIS IS AN INDEX OF PLAYER IMAGES.
currentImage = 0
PLAYERIMAGES = [IMAGESDICT['princess'],
IMAGESDICT['boy'],
IMAGESDICT['catgirl'],
IMAGESDICT['horngirl'],
IMAGESDICT['pinkgirl']]
startScreen()
levels = readLevelsFile('levels.txt')
currentLevelIndex = 0
while True:
result = runLevel(levels, currentLevelIndex)
if result in ('solved', 'next'):
currentLevelIndex += 1
if currentLevelIndex >= len(levels):
currentLevelIndex = 0
elif result == 'back':
currentLevelIndex -= 1
if currentLevelIndex <0:
currentLevelIndex = len(levels)-1
elif result == 'reset':
pass
def runLevel(levels, levelNum):
global currentImage
level0bj = levels[levelnum]
map0bj = decorateMap(level0bj['map0bj'],
level0bj['startState']['player'])
gameState0bj = copy.deepcopy(level0bj['startState'])
mapNeedsRedraw = True
levelSurf = BASICFONT.render('Level %s of %s' % (level0bj['levelNum']
+1, totalNumOfLevels), 1, TEXTCOLOR)
levelRect = levelSurf.get_rect()
levelRect.bottomleft = (20, WINHEIGHT - 35)
mapWidth = len(map0bj) * TITLEWIDTH
mapHeight = (len(map0bj[0]) - 1) * (TITLEHEIGHT - TILEFLOORHEIGHT) +
TILEHEIGHT
MAX_CAM_X_PAN = abs(HALF_WINHEIGHT - int(mapHeight / 2)) + TILEWIDTH
MAX_CAM_Y_PAN = abs(HALF_WINWIDTH - int(mapWidth / 2)) + TILEHEIGHT
levelIsComplete = False
camera0ffsetX = 0
camera0ffsety = 0
cameraUp = False
cameraDown = False
cameraLeft = False
cameraRight = False
while True:
playerMoveTo = None
kepPressed = False
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
keyPressed == True
if event.key == K_LEFT:
playerMoveTo = LEFT
elif event.key == K_RIGHT:
playerMoveTo = RIGHT
elif event.key == K_UP:
playerMoveTo = UP
elif event.key == K_DOWN:
playerMoveTo = DOWN
elif event.key == K_a:
cameraLeft = True
elif event.key == K_d:
cameraRight = True
elif event.key == K_w:
cameraUp = True
elif event.key == K_s:
cameraDown = True
elif event.key == K_n:
return 'next'
elif event.key == K_b:
return 'back'
elif event.key == K_ESCAPE:
terminate() #Perhaps add a print box confirmation?
elif event.key == K_BACKSPACE:
return 'reset' #Same confirmation for level reset.
elif event.key == K_p:
currentImage += 1
if currentImage >= len(PLAYERIMAGES):
currentImage = 0
mapNeedsRedraw = True
elif event.type == KEYUP:
if event.key == K_a:
cameraLeft = False
elif event.key == K_d:
cameraRight = False
elif event.key == K_w:
cameraUp = False
elif event.key == K_s:
cameraDown = False
if playerMoveTo != None and not levelIsComplete:
moved = makeMove(map0bj, gameState0bj, playerMoveTo)
if moved:
gameState0bj['stepCounter'] += 1
mapNeedsRedraw = True
if isLevelFinished(level0bj, gameState0bj):
levelIsComplete = True
keyPressed = False
DISPLAYSURF.fill(BGCOLOR)
if mapNeedsRedraw:
mapSurf = drawMap(map0bj, gameState0bj,
level0bj['goals'])
mapNeedsRedraw = False
if cameraUp and camera0ffsetY < MAX_CAM_X_PAN:
camera0ffsetY += CAM_MOVE_SPEED
elif cameraDown and camera0ffsetY > -MAX_CAM_X_PAN:
camera0ffsetY -= CAM_MOVE_SPEED
if cameraLeft and camera0ffsetX < MAX_CAM_Y_PAN:
camera0ffsetX += CAM_MOVE_SPEED
elif cameraRight and camera0ffsetX > -MAX_CAM_Y_PAN:
camera0ffsetX -= CAM_MOVE_SPEED
mapSurfRect = mapSurf.get_rect()
mapSurfRect.center = (HALF_WINWIDTH + camera0ffsetX,
HALF_WINHEIGHT + camera0ffsetY)
DISPLAYSURF.blit(mapSurf, levelRect)
stepSurf = BASICFONT.render('Steps: %s'
%(gameState0bj['stepCounter']), 1, TEXTCOLOR)
stepRect = stepSurf.get_rect()
stepRect.bottomleft = (20, WINHEIGHT -10)
DISPLAYSURF.blit(stepSurf, stepRect)
if levelIsComplete:
solvedRect = IMAGESDICT['solved'].get_rect()
dolvedRect.center = (HALF_WINWIDTH, HALF_WINHEIGHT)
DISPLAYSURF.blit(IMAGESDICT['solved'], solvedRect)
if keyPressed:
return 'solved'
pygame.display.update()
FPSCLOCK.tick()
def decorateMap(map0bj, startxy):
startx, starty = startxy
map0bjCopy = copy.deepcopy(map0bj)
for x in range(len(map0bjCopy)):
for y in range(len(map0bjCopy[0])):
if map0bjCopy[x][y] in ('$', '.', '@', '+', '*'):
map0bjCopy[x][y] = ' '
floodFill(map0bjCopy, startx, starty, ' ', 'o')
for x in range(len(map0bjCopy)):
for y in range(len(map0bjCopy[0])):
if (isWall(mapObjCopy, x, y-1) and isWall(mapObjCopy, x+1, y))
or \
(isWall(mapObjCopy, x+1, y) and isWall(mapObjCopy, x, y+1))
or \
(isWall(mapObjCopy, x, y+1) and isWall(mapObjCopy, x-1, y))
or \
(isWall(mapObjCopy, x-1, y) and isWall(mapObjCopy, x, y-1)):
map0bjCopy[x][y] = 'x'
elif map0bjCopy[x][y] == ' ' and random.randint(0, 99) <
OUTSIDE_DECORATION_PCT:
map0bjCopy[x][y] =
random.choice(list(OUTSIDECOMAPPING.keys()))
return map0bjCopy
def isBlocked(map0bj, gameState0bj, x, y):
if isWall(map0bj, x, y):
return True
elif x < 0 or x >= len(map0bj) or y < 0 or y >= len(map0bj[x]):
return True
return False
def makeMove(map0bj, gameState0bj, playerMoveTo):
playerx, playery = gameState0bj['player']
stars = gameState0bj['stars']
if playerMoveTo == UP:
x0ffset = 0
y0ffset = -1
elif playerMoveTo == RIGHT:
x0ffset = 1
y0ffset = 0
elif playerMoveTo == DOWN:
x0ffset = 0
y0ffset = 1
elif playerMoveTo == LEFT:
x0ffset = -1
y0ffset = 0
if isWall(map0bj, playerx, x0ffset, playery + y0ffset):
return False
else:
if (playerx + x0ffset, playery + y0ffset) in stars:
if not isBlocked(map0bj, gameState0bj, playerx + (x0ffset*2),
playery + (y0ffset*2)):
ind = stars.index((playerx + x0ffset, playery + y0ffset))
stars[ind] = (stars[ind][0] + x0ffset, stars[ind][1] +
y0ffset)
else:
return False
gameState0bj['player'] = (playerx + x0ffset, playery + y0ffset)
return True
def startScreen():
titleRect = IMAGESDICT['title'].get_rect()
topCoord = 50
titleRect.top = topCoord
titleRect.centerx = HALF_WINWIDTH
topCoord += titleRect.height
instructionText = ['Push the stars over the marks.',
'Arrow keys move the player, WASD controls the
camera, and P changes the characer.',
'Backspaced resets the level, Escape quits the
game.',
'N for next level, B to go back a level.']
DISPLAYSURF.fill(BGCOLOR)
DISPLAYSURF.blit(IMAGESDICT['title'], titleRect)
for i in range(len(instructionText)):
instSurf = BASICFONT.render(instructionText[i], 1, TEXTCOLOR)
instRect = instSurf.get_rect()
topCoord += 10
instRect.top = topCoord
instRect.centerx = HALF_WINWIDTH
topCoord += instRect.height
DISPLAYSURF.blit(instSurf, instRect)
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if event.key ==K_ESCAPE:
terminate()
return
pygame.display.update()
FPSCLOCK.tick()
def readLevelsFile(filename):
assert os.path.exists(filename), 'Cannot find the level file: %s' %
(filename)
mapFile = open(filename, 'r')
content = mapFile.readlines() + ['\r\n']
mapFile.close()
levels = []
levelNum = 0
mapTextLines = []
map0bj = []
for lineNum in range (len(content)):
line = content[lineNum].rstrip('\r\n')
if ';' in line:
line = line[:line.find(';')]
if line != '':
mapTextLines.append(line)
elif line == '' and len(mapTextLines) > 0:
maxWidth = -1
for i in range(len(mapTextLines)):
if len(mapTextLines[i]) > maxWidth:
maxWidth = len(mapTextLines[i])
for i in range(len(mapTextLines)):
mapTextLines[i] += ' ' * (maxWidth - len(mapTextLines[i]))
for x in range(len(mapTextLines[0])):
map0bj.append([])
for y in range(len(mapTextLines)):
for x in range(maxWidth):
map0bj[x].append(mapTextLines[y][x])
startx = None
starty = None
goals = []
stars = []
for x in range(maxWidth):
for y in range (len(map0bj[x])):
if map0bj[x][y] in ('@', '+'):
startx = x
starty = y
if map0bj [x][y] in ('.', '+', '*'):
goals.append((x, y))
assert startx != None and starty!= None, 'Level %s (around
line %s) in %s is missing a "@" or "+" to mark the start point.' %
(levelNum+1, lineNum, filename)
assert len(goals) > 0, 'Level %s (around line %s) in %s
must have at least one goal.' % (levelNum+1, lineNum, filename)
assert len(stars) >= len(goals), 'Level %s (around line %s)
in %s is impossible to solve. It has %s goals but only %s stars.' %
(levelNum+1, lineNum, filename, len(goals), len(stars))
gameState0bj = {'player': (startx, starty),
'stepCounter': 0,
'stars': stars}
level0bj = {'width': maxWidth,
'height': len(map0bj),
'map0bj': map0bj,
'goals': goals,
'startState': gameState0bj}
levels.append(level0bj)
mapTextLines = []
map0bj = []
gameState0bj = {}
levelNum += 1
return levels
def floodFill(map0bj, x, y, oldCharacter, newCharacter):
if map0bj[x][y] == oldCharacter:
map0bj[x][y] = newCharacter
if x < len(map0bj) - 1 and map0bj[x+1][y] == oldCharacter:
floodFill(map0bj, x+1, y, oldCharacter, newCharacter)
if x > 0 and map0bj[x-1][y] == oldCharacter:
floodFill(mapObj, x-1, y, oldCharacter, newCharacter)
if y < len(mapObj[x]) - 1 and mapObj[x][y+1] == oldCharacter:
floodFill(mapObj, x, y+1, oldCharacter, newCharacter)
if y > 0 and mapObj[x][y-1] == oldCharacter:
floodFill(mapObj, x, y-1, oldCharacter, newCharacter)
def drawMap(map0bj, gamestate0bj, goals):
mapSurfWidth = len(map0bj) * TILEWIDTH
mapSurfHeight = len(len(map0bj[0]) - 1) * (TILEHEIGHT -
TILEFLOORHEIGHT) + TILEHEIGHT
mapSurf = pygame.Surface((mapSurfWidth, mapSurfHeight))
mapSurf.fill(BGCOLOR)
for x in range(len(map0bj)):
for y in range(len(map0bj)):
spaceRect = pygame.Rect((x * TILEWIDTH, y * (TILEHEIGHT -
TILEFLOORHEIGHT), TILEWIDTH, TILEHEIGHT))
if map0bj[x][y] in TILEMAPPING:
baseTile = TILEMAPPING[map0bj[x][y]]
elif map0bj[x][y] in OUTSIDECOMAPPING:
baseTile = TILEMAPPING[' ']
mapSurf.blit(baseTile, spaceRect)
if map0bj[x][y] in OUTSIDECOMAPPING:
mapSurf.blit(OUTSIDEDECOMAPPING[map0bj[x][y]], spaceRect)
elif (x, y) in gameState0bj['stars']:
if (x, y) in goals:
mapSurf.blit(IMAGESDICT['covered goal'], spaceRect)
mapSurf.blit(IMAGESDICT['star'], spaceRect)
elif (x, y) in goals:
mapSurf.blit(IMAGESDICT['uncovered goal'], spaceRect)
if (x, y) == gameState0bj['player']:
mapSurf.blit(PLAYERIMAGES[currentImage], spaceRect)
return mapSurf
def isLevelFinished(level0bj, gameState0bj):
for goal in level0bj['goals']:
if goal not in gameState0bj['stars']:
return False
return True
def terminate():
pygame.quit()
sys.exit()
if __name__ == '__main__':
main()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20130413/e8c4b2be/attachment-0001.html>
More information about the Tutor
mailing list