0

そのため、あるクラスから別のクラスに変数を渡そうとしています。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()
4

2 に答える 2

2

クラスの継承に Python の構文を使用しています。継承は'is a'Sidescroller関係、やのような仮想クラスに使用されFPSます。これらはゲームの一種であるためです。

Mapはゲームの一種ではなく、ゲーム内の何かなので、Game' has a'関係があります。スプライトやサウンドと同様に、ゲームにはマップがあります。「has a」関係に特別な構文はありません。親クラスは、子クラスのインスタンスを作成するだけです。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()
于 2012-12-21T03:13:09.157 に答える
1

基本クラスとしてMap使用するには、代わりにを使用して定義する必要があります。Gameclass 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実行されると、 が 2 回呼び出されることがわかりますGame.__init__()。1 つ目は でGame作成されたインスタンスの場合でGame()、次に起こることは少し奇妙です。作成されたばかりのインスタンスは の基本クラスとして使用されるMapため、その メソッドは の 3 つの引数バージョン(名前、基本クラス、および辞書) と__init__()同じ引数を使用して呼び出されます。type()

Game.__init__()これが、表示される奇妙なエラーが発生する理由であり、 where wis the string'Map'およびis a Dictionaryへの呼び出しが発生し、文字列を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'
于 2012-12-20T22:49:54.913 に答える