PDA

View Full Version : [Lingo] Some error on my TileEngine



Dentafrice1
03-04-2007, 11:07 PM
-- 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


My TileEngine

Error:



Script error: Command expected

"Bad parameter: supplied map is incorrectly populated (first row is empty)"?

Want to hide these adverts? Register an account for free!