My TileEngineCode:-- Note this version of the TileEngine does not pre-render the map. The -- advantage is that you can use big maps. The disadvantage is that it will be -- slower (especially for large display area with small tiles). ------------------------ IMAGING property Buffer -- offscreen image of the map property Canvas -- the output image property RectOnCanvas -- dest rect on the canvas ------------------------ MAPPING property MapList -- map of the current tiled image property MapLoaded ------------------------ STATIC TILE PROPERTIES property Tile_Width, Tile_Height -- assume all tiles are the same size property Tile_Rect property Tile_HalfWidth property Tile_HalfHeight ------------------------ SCROLLING property MapY, MapX -- current mapping (scroll) property MapXi, MapYi -- integer versions of MapX and MapY property MapXLimit, MapYLimit -- limits on moving the view property MaxTilesToDrawX, MaxTilesToDrawY -- max number of tiles to draw property WorldPixelSize ------------------------ DEBUGGING property SelectedTile property LastPath -------------------------------------------------------------------------------- -- Initialise -------------------------------------------------------------------------------- on Initialise (me, outputImage, aRect) Canvas = outputImage if aRect.ilk = #rect then RectOnCanvas = aRect else RectOnCanvas = Canvas.rect MapLoaded = false LastPath = [] return me end -------------------------------------------------------------------------------- -- Load Map -------------------------------------------------------------------------------- on LoadMap (me, aMap, baseTile, feedbackObj) -- Parameters: -- * aMap is a list of lists containing tile objects -- * base tile is a member reference of a 'base tile' (used -- to get width, height and regpoint) -- Returns -- "OK" for success or an error description -- check input parameters if (aMap.ilk <> #list) then return \ "Bad parameter: supplied Map is not a list" if (count(aMap) < 1) then return \ "Bad parameter: supplied Map is empty" if (aMap[1].ilk <> #list) then return \ "Bad parameter: supplied Map is incorrectly populated (first row is not a list)" if (aMap[1].count < 1) then return "Bad parameter: supplied Map is incorrectly populated (first row is empty)" if (baseTile.ilk <> #member) then return \ "Bad parameter: need a member reference for a base tile" if (baseTile.type <> #bitmap) then return \ "Bad parameter: need a bitmap member reference for a base tile" me._InitialiseMap(aMap, baseTile, feedbackObj) MapLoaded = true return "OK" end -------------------------------------------------------------------------------- -- Mapping Methods -- MapLoc is the position of the tile in the map ie. point(TilesX, TilesY) -- WorldLoc is the position is the 'world' (in pixels) -- ViewLoc is the position in the view (ie. WorldLoc - scrollAmount) -------------------------------------------------------------------------------- on WorldToMap (me, worldLoc) if MapLoaded then x = floor((worldLoc.locH)/float(Tile_Width)) + 1 y = floor((worldLoc.locV)/float(Tile_Height)) + 1 x = Max(1, Min(MapList[1].count, x)) y = Max(1, Min(MapList.count, y)) return point(x,y) end if end on MapToWorld (me, mapLoc) if MapLoaded then -- return the point in the middle of the specified tile x = (mapLoc.locH-1)*Tile_Width + Tile_HalfWidth y = (mapLoc.locV-1)*Tile_Height + Tile_HalfHeight return point(x,y) end if end on ViewToWorld (me, viewLoc) -- translates a point in the current view to a its -- position in the world return point(viewLoc.locH -MapX, viewLoc.locV-MapY) end on WorldToView (me, p) -- translates a point in the world to a its -- relative position in the current view return point(p.locH +MapX, p.locV+MapY) end on ViewToMap (me, viewLoc) -- translates a point in the current view to a its -- position in the world return me.WorldToMap(point(viewLoc.locH -MapX, viewLoc.locV-MapY)) end on MapToView (me, p) -- translates a point in the world to a its -- relative position in the current view p = me.MapToWorld(p) return point(p.locH +MapX, p.locV+MapY) end on OffsetToMiddleOfView (me, PntOnMap) -- return a vector (point) from the specifed point -- to the middle of the current view p1 = point(PntOnMap.locH , PntOnMap.locV) p2 = point( RectOnCanvas.width/2-MapX, RectOnCanvas.height/2-MapY) return (p2-p1) end -------------------------------------------------------------------------------- -- Update Event -- Redraw all the visible tiles -------------------------------------------------------------------------------- on Update (me) if MapLoaded then -- update the visible tiles -- work out the start and end of the x/y coordinates to draw startX = (-MapXi/Tile_Width) + 1 startY = (-MapYi/Tile_Height) + 1 endX = Min(MapList[1].count, startX + MaxTilesToDrawX) endY = Min(MapList.count, startY + MaxTilesToDrawY) -- now draw the visible tiles repeat with y = startY to endY repeat with x = startX to endX thisTile = MapList[y][x] thisTile.Paint(canvas, MapXi,MapYi) end repeat end repeat -- now paint the hilight if SelectedTile <> VOID then aColor = rgb("#000") PaintRect = SelectedTile.destRect.offset(MapXi,MapYi) Canvas.draw( PaintRect, [#ShapeType:#rect, #Color: aColor]) end if end if end -------------------------------------------------------------------------------- -- Painting Methods -------------------------------------------------------------------------------- on PaintFullMap (me, intoThisImage) -- paint the map into a supplied image, returning the scale -- of the rendered map and an offset to the top-left of the -- canvas the map has been painted into. This method is used -- by the 'minimap' to get small version of the whole map PaintRect = intoThisImage.rect worldTileSize = [maplist[1].count, maplist.count] -- TileOffset = [0,0] if worldTileSize[1] = worldTileSize[2] then tileDrawWidth = PaintRect.width/float(maplist[1].count) tileDrawHeight = PaintRect.height/float(maplist.count) tileDrawRect = rect(0, 0, tileDrawWidth, tileDrawHeight) else if worldTileSize[1] > worldTileSize[2] then tileDrawWidth = PaintRect.width/float(maplist[1].count) tileDrawHeight = tileDrawWidth tileDrawRect = rect(0, 0, tileDrawWidth, tileDrawHeight) gap = PaintRect.height - (worldTileSize[2]*tileDrawHeight) TileOffset = TileOffset + [0, gap*0.5] else tileDrawHeight = PaintRect.height/float(maplist.count) tileDrawWidth = tileDrawHeight tileDrawRect = rect(0, 0, tileDrawWidth, tileDrawHeight) gap = PaintRect.width - (worldTileSize[1]*tileDrawWidth) TileOffset = TileOffset + [gap*0.5, 0] end if MapScale = float(tileDrawWidth) / tile_width CurrentOffset = TileOffset.duplicate() repeat with y = 1 to worldTileSize[2] aRow = maplist[y] repeat with x = 1 to worldTileSize[1] destRect = tileDrawRect + rect(CurrentOffset[1], CurrentOffset[2],\ CurrentOffset[1], CurrentOffset[2]) imageRef = maplist[y][x].image intoThisImage.copyPixels(imageRef, destRect, tile_Rect) CurrentOffset[1] = CurrentOffset[1] + tileDrawWidth end repeat CurrentOffset[1] = TileOffset[1] CurrentOffset[2] = CurrentOffset[2] + tileDrawHeight end repeat return [#MapScale: MapScale,#TileOffset:TileOffset] end -------------------------------------------------------------------------------- -- Pathfinding -------------------------------------------------------------------------------- on GetPathCost (me, x,y) -- return the cost to make a path across the specified tile x = mapList[y][x].GetCost() return x end on ShowPath (me, aPath) -- just for debugging repeat with T in LastPath T.RestoreImage() end repeat LastPath.deleteAll() repeat with aLoc in aPath t = MapList[aLoc.locV][aLoc.locH] T.PathHilight() LastPath.append(T) end repeat end -------------------------------------------------------------------------------- -- Scrolling the view -------------------------------------------------------------------------------- on MoveView (me, x, y) -- Shifts the current map coordinates by the specified -- amount and updates the buffer if MapLoaded then MapX = MIN(0, MAX(MapXLimit, MapX-x)) MapY = MIN(0, MAX(MapYLimit, MapY-y)) MapXi = integer(MapX) MapYi = integer(MapY) end if end on MoveViewTo (me, newLoc) -- shifts the current map coordinates to the specified point if MapLoaded then amnt = newLoc + point(RectOnCanvas.width/2, RectOnCanvas.height/2) MapX = MIN(0, MAX(MapXLimit, amnt.locH)) MapY = MIN(0, MAX(MapYLimit, amnt.locV)) MapXi = integer(MapX) MapYi = integer(MapY) end if end on GetViewRect(me) return RectOnCanvas.offset(-MapXi,-MapYi) end -------------------------------------------------------------------------------- -- Get and Set Tile Objects -------------------------------------------------------------------------------- on GetTile (me, iPnt) -- returns a reference to the specified tile object iy = iPnt.locV ix = iPnt.locH return mapList[iy][ix] end on SetTile (me, iPnt, thisTile) -- returns a reference to the specified tile object iy = iPnt.locV ix = iPnt.locH x_offset = (ix-1)*Tile_Width y_offset = (iy-1)*Tile_Height mappedTile = script("TileEngine.Tile.Mapped").new(thisTile,\ x_offset, y_offset) MapList[iy][ix] = mappedTile return MapList[iy][ix] end -------------------------------------------------------------------------------- -- Interacting with Map -------------------------------------------------------------------------------- on GetMovedPoint(me, startPnt, endPnt, rectToMove) -- return the point furthest along the line from -- startPnt to endPnt that the rectToMove can move to -- in this version, simply ensure that the rect stays -- within the world rect x = 0 y = 0 r = rectToMove.offset(endPnt.locH, endPnt.locV) if r.left < 0 then x = -r.left else if r.right > WorldPixelSize[1] then x = WorldPixelSize[1]-r.right if r.top < 0 then y = -r.top else if r.bottom > WorldPixelSize[2] then y = WorldPixelSize[2]-r.bottom return endPnt + point(x,y) end -------------------------------------------------------------------------------- -- Hilight a tile -------------------------------------------------------------------------------- on HilightTile (me, aTile) if aTile.ilk = #instance then SelectedTile = aTile end if end on DeselectTile (me) SelectedTile = VOID end -------------------------------------------------------------------------------- -- Private Methods -------------------------------------------------------------------------------- on _InitialiseMap (me, aMap, basetile, feedbackObj) MapList = aMap MapY = 0 MapX = 0 Tile_Width = basetile.width Tile_Height = basetile.height Tile_Rect = rect(0,0,Tile_Width,Tile_Height) Tile_HalfWidth = Tile_Width/2 Tile_HalfHeight = Tile_Height/2 WorldTileSize = [MapList[1].count, MapList.count] WorldPixelSize = WorldTileSize * [Tile_Width, Tile_Height] MaxTilesToDrawX = RectOnCanvas.width/Tile_Width +1 MaxTilesToDrawY = RectOnCanvas.height/Tile_Height +1 MapXLimit = -(((MapList[1].count) * Tile_Width) - RectOnCanvas.width - 1) MapYLimit = -(((MapList.count) * Tile_Height) - RectOnCanvas.height - 1) x_offset = 0 y_offset = 0 steps = float(MapList.count) repeat with y = 1 to MapList.count repeat with x = 1 to MapList[y].count thisTile = MapList[y][x] mappedTile = script("TileEngine.Tile.Mapped").new(\ thisTile, x_offset, y_offset) MapList[y][x] = mappedTile x_offset = x_offset + Tile_Width end repeat x_offset = 0 y_offset = y_offset + Tile_Height call(#ShowProgress, [feedbackObj], "Loading Map...", (y/steps)) end repeat buffer = image(WorldPixelSize[1], WorldPixelSize[2], 16) end
Error:
Code:Script error: Command expected "Bad parameter: supplied map is incorrectly populated (first row is empty)"?





Reply With Quote