Example #1
0
 def __loadLevel(self):
     self.mChunkHandler = ChunkHandler(self.mWorld, self.CHUNK_SIZE)
     self.__readLevel()
     
     if self.mMapType == MapType.PICTURE:
         self.__createPictureWorldCollision()
         print "startpos: ", self.mStartPos
         self.mChunkHandler.activateChunk(self.mChunkHandler.getChunk(self.mChunkHandler.getChunkPosition(self.mStartPos)))
         self.mTiles = self.mChunkHandler.mActiveTiles
     else:
         self.__createTextWorldCollision()
     self.__createPickups()
     self.__createEnemies()
     self.__createBoxes()
Example #2
0
class Level(object):
    
    CHUNK_SIZE = 8
    mMaxLevels = None
    mCurrentLevel = None
    mTiles = None
    mMap = None
    mWidth = None
    mHeight = None
    mStartPos = None
    mEndPos = None
    mEnemies = None
    mObjects = None
    mLevelDone = None
    mChunkHandler = None
    mMapType = None
    mCurrentTileset = None
    mSwirlActive = None
    mAllTiles = None
    
    #dataholders
    mPickupData = None
    mEnemyData = None
    mBoxData = None
    
    #crypt/decrypt
    __mCrypt = None
    
    def __init__(self, world, gravity, lvl):
        self.__mCrypt = Crypt()
        self.mMaxLevels = self.countLevels()
        self.mSwirlActive = False
        self.mLevelDone = False
        self.mTiles = []
        self.mObjects = []
        self.mEnemies = []
        self.mWorld = world
        self.mGravity = gravity
        self.mCurrentLevel = lvl
        self.mAllTiles = []
        
        self.__loadLevel()
        
    def __loadLevel(self):
        self.mChunkHandler = ChunkHandler(self.mWorld, self.CHUNK_SIZE)
        self.__readLevel()
        
        if self.mMapType == MapType.PICTURE:
            self.__createPictureWorldCollision()
            print "startpos: ", self.mStartPos
            self.mChunkHandler.activateChunk(self.mChunkHandler.getChunk(self.mChunkHandler.getChunkPosition(self.mStartPos)))
            self.mTiles = self.mChunkHandler.mActiveTiles
        else:
            self.__createTextWorldCollision()
        self.__createPickups()
        self.__createEnemies()
        self.__createBoxes()
        
    """ 
        Reads in enemies, pickups and if there's not a picture specified, worldcollision
        http://qq.readthedocs.org/en/latest/tiles.html#map-definition
    """
    def __readLevel(self):
        parser = self.__mCrypt.dectryptParser(self.mCurrentLevel)  
        self.mCurrentTileset = parser.get("level", "tileset")
        self.mBackground = parser.get("level", "bg")
        bgcolor = pygame.image.load("assets/gfx/%s" % self.mBackground)
        self.mBackgroundcolor = bgcolor.get_at((0, 0))
        self.mPickupData = parser.get("objects", "pickups")
        self.mEnemyData = parser.get("objects", "enemies")
        self.mBoxData = parser.get("objects", "boxes")
        
        #Mapcollision
        #check for pictures first
        if os.path.exists("assets/Levels/level%d.png" % self.mCurrentLevel):
            self.mMap = pygame.image.load("assets/levels/level%d.png" % self.mCurrentLevel)
            self.mWidth, self.mHeight = self.mMap.get_size()
            self.mMapType = MapType.PICTURE
        else: #check for lvl-file
            self.mMap = parser.get("level", "map").replace(" ", "").split("\n")
            self.mWidth = len(self.mMap[0])
            self.mHeight = len(self.mMap)
            self.mMapType = MapType.TEXT
    
    def __unloadCurrentLevel(self):
        self.mEndPos = None
        self.mStartPos = None
        self.mSwirlActive = False
        self.__unloadEntities()
        for tile in self.mTiles:
            tile.destroy()
        
        self.mTiles = []
            
    def __unloadEntities(self):
        for obj in self.mObjects:
            if obj.alive:
                self.mWorld.DestroyBody(obj.getBody())
        
        for e in self.mEnemies:
            self.mWorld.DestroyBody(e.getBody())
        
        self.mObjects = []
        self.mEnemies = []
    
    
    def update(self, delta, playerpos):
        if self.mMapType == MapType.PICTURE:
            self.mChunkHandler.manageChunks(playerpos)
          
        if not self.mLevelDone:
            self.checkLevelCompletion(playerpos)    
        else:
            self.mLevelDone = False
            return True
        
    
    def checkLevelCompletion(self, pos):
        done = True
        for o in self.mObjects:
            if isinstance(o, Crystal):
                if o.alive:
                    done = False
                    break
        
        if done:
            self.mSwirlActive = True
        
            if (pos.x > self.mEndPos.x and pos.x < self.mEndPos.x + Tile.TILE_SIZE and 
                pos.y > self.mEndPos.y and pos.y < self.mEndPos.y + Tile.TILE_SIZE):    
                    self.__updateLevelLockState()            
                    self.mLevelDone = True
    
    #updates the statefile if a level is cleared                  
    def __updateLevelLockState(self):
        with open("assets/state/state.json", "rb") as state:
            decryptedData = self.__mCrypt.decrypt(state.read())
            lvldata = json.loads(decryptedData)
        
        if int(lvldata["LVL"]) <= self.mCurrentLevel:
            with open("assets/state/state.json", "wb") as data:
                lvl = min(self.mCurrentLevel+1, self.mMaxLevels)
                data.write(self.__mCrypt.encrypt('{"LVL":"%s"}' % (str(lvl))))
    
    #create collisiontiles from txt-file       
    def __createTextWorldCollision(self):
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                
                if self.mMap[y][x] == "#":
                    self.mTiles.append(Tile(self.mWorld, b2Vec2(x, y), self.__calculateTileType(x, y)))
                elif self.mMap[y][x] == "S":
                    self.mStartPos = b2Vec2(x, y)
                elif self.mMap[y][x] == "E":
                    self.mEndPos = b2Vec2(x, y)
                elif self.mMap[y][x] == "*":
                    self.mTiles.append(Tile(self.mWorld, b2Vec2(x, y), TileType.GRAVITYZONE))
                elif self.mMap[y][x] == "B":
                    self.mObjects.append(Box(b2Vec2(x, y), self.mWorld, self.mGravity))
        
        for tile in self.mTiles:
            tile.create()
    
    #create collisiontiles from picture and divid em into chunks  
    def __createPictureWorldCollision(self):
        self.mMap.lock()
        
        chunkx = self.mWidth / self.CHUNK_SIZE
        chunky = self.mHeight / self.CHUNK_SIZE
        
        for cy in range(chunky):
            self.mChunkHandler.chunkslist.append([])
            for cx in range(chunkx):
                self.mChunkHandler.chunkslist[cy].append([])
                
                chunkmap = self.mMap.subsurface(Rect(cx * self.CHUNK_SIZE, cy * self.CHUNK_SIZE, self.CHUNK_SIZE, self.CHUNK_SIZE))
                chunktiles = []
                
                for y in range(chunkmap.get_height()):
                    for x in range(chunkmap.get_width()):
                        
                        r,g,b,a = chunkmap.get_at((x, y))
                        
                        #mapx / mapy
                        mx = x + cx * self.CHUNK_SIZE
                        my = y + cy * self.CHUNK_SIZE
                        
                        if (r,g,b) != Color.WHITE:
                            
                            pos = b2Vec2(mx, my)
                            
                            if (r,g,b) == Color.WALL:
                                self.mAllTiles.append(Tile(self.mWorld, pos, self.__calculateTileType(mx, my)))
                                chunktiles.append(Tile(self.mWorld, pos, self.__calculateTileType(mx, my)))
                            elif (r,g,b) == Color.STARTPOS:
                                self.mStartPos = pos
                            elif (r,g,b) == Color.ENDPOS:
                                self.mEndPos = pos
                
                self.mChunkHandler.chunkslist[cy][cx] = Chunk(b2Vec2(cx, cy), chunktiles)                         
        self.mMap.unlock()
    
    def __isWallType(self, tile):
        if self.mMapType == MapType.PICTURE:
            return True if tile == Color.WALL else False
        else:
            return True if tile == "#" else False
       
    def __accessMap(self, x, y):
        if self.mMapType == MapType.PICTURE:
            return self.mMap.get_at((x, y))
        else:
            return self.mMap[y][x]
    
    def __calculateTileType(self, mx, my):
        tiletype = TileType.M
        
        #left edge
        if mx == 0:
            if my == 0:
                tiletype = TileType.ETL
            elif my == self.mHeight-1:
                tiletype = TileType.EBL
            elif self.__isWallType(self.__accessMap(mx+1, my)) or self.__isWallType(self.__accessMap(mx+1, my)):
                tiletype = TileType.EL
            else:
                tiletype = TileType.R
        
        #right edge    
        elif mx == self.mWidth-1:
            if my == 0:
                tiletype = TileType.ETR
            elif my == self.mHeight-1:
                tiletype = TileType.EBR
            elif self.__isWallType(self.__accessMap(mx-1, my)):
                tiletype = TileType.ER
            else:
                tiletype = TileType.L
        
        #top
        elif my == 0:
            if not self.__isWallType(self.__accessMap(mx, my+1)):
                tiletype = TileType.B
            else:
                tiletype = TileType.ET
                
        #bottom
        elif my == self.mHeight-1:
            if not self.__isWallType(self.__accessMap(mx, my-1)):
                tiletype = TileType.GM
            else:
                tiletype = TileType.EB
                
        if my > 0 and my < self.mHeight-1 and mx > 0 and mx < self.mWidth-1:
            
            #only under
            if not self.__isWallType(self.__accessMap(mx, my-1)) and self.__isWallType(self.__accessMap(mx, my+1)):
                
                #only right side
                if not self.__isWallType(self.__accessMap(mx-1, my)) and self.__isWallType(self.__accessMap(mx+1, my)):
                    tiletype = TileType.GL
                    
                #only left side
                elif not self.__isWallType(self.__accessMap(mx+1, my)) and self.__isWallType(self.__accessMap(mx-1, my)):
                    tiletype = TileType.GR
                
                #neither sides
                elif not self.__isWallType(self.__accessMap(mx+1, my)) and not self.__isWallType(self.__accessMap(mx-1, my)):
                    tiletype = TileType.SVT
                else:
                    tiletype = TileType.GM
            
            #only over     
            elif self.__isWallType(self.__accessMap(mx, my-1)) and not self.__isWallType(self.__accessMap(mx, my+1)):
                
                #only right side
                if not self.__isWallType(self.__accessMap(mx-1, my)) and self.__isWallType(self.__accessMap(mx+1, my)):
                    tiletype = TileType.BL
                    
                #only left side
                elif not self.__isWallType(self.__accessMap(mx+1, my)) and self.__isWallType(self.__accessMap(mx-1, my)):
                    tiletype = TileType.BR
                
                #neither sides
                elif not self.__isWallType(self.__accessMap(mx+1, my)) and not self.__isWallType(self.__accessMap(mx-1, my)):
                    tiletype = TileType.SVB
                else:
                    tiletype = TileType.B
            
            #not over nor under        
            elif not self.__isWallType(self.__accessMap(mx, my-1)) and not self.__isWallType(self.__accessMap(mx, my+1)):
                
                #neither sides
                if not self.__isWallType(self.__accessMap(mx-1, my)) and not self.__isWallType(self.__accessMap(mx+1, my)):
                    tiletype = TileType.SG
                
                #only right side
                elif not self.__isWallType(self.__accessMap(mx-1, my)) and self.__isWallType(self.__accessMap(mx+1, my)):
                    tiletype = TileType.SGL
                
                #only left side
                elif not self.__isWallType(self.__accessMap(mx+1, my)) and self.__isWallType(self.__accessMap(mx-1, my)):
                    tiletype = TileType.SGR
                else:
                    tiletype = TileType.SGM
            else:
                
                #only left side
                if not self.__isWallType(self.__accessMap(mx+1, my)) and self.__isWallType(self.__accessMap(mx-1, my)):
                    tiletype = TileType.R
                
                #only right side
                elif not self.__isWallType(self.__accessMap(mx-1, my)) and self.__isWallType(self.__accessMap(mx+1, my)):
                    tiletype = TileType.L
                
                #neither sides
                elif not self.__isWallType(self.__accessMap(mx-1, my)) and not self.__isWallType(self.__accessMap(mx+1, my)):
                    tiletype = TileType.SVM
                
                else:
                    tiletype = TileType.M
                    
        return tiletype
    
    def __createPickups(self):
        objects = json.loads(self.mPickupData)
        
        if len(objects) > 0:
            for obj in range(len(objects)):
                x, y = [float(i) for i in objects[obj]["POS"].split(",")]
                objtype = objects[obj]["TYPE"]
                
                if objtype == ObjectType.NUGGET:
                    self.mObjects.append(Crystal((x,y), self.mWorld))
    
    def __createEnemies(self):
        enemies = json.loads(self.mEnemyData)
        
        if len(enemies) > 0:
            for e in range(len(enemies)):
                x, y = [float(i) for i in enemies[e]["POS"].split(",")]
                etype = enemies[e]["TYPE"]
                
                if etype == EnemyType.SPIKEBOX:
                    speed = float(enemies[e]["SPEED"])
                    delay = float(enemies[e]["DELAY"])
                    ex, ey = [float(i) for i in enemies[e]["ENDPOS"].split(",")]
                    self.mEnemies.append(SpikeBox(self.mWorld, (x,y), (ex, ey), delay, speed))
                elif etype == EnemyType.SPIKE:
                    facing = int(enemies[e]["FACING"])
                    self.mEnemies.append(Spike(self.mWorld, (x,y), facing))
                elif etype == EnemyType.SAW:
                    pattern = [(k, v) for k,v in (str(enemies[e]["PATTERN"][x]).split(",") for x in range(len(enemies[e]["PATTERN"])))]
                    speed = float(enemies[e]["SPEED"])
                    radius = float(enemies[e]["RADIUS"])
                    self.mEnemies.append(Saw(self.mWorld, (x,y), pattern, radius, speed))
                elif etype == EnemyType.LASER:
                    ex, ey = [float(i) for i in enemies[e]["ENDPOS"].split(",")]
                    delay = float(enemies[e]["DELAY"])
                    triggertime = float(enemies[e]["T_TIMER"])
                    firingtime = float(enemies[e]["F_TIMER"])
                    self.mEnemies.append(Laser(self.mWorld, b2Vec2(x,y), b2Vec2(ex,ey), delay, triggertime, firingtime))
    
    def __createBoxes(self):
        boxes = json.loads(self.mBoxData)
        
        if len(boxes) > 0:
            for box in range(len(boxes)):
                x, y = [float(i) for i in boxes[box]["POS"].split(",")]
                self.mObjects.append(Box(b2Vec2(x, y), self.mWorld, self.mGravity))
    
    def nextLevel(self):
        if self.mCurrentLevel < self.mMaxLevels:
            self.__unloadCurrentLevel()
            self.mCurrentLevel += 1
            self.__loadLevel()

    def retryLevel(self):
        self.__unloadEntities()
        self.__createPickups()
        self.__createEnemies()
        #self.__createBoxes()
        self.mSwirlActive = False
               
    def isInActiveChunks(self, position):
        return True if self.mMapType == MapType.TEXT else self.mChunkHandler.isPositionInActiveChunks(position)
    
    @staticmethod
    def countLevels():
        lvls = 0
        for filename in os.listdir("assets/levels"):
            if filename.endswith(".lvl"):
                lvls += 1
        return lvls