Example #1
0
class FlxTilemap(FlxCore):
    #@desc		Constructor
    #@param	MapData			A string of comma and line-return delineated indices indicating what order the tiles should go in
    #@param	TileGraphic		All the tiles you want to use, arranged in a strip corresponding to the numbers in MapData
    #@param	CollisionIndex	The index of the first tile that should be treated as a hard surface
    #@param	DrawIndex		The index of the first tile that should actually be drawn
    def __init__(self,MapData, TileGraphic, CollisionIndex=1, DrawIndex=1):
        #image = pyglet.resource.image("data/logo.png")
        FlxCore.__init__(self);
        self.CollideIndex = CollisionIndex;self.DrawIndex = 1;
        self._ci = CollisionIndex;
        self.widthInTiles = 0;
        self.heightInTiles = 0;
        self._data = FlxArray();
        #c;
        #cols:Array;
        rows = open(MapData).read().split("\n");
        
        rows.reverse()
        rows=rows[2:]
        self.heightInTiles = len(rows);
        for  r  in range(self.heightInTiles):
            cols = rows[r].split(",");
            if(len(cols) <= 1):
                self.heightInTiles-=1;
                continue;
            if(self.widthInTiles == 0):
                self.widthInTiles = len(cols);
            for c in range(self.widthInTiles):
                self._data.append(int(cols[c]));
                  
        self._pixels = TileGraphic
        self._rects = FlxArray();
        self._p = FlxPoint();
        self._tileSize =self._pixels.height;
        self.width = self.widthInTiles*self._tileSize;
        self.height = self.heightInTiles*self._tileSize;
        self.numTiles = self.widthInTiles*self.heightInTiles;
        for i in range(self.numTiles):
            if(self._data[i] >= DrawIndex):
                self._rects.append(FlxRect(self._tileSize*self._data[i],0,self._tileSize,self._tileSize));
            else:
                self._rects.append(None);
        #self._block = FlxBlock(0,0,self._tileSize,self._tileSize,None);
        
        self._screenRows =int( Math.ceil(FlxG.height/self._tileSize)+1);
        if(self._screenRows > self.heightInTiles):
            self._screenRows = self.heightInTiles;
        self._screenCols = int(Math.ceil(FlxG.width/self._tileSize)+1);
        if(self._screenCols > self.widthInTiles):
            self._screenCols = self.widthInTiles;
        
        self._tileObjects = range(self._pixels.width/self._pixels.height)
        i=0
        while(i < self._pixels.width/self._pixels.height):
            collide=FlxCore.NONE
            if(i>= self.CollideIndex):
                collide=self.allowCollisions
            self._tileObjects[i] =FlxTile(self,i,self._tileSize,self._tileSize,(i >= self.DrawIndex),collide)
            i+=1;
    #@desc		Draws the tilemap
    def render(self):
        #NOTE: While this will only draw the tiles that are actually on screen, it will ALWAYS draw one screen's worth of tiles
        FlxCore.render(self)
        self.getScreenXY(self._p);
        #print self._p.x,self._p.y
        #self.position=(self._p.x,self._p.y)
        #raw_input()
        tx = Math.floor(-self._p.x/self._tileSize);
        ty = Math.floor(-self._p.y/self._tileSize);
        if(tx < 0): 
            tx = 0;
        if(tx > self.widthInTiles-self._screenCols): 
            tx = self.widthInTiles-self._screenCols;
        if(ty < 0): 
            ty = 0;
        if(ty > self.heightInTiles-self._screenRows): 
            ty = self.heightInTiles-self._screenRows;
        ri =int(ty*self.widthInTiles+tx);
        self._p.x += tx*self._tileSize;
        self._p.y += ty*self._tileSize;
        opx = self._p.x;
        for r in range(self._screenRows):
            cri = ri;
            for c in range(self._screenCols):
                #print self._rects[cri]
                #raw_input()
                if(self._rects[cri] != None):
                    im=self._pixels.get_region(self._rects[cri].x,self._rects[cri].y,self._rects[cri].width,self._rects[cri].height)#.x,self._rects[cri].y, self._rects[cri].width,self._rects[cri].height)
                    #tmp=Sprite(im)
                    #tmp.position=(self._p.x,self._p.y)
                    #print r,c,"tile",self._p.x,self._p.y
                    #self.add(tmp)
                    r=FlxRect(self._p.x,self._p.y,self._rects[cri].width,self._rects[cri].height)
                    im.blit(self._p.x,self._p.y);
                cri+=1;
                self._p.x += self._tileSize;
            ri += self.widthInTiles;
            self._p.x = opx;
            self._p.y += self._tileSize;
    
    #@desc		Collides a FlxSprite against the tilemap
    #@param	Spr		The FlxSprite you want to collide
    def old_collide(self,Spr):
        #print "map collide"#Spr.velocity.x
        ix =int(Math.floor((Spr.x - self.x)/self._tileSize))
        iy =int(Math.floor((Spr.y - self.y)/self._tileSize))
        for r in [iy-1,iy,iy+1]:
            if((r < 0) or (r >= self.heightInTiles)): 
                continue;
            for c in [ix-1,ix,ix+1]:
                if((c < 0) or (c >= self.widthInTiles)): 
                    continue;
                at=(r)*self.widthInTiles+c
                #print "at=",at
                if( self._data[at] >= self._ci):
                    self._block.x = self.x+c*self._tileSize;
                    self._block.y = self.y+r*self._tileSize;
                    self._block.collide(Spr);
                    #print at,self._block.x,self._block.y
        return 
        #old
        ix =int(Math.floor((Spr.x - self.x)/self._tileSize))
        iy =int(Math.floor((Spr.y - self.y)/self._tileSize))
        iw =int( Math.ceil(float(Spr.width)/self._tileSize)+1)
        ih =int(Math.ceil(float(Spr.height)/self._tileSize)+1)
        print "map collide",ih,iw
        print Spr.width,self._tileSize,Spr.x,Spr.y
        for r in range( ih):
            if((r < 0) or (r >= self.heightInTiles)): 
                continue;
            for c in range(iw):
                if((c < 0) or (c >= self.widthInTiles)): 
                    continue;
                at=(iy+r)*self.widthInTiles+ix+c
                print "at=",at,
                if(at<len(self._data) and self._data[at] >= self._ci):
                    self._block.x = self.x+(ix+c)*self._tileSize;
                    self._block.y = self.y+(iy+r)*self._tileSize;
                    self._block.collide(Spr);
                    #print Spr.ySpr.y,Spr.velocity.y,"block",self._block.x,self._block.y,self._block.width,self._block.height
        #raw_input()
    # def collide(self,Spr):
        # self.overlapsWithCallback(Spr,FlxCore.separate)
    def setTileProperties(self,Tile,AllowCollisions=0x1111,Callback=None,CallbackFilter=None,Range=1):
        if(Range <= 0):
            Range = 1;
        i = Tile;
        l = Tile+Range;
        while(i < l):
            tile = self._tileObjects[i]
            i+=1
            tile.allowCollisions = AllowCollisions;
            tile.callback = Callback;
            tile.filter = CallbackFilter;
    def overlapsArr(self,Array,callback):
        #print "overlapsArr"
        
        for i in range(len( Array)):
            
            c = Array[i];
            #print dir(c)
            if(c.exists):#,c.visible
                self.overlapsWithCallback(c,callback)
    def collideArr(self,Array):
        for i in range(len( Array)):
            c = Array[i];
            self.collide(c)
    def collide(self,Object):
        results = false;
        Position=None
        X = self.x;
        Y = self.y;
        if(Position != None):
            X = Position.x;
            Y = Position.y;
        #Figure out what tiles we need to check against
        selectionX = Math.floor((Object.x - X)/self._tileSize)
        selectionY = Math.floor((Object.y - Y)/self._tileSize)
        selectionWidth = selectionX + (Math.ceil(Object.width/self._tileSize)) + 1;
        selectionHeight = selectionY + Math.ceil(Object.height/self._tileSize) + 1;
        
        #Then bound these coordinates by the map edges
        if(selectionX < 0):
            selectionX = 0;
        if(selectionY < 0):
            selectionY = 0;
        if(selectionWidth > self.widthInTiles):
            selectionWidth = self.widthInTiles;
        if(selectionHeight > self.heightInTiles):
            selectionHeight = self.heightInTiles;
        
        #Then loop through this selection of tiles and call FlxObject.separate() accordingly
        rowStart = selectionY*self.widthInTiles;
        row = selectionY;
        overlapFound=false;
        deltaX = X - self.last.x;
        deltaY = Y - self.last.y;
        #print "selection====="
        
        #print selectionX,selectionY,selectionWidth,selectionHeight
        
        while(row <= selectionHeight):
            column = selectionX;
            while(column <=selectionWidth):
                
                overlapFound = false;
                #print "at="+str(int(rowStart+column))
                tile = self._tileObjects[self._data[int(rowStart+column)]];
                #print "row,column",row,column,tile.allowCollisions
                #print "data="+str(self._data[int(rowStart+column)])
                
                if(tile.allowCollisions):
                    tile.x = X+column*self._tileSize;
                    tile.y = Y+row*self._tileSize;
                    tile.last.x = tile.x - deltaX;
                    tile.last.y = tile.y - deltaY;
                    #print "==========="
                    #print tile.x,tile.y,self._tileSize
                    #print Object.x,Object.y,Object.width,Object.height
                    mycollide.collide(Object,tile)
                #raw_input()
                column+=1;
            rowStart += self.widthInTiles;
            row+=1;
        return results;
    def overlapsWithCallback(self,Object,Callback=None,FlipCallbackParams=false,Position=None):
        results = false;
        X = self.x;
        Y = self.y;
        if(Position != None):
            X = Position.x;
            Y = Position.y;
        #Figure out what tiles we need to check against
        selectionX = Math.floor((Object.x - X)/self._tileSize)
        selectionY = Math.floor((Object.y - Y)/self._tileSize)
        selectionWidth = selectionX + (Math.ceil(Object.width/self._tileSize)) + 1;
        selectionHeight = selectionY + Math.ceil(Object.height/self._tileSize) + 1;
        
        #Then bound these coordinates by the map edges
        if(selectionX < 0):
            selectionX = 0;
        if(selectionY < 0):
            selectionY = 0;
        if(selectionWidth > self.widthInTiles):
            selectionWidth = self.widthInTiles;
        if(selectionHeight > self.heightInTiles):
            selectionHeight = self.heightInTiles;
        
        #Then loop through this selection of tiles and call FlxObject.separate() accordingly
        rowStart = selectionY*self.widthInTiles;
        row = selectionY;
        overlapFound=false;
        deltaX = X - self.last.x;
        deltaY = Y - self.last.y;
        while(row < selectionHeight):
            column = selectionX;
            while(column < selectionWidth):
                #print "row,column",row,column
                overlapFound = false;
                tile = self._tileObjects[self._data[int(rowStart+column)]];
                if(tile.allowCollisions):
                    tile.x = X+column*self._tileSize;
                    tile.y = Y+row*self._tileSize;
                    tile.last.x = tile.x - deltaX;
                    tile.last.y = tile.y - deltaY;
                    if(Callback != None):
                        if(FlipCallbackParams):
                            overlapFound = Callback(Object,tile);
                        else:
                            overlapFound = Callback(tile,Object);
                    else:
                        overlapFound = (Object.x + Object.width > tile.x) and (Object.x < tile.x + tile.width) and (Object.y + Object.height > tile.y) and (Object.y < tile.y + tile.height);
                    if(overlapFound):
                        if((tile.callback != None) and ((tile.filter == None) or (Object is tile.filter))):
                            tile.mapIndex = rowStart+column;
                            tile.callback(tile,Object);
                        results = true;
                elif((tile.callback != None) and ((tile.filter == None) or (Object is tile.filter))):
                    tile.mapIndex = rowStart+column;
                    tile.callback(tile,Object);
                column+=1;
            rowStart += self.widthInTiles;
            row+=1;
        return results;
Example #2
0
class FlxTilemap(FlxCore):
    #@desc		Constructor
    #@param	MapData			A string of comma and line-return delineated indices indicating what order the tiles should go in
    #@param	TileGraphic		All the tiles you want to use, arranged in a strip corresponding to the numbers in MapData
    #@param	CollisionIndex	The index of the first tile that should be treated as a hard surface
    #@param	DrawIndex		The index of the first tile that should actually be drawn
    def __init__(self, MapData, TileGraphic, CollisionIndex=1, DrawIndex=1):
        #image = pyglet.resource.image("data/logo.png")
        FlxCore.__init__(self)
        self.CollideIndex = CollisionIndex
        self.DrawIndex = 1
        self._ci = CollisionIndex
        self.widthInTiles = 0
        self.heightInTiles = 0
        self._data = FlxArray()
        #c;
        #cols:Array;
        rows = open(MapData).read().split("\n")

        rows.reverse()
        rows = rows[2:]
        self.heightInTiles = len(rows)
        for r in range(self.heightInTiles):
            cols = rows[r].split(",")
            if (len(cols) <= 1):
                self.heightInTiles -= 1
                continue
            if (self.widthInTiles == 0):
                self.widthInTiles = len(cols)
            for c in range(self.widthInTiles):
                self._data.append(int(cols[c]))

        self._pixels = TileGraphic
        self._rects = FlxArray()
        self._p = FlxPoint()
        self._tileSize = self._pixels.height
        self.width = self.widthInTiles * self._tileSize
        self.height = self.heightInTiles * self._tileSize
        self.numTiles = self.widthInTiles * self.heightInTiles
        for i in range(self.numTiles):
            if (self._data[i] >= DrawIndex):
                self._rects.append(
                    FlxRect(self._tileSize * self._data[i], 0, self._tileSize,
                            self._tileSize))
            else:
                self._rects.append(None)
        #self._block = FlxBlock(0,0,self._tileSize,self._tileSize,None);

        self._screenRows = int(Math.ceil(FlxG.height / self._tileSize) + 1)
        if (self._screenRows > self.heightInTiles):
            self._screenRows = self.heightInTiles
        self._screenCols = int(Math.ceil(FlxG.width / self._tileSize) + 1)
        if (self._screenCols > self.widthInTiles):
            self._screenCols = self.widthInTiles

        self._tileObjects = range(self._pixels.width / self._pixels.height)
        i = 0
        while (i < self._pixels.width / self._pixels.height):
            collide = FlxCore.NONE
            if (i >= self.CollideIndex):
                collide = self.allowCollisions
            self._tileObjects[i] = FlxTile(self, i, self._tileSize,
                                           self._tileSize,
                                           (i >= self.DrawIndex), collide)
            i += 1

    #@desc		Draws the tilemap
    def render(self):
        #NOTE: While this will only draw the tiles that are actually on screen, it will ALWAYS draw one screen's worth of tiles
        FlxCore.render(self)
        self.getScreenXY(self._p)
        #print self._p.x,self._p.y
        #self.position=(self._p.x,self._p.y)
        #raw_input()
        tx = Math.floor(-self._p.x / self._tileSize)
        ty = Math.floor(-self._p.y / self._tileSize)
        if (tx < 0):
            tx = 0
        if (tx > self.widthInTiles - self._screenCols):
            tx = self.widthInTiles - self._screenCols
        if (ty < 0):
            ty = 0
        if (ty > self.heightInTiles - self._screenRows):
            ty = self.heightInTiles - self._screenRows
        ri = int(ty * self.widthInTiles + tx)
        self._p.x += tx * self._tileSize
        self._p.y += ty * self._tileSize
        opx = self._p.x
        for r in range(self._screenRows):
            cri = ri
            for c in range(self._screenCols):
                #print self._rects[cri]
                #raw_input()
                if (self._rects[cri] != None):
                    im = self._pixels.get_region(
                        self._rects[cri].x, self._rects[cri].y,
                        self._rects[cri].width, self._rects[cri].height
                    )  #.x,self._rects[cri].y, self._rects[cri].width,self._rects[cri].height)
                    #tmp=Sprite(im)
                    #tmp.position=(self._p.x,self._p.y)
                    #print r,c,"tile",self._p.x,self._p.y
                    #self.add(tmp)
                    r = FlxRect(self._p.x, self._p.y, self._rects[cri].width,
                                self._rects[cri].height)
                    im.blit(self._p.x, self._p.y)
                cri += 1
                self._p.x += self._tileSize
            ri += self.widthInTiles
            self._p.x = opx
            self._p.y += self._tileSize

    #@desc		Collides a FlxSprite against the tilemap
    #@param	Spr		The FlxSprite you want to collide
    def old_collide(self, Spr):
        #print "map collide"#Spr.velocity.x
        ix = int(Math.floor((Spr.x - self.x) / self._tileSize))
        iy = int(Math.floor((Spr.y - self.y) / self._tileSize))
        for r in [iy - 1, iy, iy + 1]:
            if ((r < 0) or (r >= self.heightInTiles)):
                continue
            for c in [ix - 1, ix, ix + 1]:
                if ((c < 0) or (c >= self.widthInTiles)):
                    continue
                at = (r) * self.widthInTiles + c
                #print "at=",at
                if (self._data[at] >= self._ci):
                    self._block.x = self.x + c * self._tileSize
                    self._block.y = self.y + r * self._tileSize
                    self._block.collide(Spr)
                    #print at,self._block.x,self._block.y
        return
        #old
        ix = int(Math.floor((Spr.x - self.x) / self._tileSize))
        iy = int(Math.floor((Spr.y - self.y) / self._tileSize))
        iw = int(Math.ceil(float(Spr.width) / self._tileSize) + 1)
        ih = int(Math.ceil(float(Spr.height) / self._tileSize) + 1)
        print "map collide", ih, iw
        print Spr.width, self._tileSize, Spr.x, Spr.y
        for r in range(ih):
            if ((r < 0) or (r >= self.heightInTiles)):
                continue
            for c in range(iw):
                if ((c < 0) or (c >= self.widthInTiles)):
                    continue
                at = (iy + r) * self.widthInTiles + ix + c
                print "at=", at,
                if (at < len(self._data) and self._data[at] >= self._ci):
                    self._block.x = self.x + (ix + c) * self._tileSize
                    self._block.y = self.y + (iy + r) * self._tileSize
                    self._block.collide(Spr)
                    #print Spr.ySpr.y,Spr.velocity.y,"block",self._block.x,self._block.y,self._block.width,self._block.height
        #raw_input()

    # def collide(self,Spr):
    # self.overlapsWithCallback(Spr,FlxCore.separate)
    def setTileProperties(self,
                          Tile,
                          AllowCollisions=0x1111,
                          Callback=None,
                          CallbackFilter=None,
                          Range=1):
        if (Range <= 0):
            Range = 1
        i = Tile
        l = Tile + Range
        while (i < l):
            tile = self._tileObjects[i]
            i += 1
            tile.allowCollisions = AllowCollisions
            tile.callback = Callback
            tile.filter = CallbackFilter

    def overlapsArr(self, Array, callback):
        #print "overlapsArr"

        for i in range(len(Array)):

            c = Array[i]
            #print dir(c)
            if (c.exists):  #,c.visible
                self.overlapsWithCallback(c, callback)

    def collideArr(self, Array):
        for i in range(len(Array)):
            c = Array[i]
            self.collide(c)

    def collide(self, Object):
        results = false
        Position = None
        X = self.x
        Y = self.y
        if (Position != None):
            X = Position.x
            Y = Position.y
        #Figure out what tiles we need to check against
        selectionX = Math.floor((Object.x - X) / self._tileSize)
        selectionY = Math.floor((Object.y - Y) / self._tileSize)
        selectionWidth = selectionX + (Math.ceil(
            Object.width / self._tileSize)) + 1
        selectionHeight = selectionY + Math.ceil(
            Object.height / self._tileSize) + 1

        #Then bound these coordinates by the map edges
        if (selectionX < 0):
            selectionX = 0
        if (selectionY < 0):
            selectionY = 0
        if (selectionWidth > self.widthInTiles):
            selectionWidth = self.widthInTiles
        if (selectionHeight > self.heightInTiles):
            selectionHeight = self.heightInTiles

        #Then loop through this selection of tiles and call FlxObject.separate() accordingly
        rowStart = selectionY * self.widthInTiles
        row = selectionY
        overlapFound = false
        deltaX = X - self.last.x
        deltaY = Y - self.last.y
        #print "selection====="

        #print selectionX,selectionY,selectionWidth,selectionHeight

        while (row <= selectionHeight):
            column = selectionX
            while (column <= selectionWidth):

                overlapFound = false
                #print "at="+str(int(rowStart+column))
                tile = self._tileObjects[self._data[int(rowStart + column)]]
                #print "row,column",row,column,tile.allowCollisions
                #print "data="+str(self._data[int(rowStart+column)])

                if (tile.allowCollisions):
                    tile.x = X + column * self._tileSize
                    tile.y = Y + row * self._tileSize
                    tile.last.x = tile.x - deltaX
                    tile.last.y = tile.y - deltaY
                    #print "==========="
                    #print tile.x,tile.y,self._tileSize
                    #print Object.x,Object.y,Object.width,Object.height
                    mycollide.collide(Object, tile)
                #raw_input()
                column += 1
            rowStart += self.widthInTiles
            row += 1
        return results

    def overlapsWithCallback(self,
                             Object,
                             Callback=None,
                             FlipCallbackParams=false,
                             Position=None):
        results = false
        X = self.x
        Y = self.y
        if (Position != None):
            X = Position.x
            Y = Position.y
        #Figure out what tiles we need to check against
        selectionX = Math.floor((Object.x - X) / self._tileSize)
        selectionY = Math.floor((Object.y - Y) / self._tileSize)
        selectionWidth = selectionX + (Math.ceil(
            Object.width / self._tileSize)) + 1
        selectionHeight = selectionY + Math.ceil(
            Object.height / self._tileSize) + 1

        #Then bound these coordinates by the map edges
        if (selectionX < 0):
            selectionX = 0
        if (selectionY < 0):
            selectionY = 0
        if (selectionWidth > self.widthInTiles):
            selectionWidth = self.widthInTiles
        if (selectionHeight > self.heightInTiles):
            selectionHeight = self.heightInTiles

        #Then loop through this selection of tiles and call FlxObject.separate() accordingly
        rowStart = selectionY * self.widthInTiles
        row = selectionY
        overlapFound = false
        deltaX = X - self.last.x
        deltaY = Y - self.last.y
        while (row < selectionHeight):
            column = selectionX
            while (column < selectionWidth):
                #print "row,column",row,column
                overlapFound = false
                tile = self._tileObjects[self._data[int(rowStart + column)]]
                if (tile.allowCollisions):
                    tile.x = X + column * self._tileSize
                    tile.y = Y + row * self._tileSize
                    tile.last.x = tile.x - deltaX
                    tile.last.y = tile.y - deltaY
                    if (Callback != None):
                        if (FlipCallbackParams):
                            overlapFound = Callback(Object, tile)
                        else:
                            overlapFound = Callback(tile, Object)
                    else:
                        overlapFound = (Object.x + Object.width > tile.x) and (
                            Object.x < tile.x + tile.width) and (
                                Object.y + Object.height >
                                tile.y) and (Object.y < tile.y + tile.height)
                    if (overlapFound):
                        if ((tile.callback != None)
                                and ((tile.filter == None) or
                                     (Object is tile.filter))):
                            tile.mapIndex = rowStart + column
                            tile.callback(tile, Object)
                        results = true
                elif ((tile.callback != None)
                      and ((tile.filter == None) or (Object is tile.filter))):
                    tile.mapIndex = rowStart + column
                    tile.callback(tile, Object)
                column += 1
            rowStart += self.widthInTiles
            row += 1
        return results