所以我试图将vars从一个类传递到另一个类。我希望Map类从Game类接收变量。当我运行它时,我收到一个错误:
self.width = w*self.multi TypeError: Error when calling the metaclass bases can't multiply sequence by non-int of type 'dict'
我该如何解决这个问题,或者我应该以不同的方式解决这个问题?
import pygame, os
from pygame.locals import *
from pygame import Color
from time import time
from datetime import datetime
class Game():
""" Lets try to get this going by simple steps
One by one. First step, lets figure how to make a class
that can do the display stuff. NOTE TO SELF: Remember, these
are only called ONCE at the start. Lord have mercy on my soul"""
def __init__(self, w=256, h=224, multi=3):
"""Initialization"""
pygame.init()
self.multi = multi
self.runGame = True
self.width = w*self.multi
self.height = h*self.multi
self.sprSz = 16*self.multi
self.clock = pygame.time.Clock()
self.screen = pygame.display.set_mode((self.width, self.height))
self.kl = []
self.walk = [0, 0]
self.speed = self.multi*1.5
self.x,self.y = (self.width/2-(self.sprSz/2)), (self.height/2-(self.sprSz/2))
self.music = self.sndLoad('relent.ogg')
self.playerSpr = self.imgLoad('link1.png', self.multi, 0, 0)
self.playerRec = Rect(self.x,self.y,self.sprSz,self.sprSz)
self.aSprite = self.imgLoad('greenwall_01.png', self.multi, 0, 0)
self.aSpriteRec = Rect(self.aSprite.get_rect())
def imgLoad(self, image, size, flipx, flipy):
try:
self.img=pygame.image.load('images/'+image).convert_alpha()
except pygame.error, message:
print "Unable to load image: " + image
raise SystemExit, message
if size>1:
self.img=pygame.transform.scale(self.img, (self.img.get_width()*size, self.img.get_height()*size))
if flipx==1:
self.img=pygame.transform.flip(self.img, True, False)
if flipy==1:
self.img=pygame.transform.flip(self.img, False, True)
if flipy>1 or flipy<0:
self.img=pygame.transform.rotate(self.img, flipy)
return self.img
def sndLoad(self, sound):
try:
self.sound = pygame.mixer.Sound('sounds/'+sound)
except pygame.error, message:
print "Cannot load sound: " + sound
raise SystemExit, message
return self.sound
def mainLoop(self):
"""Loop through the main game routines
1. Drawing 2. Input handling 3. Updating
Then loop through it until user quits"""
self.music.play()
self.music.set_volume(0.01)
while self.runGame:
self.clock.tick(160)
self.events()
self.draw()
def events(self):
"""Time to handle some events"""
for e in pygame.event.get():
if (e.type == pygame.QUIT) or (e.type == KEYDOWN and e.key == K_ESCAPE):
self.runGame = False
break
if e.type == KEYDOWN and e.key == K_PRINT:
self.screenShot()
if e.type==KEYDOWN:
if e.key==pygame.K_a: self.kl.append(1)
if e.key==pygame.K_d: self.kl.append(2)
if e.key==pygame.K_w: self.kl.append(3)
if e.key==pygame.K_s: self.kl.append(4)
if e.type==pygame.KEYUP:
if e.key==pygame.K_a: self.kl.remove(1)
if e.key==pygame.K_d: self.kl.remove(2)
if e.key==pygame.K_w: self.kl.remove(3)
if e.key==pygame.K_s: self.kl.remove(4)
if self.kl[-1:]==[1]: self.walk=[-self.speed, 0]
elif self.kl[-1:]==[2]: self.walk=[ self.speed, 0]
elif self.kl[-1:]==[3]: self.walk=[0,-self.speed]
elif self.kl[-1:]==[4]: self.walk=[0, self.speed]
else: self.walk=[0, 0]
self.playerRec.move_ip(*self.walk) # instead of self.x+=self.walk[0] / self.y+=self.walk[1]
self.playerRec.clamp_ip(self.screen.get_rect()) # probably do this right after 'move_ip'
def screenShot(self):
"""Lets make a folder if it doesnt exist for screenshots
Then lets name teh screenshot something useful and unique"""
if not os.path.exists('screenshots'):
os.makedirs('screenshots')
t = datetime.now()
pygame.image.save(self.screen, ('screenshots/'+str(t.strftime("%a-%d-%b-%Y-%H.%M.%S_%f"))+'.png'))
def idk(self):
pygame.sprite.collide_rect(left, right)
def draw(self):
"""Draw and update the main screen. Sacrifice virgins to the
unholy prankster god of programming and cross fingers"""
pygame.display.set_caption('Grid2. FPS: '+str(round(self.clock.get_fps(), 1)))
back = self.screen.fill(Color('darkblue'))
map.drawMapArray(map.readMap('kk.txt'))
link = self.screen.blit(self.playerSpr, self.playerRec) # 'blit' accepts a 'Rect' as second parameter
bush = self.screen.blit(self.aSprite, self.aSpriteRec)
d = link.colliderect(bush)
print d
pygame.display.update()
class Map(Game()):
"""What we need to do here is go out and open a map file.
Read the file, and for each charactor load it onto the surface
in the right x/y coords. Should be easy. lulz"""
def __init__(self, md='maps/'):
self.md = md
self.tiles = []
#self.sprSz = game.sprSz
#self.multi = game.multi
#self.screen = game.screen
def readMap(self, mapfile):
"""Lets open that map file up in a semi elegant way. Let
us code cleanly and improve on simple things. """
try:
self.mpath = os.path.join(self.md, mapfile)
self.map = open(self.mpath, 'r')
except IOError, message:
print "Unable to Map: " + self.md+mapfile
raise SystemExit, message
self.lines = self.map.readlines()
self.Ty = len(self.lines)
self.Tx = len(self.lines[0])-1
self.map.close()
for c in range(self.Ty):
self.tiles.append([])
for r in range(self.Tx):
self.tiles[c].append(self.lines[c][r])
return self.tiles
def drawMapArray(self, map):
for x in range(0, self.Tx):
for y in range(0, self.Ty):
#Determines tile type.
curTile=tile_d[map[y][x]][3]
#print x,y
#print map
#print curTile
#if tile_d[self.readMap[y][x]][2]>-1:
#game.screen.blit(curTile, (x*game.sprSz, y*game.sprSz+game.multi*56), (tile_d[self.readMap[y][x]][2]*resmulti*16, 0, 16*resmulti, 16*resmulti))
#else:
e = self.screen.blit(curTile, (x*self.sprSz, y*self.sprSz+self.multi*56))
#print e
if __name__ == "__main__":
game = Game()
map = Map()
tile_d={
'#' : ('Link', True, 0, game.imgLoad("link1.png", game.multi, 0, 0)),
' ' : ('Link', True, 0, game.imgLoad("empty.png", game.multi, 0, 0)),
'Q' : ('Link', True, 0, game.imgLoad("link1.png", game.multi, 0, 0)),
'R' : ('Link', True, 0, game.imgLoad("empty.png", game.multi, 0, 0)),
'W' : ('Link', True, 0, game.imgLoad("link1.png", game.multi, 0, 0)),
'E' : ('Link', True, 0, game.imgLoad("empty.png", game.multi, 0, 0)),
'R' : ('Link', True, 0, game.imgLoad("link1.png", game.multi, 0, 0)),
'B' : ('Link', True, 0, game.imgLoad("empty.png", game.multi, 0, 0)),
'T' : ('Link', True, 0, game.imgLoad("link1.png", game.multi, 0, 0)),
'Y' : ('Link', True, 0, game.imgLoad("empty.png", game.multi, 0, 0)),
}
game.mainLoop()
答案 0 :(得分:2)
您正在使用Python的语法进行类继承。继承用于'是'关系,假设类如Sidescroller
或FPS
,因为它们是游戏类型。
Map
不是一种游戏,它是游戏中的某种东西,因此Game
和Map
的'具有'关系。你的游戏有一张地图,就像有精灵和声音一样。 '具有'关系没有特殊语法。父类只是创建子类的实例。
由于您希望访问Game
的变量,因此在声明地图时可以将其原始实例传递给Map
。如果您在Map
内声明Game
,则可以使用self
传递游戏实例。这是一个例子:
# print the game's title via the Map class
class Game:
def __init__(self):
self.title = "Robot Ninja Spaceman: Lazer Quest"
self.map = Map(self)
class Map:
def __init__(self, game):
print game.title
if __name__ == "__main__":
game = Game()
答案 1 :(得分:1)
要让Map
使用Game
作为基类,您应该使用class Map(Game)
而不是class Map(Game())
来定义它。
以下是尝试使用Game
实例作为基类时会发生什么的简短示例:
>>> class Game():
... def __init__(*args):
... print args
...
>>> class Map(Game()):
... pass
...
(<__main__.Game instance at 0x7fa41d06f320>,)
(<__main__.Game instance at 0x7fa41d0549e0>, 'Map', (<__main__.Game instance at 0x7fa41d06f320>,), {'__module__': '__main__'})
因此,我们看到当Map
的类定义运行时,我们会调用Game.__init__()
两次。第一个是用Game
创建的Game()
实例,接下来发生的事情有点奇怪。刚刚创建的实例用作Map
的基类,因此使用与{{3}的三个参数版本相同的参数调用其 __init__()
方法(名称,基类和字典)。
这就是为什么你最终会遇到这个奇怪的错误,最后打电话给Game.__init__()
,其中w
是字符串'Map'
而multi
是字典,并尝试将字符串乘以字典会导致TypeError:
>>> self.multi = 'Map' * {}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'dict'