Omnimaga

Calculator Community => TI Calculators => Lua => Topic started by: hoffa on December 25, 2011, 08:01:21 am

Title: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: hoffa on December 25, 2011, 08:01:21 am
I've been working on a tile engine I named Owl. I had tried it before, but it was generally quite slow and a pain in the butt to use and adapt. I tried it again, but this time a lot more seriously, and it's been progressing nicely. My goal is to make a fast (fast as in TI-Nspire Lua fast), clean, flexible and lightweight tile map engine that anyone can use. The engine currently supports arbitrary-sized maps with scrolling, easy tile, object (anything that can change state during the game), and event (detonate the nuke when Link reads that sign) management. To keep the games responsive, playable and frustration-free, scrolling and movement is blocky, i.e. no smooth scrolling or fancy walking animations (although there will be basic animation management).

As mentioned up there, graphics-heavy TI-Nspire Lua programs (read: programs that use the TI.Image format to draw images a lot) are usually rather slow. But because sprites with a lot of transparent pixels and primitive shapes can be drawn relatively quickly, to tackle the issue of slowness I decided that every tile is defined by an optional background color and and a (hopefully) partially transparent sprite that comes on top of it. That in most cases improves the speed quite a bit. Also I'm working on a map format that will increase the FPS by a good 10%—40%.

All I can give you right now is the current source code, which is kept and updated whenever I commit a change on github (I repeat, it's not ready for public use): https://github.com/Hoffa/Owl (https://github.com/Hoffa/Owl)

I'll at some point write some sort of documentation and release a public version (when I feel it works and am generally pleased with it, might take some time), but until then you can play around with the code on github if you wish.

EDIT: on hold while I work on the SDL port.
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Adriweb on December 25, 2011, 08:33:01 am
Awesome !

I'll take a close look :D

Here's the source code (extracted with the sdk ... :D)
(and optimized images (replaced \000 with \0

Code: [Select]
Coyote = class()

function Coyote:init(x, y, width, height, options)
    options = options or {}
    self.gc = platform.gc()
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.tiles = {}
    self.controls = options.controls or {up = "up",
                                         down = "down",
                                         left = "left",
                                         right = "right"}
    self.player = {}
    self.tileSize = options.tileSize or 16
    self.scrollThreshold = options.scrollThreshold or 1
    self.outOfBoundsColor = options.outOfBoundsColor or {0, 0, 0}
    self.tileCount = 0
end

function Coyote:loadTile(sprites, color, walkable)
    self.tileCount = self.tileCount + 1
    self.tiles[self.tileCount] = {}
    local tile = self.tiles[self.tileCount]
    if type(sprites) == "string" then
        tile.sprites = {image.new(sprites)}
    elseif type(sprites) == "table" then
        tile.sprites = {}
        for i = 1, #sprites do
            tile.sprites[i] = image.new(sprites[i])
        end
    end
    tile.color = color
    tile.walkable = walkable
    return self.tileCount
end

function Coyote:handleMoveKey(key)
    local direction = (key == self.controls.up and 1)
                    or (key == self.controls.right and 2)
                    or (key == self.controls.down and 3)
                    or (key == self.controls.left and 4)
    local map = self.area.map
    local player = self.player
    if direction == self.player.direction then
        local x = player.x + ((direction == 2 and 1) or (direction == 4 and -1) or 0)
        local y = player.y + ((direction == 1 and -1) or (direction == 3 and 1) or 0)
        if self.tiles[map.data[y][x]].walkable then
            local object = self.area:getObjectAt(x, y)
            if not object or self.tiles[object.tile].walkable then
                player.x = x
                player.y = y
            end
        end
        if self:processEvents() then
            return
        end
        map.x = map.x + ((player.x <= map.x + self.scrollThreshold and -1)
                         or (player.x + self.scrollThreshold > map.x + self.width and 1)
                         or 0)
        map.y = map.y + ((player.y <= map.y + self.scrollThreshold and -1)
                         or (player.y + self.scrollThreshold > map.y + self.height and 1)
                         or 0)
    end
    self.player.direction = direction
end

function Coyote:handleEventKey()
    self:processEvents(true)
end

function Coyote:processEvents(keyPressed)
    for i = 1, #self.area.events do
        local event = self.area.events[i]
        if event.x == self.player.x
        and event.y == self.player.y
        and event.keyPress == (keyPressed or false) then
            if not event.direction
            or event.direction == self.player.direction then
                event.callback()
                return true
            end
        end
    end
end

function Coyote:setPlayer(tile, x, y, offsetX, offsetY, direction)
    local player = self.player
    player.tile = tile
    player.x = x
    player.y = y
    player.offset = {x = offsetX or 0, y = offsetY or 0}
    player.direction = direction or 3
end

function Coyote:setArea(area)
    self.area = area
end

function Coyote:movePlayer(x, y)
    self.player.x = x
    self.player.y = y
end

function Coyote:relativeToAbsolutePosition(x, y)
    return ((x - self.area.map.x - 1) * self.tileSize) + self.x,
           ((y - self.area.map.y - 1) * self.tileSize) + self.y
end

function Coyote:drawTileMap()
    local x = self.x
    local y = self.y
    local area = self.area
    for i = area.map.y + 1, area.map.y + self.height do
        for j = area.map.x + 1, area.map.x + self.width do
            if j > 0 and j <= area.map.width and i > 0 and i <= area.map.height
            and area.map.data[i][j] > 0 then
                local tile = self.tiles[area.map.data[i][j]]
                if tile.color then
                    self.gc:setColorRGB(tile.color[1], tile.color[2], tile.color[3])
                    self.gc:fillRect(x, y, self.tileSize, self.tileSize)
                end
                if tile.sprites then
                    self.gc:drawImage(tile.sprites[1], x, y)
                end
            elseif self.outOfBoundsColor then
                self.gc:setColorRGB(self.outOfBoundsColor[1],
                                    self.outOfBoundsColor[2],
                                    self.outOfBoundsColor[3])
                self.gc:fillRect(x, y, self.tileSize, self.tileSize)
            end
            x = x + self.tileSize
        end
        x = self.x
        y = y + self.tileSize
    end
end

function Coyote:drawObjects()
    local map = self.area.map
    for name, object in pairs(self.area.objects) do
        if object.x > map.x and object.x <= map.x + self.width
        and object.y > map.y and object.y <= map.y + self.height then
            local x, y = self:relativeToAbsolutePosition(object.x, object.y)
            self.gc:drawImage(self.tiles[object.tile].sprites[object.currentSprite], x, y)
        end
    end
end

function Coyote:drawPlayer()
    local x, y = self:relativeToAbsolutePosition(self.player.x, self.player.y)
    self.gc:drawImage(self.tiles[self.player.tile].sprites[self.player.direction],
                      x + self.player.offset.x, y + self.player.offset.y)
end

function Coyote:draw()
    self:drawTileMap()
    self:drawObjects()
    self:drawPlayer()
end

Area = class()

function Area:init(super, map, x, y)
    self.super = super
    self.map = {data = map,
                width = #map[1],
                height = #map,
                x = x or 0,
                y = y or 0}
    self.objects = {}
    self.events = {}
end

function Area:newObject(name, tile, x, y)
    self.objects[name] = {tile = tile, x = x, y = y, currentSprite = 1}
end

function Area:newEvent(x, y, direction, keyPress, callback)
    table.insert(self.events, {x = x, y = y,
                               direction = direction,
                               keyPress = keyPress,
                               callback = callback})
end

function Area:getObjectAt(x, y)
    for _, object in pairs(self.objects) do
        if object.x == x and object.y == y then
            return object
        end
    end
end

function Area:moveObject(name, x, y)
    self.objects[name].x = x
    self.objects[name].y = y
end

function Area:setObjectSprite(name, spriteNumber)
    self.objects[name].currentSprite = spriteNumber
end

function Area:destroyObject(name)
    self.objects[name] = nil
end

function a1Toa2()
    coyote:setArea(a2)
    coyote:movePlayer(4, 5)
end

function a2Toa1()
    coyote:setArea(a1)
    coyote:movePlayer(12, 2)
end

function signRead()
    a2:destroyObject("blocking_bush")
end

function on.arrowKey(key)
    coyote:handleMoveKey(key)
    platform.window:invalidate()
end

function on.enterKey()
    coyote:handleEventKey()
    platform.window:invalidate()
end

local bushS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0I\166I\166I\166\0\0\165\148\165\148\165\148\0\0\0\0\165\148\165\148\165\148\0\0I\166I\166I\166I\166I\166\0\0\165\148I\166I\166\0\0\165\148\165\148\0\0I\166I\166\165\148\0\0I\166I\166I\166\0\0\0\0\165\148I\166\0\0\0\0\165\148\165\148\0\0\0\0I\166\165\148\0\0\0\0I\166\0\0\165\148\165\148\165\148\165\148\0\0\0\0\165\148\165\148\0\0\0\0\165\148\165\148\165\148\165\148\231\149\165\148I\166I\166\0\0\0\0\165\148\165\148\0\0\0\0\165\148\165\148\0\0\0\0I\166I\166\165\148\165\148I\166\0\0\0\0\0\0\0\0\165\148I\166I\166\165\148\0\0\0\0\0\0\0\0I\166\165\148\165\148\165\148\0\0\0\0\0\0\0\0\165\148I\166I\166\165\148\0\0\0\0\0\0\0\0\165\148\165\148\0\0\165\148\165\148\165\148\165\148\165\148\165\148\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148\231\149\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\165\148I\166\0\0\0\0\0\0\165\148\165\148\0\0\0\0\165\148\165\148\0\0\0\0\0\0I\166\165\148\165\148I\166I\166\0\0\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\0\0I\166I\166\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148\0\0\165\148\165\148\0\0\0\0\165\148I\166\0\0\0\0I\166\165\148\0\0\0\0\165\148\165\148\0\0\0\0\0\0\165\148I\166\0\0\165\148\165\148I\166I\166\165\148\165\148\0\0I\166\165\148\0\0\0\0I\166\0\0\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0I\166I\166I\166\0\0\0\0\0\0\0\0\0\0\165\148\165\148\0\0\0\0\0\0\0\0\0\0I\166I\166"
local flowersS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\150\215\150\215\150\215\0\0\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\150\215\0\0\150\215\150\215\150\215\0\0\150\215\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\0\0\150\215\150\215\014\170\014\170\014\170\150\215\150\215\0\0\198\153\198\153\0\0\198\153\198\153\198\153\0\0\0\0e\149\150\215\014\170\014\170\014\170\150\215e\149\0\0\198\153\0\0\198\153\198\153\198\153\0\0\0\0\0\0e\149e\149\150\215\150\215\150\215e\149e\149\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\150\215\150\215\150\215\0\0\0\0\0\0\0\0\0\0\0\0\0\0\198\153\198\153\0\0\0\0\150\215\0\0\150\215\150\215\150\215\0\0\150\215\0\0\198\153\198\153\198\153\0\0\198\153\198\153\0\0\0\0\150\215\150\215\014\170\014\170\014\170\150\215\150\215\0\0\0\0\198\153\198\153\198\153\0\0\198\153\0\0\0\0e\149\150\215\014\170\014\170\014\170\150\215e\149\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0e\149e\149\150\215\150\215\150\215e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0"
local fenceS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0I\166I\166\165\148\165\148\165\148\165\148I\166I\166I\166I\166\165\148\165\148\165\148\165\148I\166I\166I\166\165\148,\206,\206,\206,\206\165\148I\166I\166\165\148,\206,\206,\206,\206\165\148I\166\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148\201\197,\206,\206,\206,\206\201\197\165\148\165\148\201\197,\206,\206,\206,\206\201\197\165\148\165\148\165\148\201\197\201\197\201\197\201\197\165\148\165\148\165\148\165\148\201\197\201\197\201\197\201\197\165\148\165\148\165\148F\177\165\148\165\148\165\148\165\148F\177\165\148\165\148F\177\165\148\165\148\165\148\165\148F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177\201\197F\177\165\148\165\148F\177\201\197\201\197F\177\201\197F\177\165\148\165\148F\177F\177\201\197F\177\201\197F\177\165\148\165\148F\177F\177\201\197F\177\201\197F\177\165\148\165\148\165\148F\177\201\197F\177\201\197\165\148\165\148\165\148\165\148F\177\201\197F\177\201\197\165\148\165\148\231\149\165\148\165\148\165\148\165\148\165\148\165\148\231\149\231\149\165\148\165\148\165\148\165\148\165\148\165\148\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149"
local stonesS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190"
local signS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148,\206,\206\165\148\165\148\165\148\165\148\165\148\165\148\0\0\165\148,\206,\206,\206,\206,\206\165\148,\206,\206\165\148,\206,\206,\206,\206,\206\165\148\165\148,\206,\206,\206,\206,\206,\206\165\148\165\148,\206,\206,\206,\206,\206,\206\165\148\165\148,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206\165\148\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0\165\148,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206\165\148\0\0\0\0\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148,\206\165\148\0\0\0\0\165\148,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206\165\148\0\0\0\0\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148,\206\165\148\0\0\0\0\165\148,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206\165\148\0\0\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148,\206,\206\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148,\206,\206\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
local linkS = {"\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144B\170B\170B\170B\170\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\0\0\164\144B\170B\170\196\186\196\186\196\186\196\186\196\186B\170\164\144\0\0\164\144\0\0\164\144l\246\164\144\164\144B\170\196\186\196\186\196\186B\170B\170B\170B\170\164\144\164\144l\246\164\144\164\144l\246\164\144\164\144B\170\196\186B\170B\170\164\144\164\144B\170B\170B\170\164\144l\246\164\144\164\144\164\213\164\144\224\245\164\144B\170\164\144B\170B\170B\170B\170\164\144\224\245\164\144\164\213\164\144\164\144\164\213\164\213\164\144\224\245\164\144B\170\196\186\196\186\196\186\221\247B\170\164\144\164\144\164\213\164\144\164\144\164\213\164\213\164\144\164\144\224\245\164\144B\170B\170\196\186\196\186B\170\164\144\164\213\164\213\164\144\0\0\164\144\164\144\149\237\164\144\164\144\164\144\164\144B\170\196\186\196\186B\170\164\144\149\237\164\144\0\0\0\0\0\0\164\144\149\237\149\237\149\237\164\144\164\144B\170B\170\196\186\164\144\149\237\164\144\0\0\0\0\0\0\164\144d\193\164\144\149\237\149\237\149\237\164\144B\170B\170\196\186\164\144\164\144\164\144\164\144\0\0\164\144d\193d\193d\193\164\144\164\144\149\237\149\237\164\144B\170\196\186\164\144\164\144d\193d\193\164\144\164\144\164\144\164\144\164\144L\154N\163\164\144\164\144\164\144\164\144\164\144L\154\164\144d\193d\193\164\144\164\144J\238J\238\164\144L\154L\154N\163N\163N\163N\163N\163L\154\164\144d\193\164\144\0\0\164\144J\238J\238\164\144L\154L\154N\163N\163N\163N\163L\154L\154L\154\164\144\0\0\0\0\0\0\164\144\164\144H\247L\154L\154L\154L\154N\163N\163L\154L\154L\154\164\144\0\0\0\0\0\0\0\0\164\144L\154H\247H\247L\154L\154L\154H\247L\154\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144L\154L\154H\247H\247H\247L\154\164\144d\220d\220\164\144\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144L\154L\154L\154\164\144d\220d\220d\220\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144d\220\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0",
               "\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\0\0\0\0\164\144\164\144\196\186B\170B\170\164\144\0\0\0\0\0\0\0\0\164\144B\170\196\186B\170\164\144\164\144B\170\196\186\196\186B\170\224\245B\170\164\144\164\144\164\144\0\0\0\0\164\144\196\186\196\186\164\144B\170\196\186\196\186B\170B\170\224\245\224\245\164\144\149\237\149\237\164\144\0\0\164\144B\170\196\186\196\186B\170B\170B\170\224\245\224\245\224\245\224\245\164\144\149\237\149\237\164\144\0\0\0\0\164\144B\170\196\186B\170\164\144\224\245\224\245\224\245\164\144\164\144\149\237\149\237\164\144\0\0\0\0\0\0\164\144B\170B\170\164\144l\246\164\144\164\144\164\144\149\237\149\237\149\237\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144l\246\164\213\164\144\149\237\149\237\164\144\164\144\164\213\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\213\164\144\149\237\149\237\164\144\221\247\164\144l\246\164\144\0\0\0\0\0\0\0\0\164\144\149\237\164\144\164\213\164\213\164\144\164\144\164\144\221\247\164\144l\246l\246\164\144\0\0\0\0\0\0\0\0\164\144\149\237\164\144\164\213\164\213l\246l\246\164\213l\246\164\213\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\213\164\213\164\213\164\213\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144d\193d\193d\193\164\144\164\144\164\144\164\144\164\144\164\144J\238\164\144\0\0\0\0\0\0\0\0\164\144\164\144d\193d\193\164\144L\154L\154L\154L\154\164\144\164\144\0\0\0\0\0\0\0\0\164\144J\238J\238\164\144\164\144L\154L\154N\163N\163L\154\164\144\0\0\0\0\0\0\0\0\0\0\164\144J\238J\238\164\144L\154L\154N\163N\163N\163\164\144H\247\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144H\247H\247L\154N\163N\163L\154H\247L\154\164\144\164\144\0\0\0\0\0\0\164\144d\220\164\144L\154L\154H\247H\247H\247H\247L\154\164\144\164\213\224\245\164\144\0\0\0\0\0\0\164\144\164\144\164\144\164\144L\154L\154L\154L\154\164\144\164\213d\220\224\245\164\144\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144d\220d\220d\220\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
               "\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144B\170B\170\196\186B\170\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144B\170B\170\196\186\196\186\196\186\196\186B\170\164\144\0\0\0\0\0\0\0\0\164\144\0\0\164\144\164\144\224\245B\170B\170\196\186B\170\224\245\164\144B\170\164\144\164\144\0\0\164\144l\246\164\144\149\237\164\144\164\144\224\245\224\245\224\245\224\245\164\144\164\144B\170\164\144l\246\164\144\164\144l\246\164\144\149\237\149\237\149\237\164\144\164\144\164\144\164\144\149\237\149\237\164\144\164\144l\246\164\144\164\144\164\213l\246\164\144\149\237\149\237\149\237\149\237\149\237\149\237\149\237\149\237\164\144l\246\164\213\164\144\164\144\164\213\164\144\149\237\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\149\237\164\144\164\213\164\144\0\0\164\144\164\213\164\144\164\213\221\247\221\247\164\213\164\213\221\247\221\247\164\213\164\144\164\213\164\144\0\0\0\0\0\0\164\144\164\213\164\213\221\247\164\144l\246l\246\164\144\221\247\164\213\164\213\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\213l\246\164\144l\246l\246\164\144l\246\164\213\164\144\164\144\0\0\0\0\0\0\164\144d\193d\193\164\144\164\213l\246l\246l\246l\246\164\213\164\144\164\144d\193\164\144\0\0\0\0\164\144d\193d\193d\193\164\144\164\144\164\213\164\213\164\144\164\144\164\144d\193d\193\164\144\0\0\0\0\164\144d\193d\193\164\144\164\144L\154\164\144\164\144L\154N\163L\154\164\144d\193\164\144\0\0\0\0\164\144d\193\164\144J\238J\238\164\144L\154N\163N\163L\154L\154L\154\164\144\0\0\0\0\0\0\0\0\164\144\164\144J\238J\238\164\144L\154N\163L\154L\154H\247H\247\164\144\0\0\0\0\0\0\0\0\164\144L\154\164\144\164\144\164\144H\247H\247\164\144H\247L\154L\154\164\144\0\0\0\0\0\0\0\0\164\144\164\144L\154L\154H\247H\247H\247\164\144L\154\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144L\154L\154L\154L\154\164\144d\220d\220\224\245\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144d\220\164\144\164\144\164\144\164\144\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0",
               "\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144B\170B\170\196\186\164\144\164\144\0\0\0\0\164\144\164\144\164\144\0\0\0\0\164\144\164\144\164\144B\170\224\245B\170\196\186\196\186B\170\164\144\164\144B\170\196\186B\170\164\144\164\144\149\237\149\237\164\144\224\245\224\245B\170B\170\196\186\196\186B\170\164\144\196\186\196\186\164\144\0\0\164\144\149\237\149\237\164\144\224\245\224\245\224\245\224\245B\170B\170B\170\196\186\196\186B\170\164\144\0\0\0\0\164\144\149\237\149\237\164\144\164\144\224\245\224\245\224\245\164\144B\170\196\186B\170\164\144\0\0\0\0\0\0\164\144\164\144\149\237\149\237\149\237\164\144\164\144\164\144l\246\164\144B\170B\170\164\144\0\0\0\0\0\0\164\144\164\213\164\144\164\144\149\237\149\237\164\144\164\213l\246\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144l\246\164\144\221\247\164\144\149\237\149\237\164\144\164\213\164\144\164\144\0\0\0\0\0\0\0\0\164\144l\246l\246\164\144\221\247\164\144\164\144\164\144\164\213\164\213\164\144\149\237\164\144\0\0\0\0\0\0\0\0\164\144\164\213l\246\164\213l\246l\246\164\213\164\213\164\144\149\237\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\213\164\213\164\213\164\213\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144J\238\164\144\164\144\164\144\164\144\164\144\164\144d\193d\193d\193\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144L\154L\154L\154L\154\164\144d\193d\193\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\164\144L\154N\163N\163L\154L\154\164\144\164\144J\238J\238\164\144\0\0\0\0\0\0\0\0\164\144H\247\164\144N\163N\163N\163L\154L\154\164\144J\238J\238\164\144\0\0\0\0\0\0\164\144\164\144L\154H\247L\154N\163N\163L\154H\247H\247\164\144\164\144\164\144\0\0\0\0\164\144\224\245\164\213\164\144L\154H\247H\247H\247H\247L\154L\154\164\144d\220\164\144\0\0\0\0\164\144\224\245d\220\164\213\164\144L\154L\154L\154L\154\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144d\220d\220d\220\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}
local map1 = {{2,2,2,2,2,2,2,2,2,2,2,5,2,2,2},
              {2,1,1,1,1,1,1,1,1,4,3,5,3,3,2},
              {2,1,1,1,1,3,1,1,1,4,4,5,4,4,2},
              {2,3,1,5,5,5,5,5,1,1,1,5,1,1,2},
              {2,1,1,5,1,1,1,5,3,1,1,5,1,1,2},
              {2,1,1,5,1,1,1,5,1,1,1,5,1,1,2},
              {2,1,1,5,1,1,1,5,5,5,5,5,3,1,2},
              {2,1,1,5,3,1,1,1,1,1,1,1,1,1,2},
              {2,1,1,5,1,1,1,1,3,1,1,1,1,1,2},
              {2,4,4,2,4,4,1,1,1,1,1,1,3,1,2},
              {2,3,3,5,3,4,1,1,1,1,1,1,1,1,2},
              {2,2,2,5,2,2,2,2,2,2,2,2,2,2,2}}
local map2 = {{2,2,2,2,2,2},
              {2,3,1,1,1,2},
              {2,1,1,3,1,2},
              {2,1,4,1,4,2},
              {2,3,4,1,4,2},
              {2,2,2,5,2,2}}
local initialized = false
function on.paint(gc)
    if not initialized then
        coyote = Coyote(63, 26, 12, 10)
        coyote:loadTile(nil, {72, 152, 72}, true)
        local bushT = coyote:loadTile(bushS, {40, 120, 56}, false)
        coyote:loadTile(flowersS, {72, 152, 72}, true)
        coyote:loadTile(fenceS, nil, false)
        coyote:loadTile(stonesS, {160, 224, 168}, true)
        local signT = coyote:loadTile(signS, nil, false)
        local linkT = coyote:loadTile(linkS, nil, false)
        coyote:setPlayer(linkT, 2, 2, 0, -8)
        a1 = Area(coyote, map1)
        a1:newObject("sign", signT, 10, 6)
        a1:newEvent(10, 7, 1, true, signRead)
        a1:newEvent(12, 1, nil, false, a1Toa2)
        a2 = Area(coyote, map2, -3, -2)
        a2:newObject("blocking_bush", bushT, 4, 4)
        a2:newEvent(4, 6, nil, false, a2Toa1)
        coyote:setArea(a1)
        initialized = true
    end
    coyote:draw()
    gc:drawRect(62, 25, 193, 161)
end



I'll see how I can optimize it if I find some way to do that...

edit : oh well, your code really looks nice already !
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on December 25, 2011, 09:05:01 am
Thanks a lot! :)
BTW, is it me or is the formatting messed up?
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: DJ Omnimaga on December 25, 2011, 09:40:37 am
In June 2012, you might have to change the Coyotes name to Nordiques. :P

Anyway joking aside, this looks nice. I will definitively have to give this a try when I have time. Will it support full screen or will it always just use a small portion of the screen due to limitations or something else?
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on December 25, 2011, 09:51:29 am
Anyway joking aside, this looks nice. I will definitively have to give this a try when I have time. Will it support full screen or will it always just use a small portion of the screen due to limitations or something else?
Oh no, of course not. It's that small just to show off the scrolling (didn't bother to make a bigger map, maybe I should for the sake of a nicer demo). As I said it'll be a very flexible library, no restrictions.

EDIT: I updated the demo to a full screen one.
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Adriweb on December 25, 2011, 11:55:21 am
Cool :)

Also, don't use platform.gc() anymore, it won't work as much (if at all) in future versions.
Here's the same code, but using on.paint's gc :

Code: [Select]
platform.apilevel = '1.0'
Coyote = class()

function Coyote:init(x, y, width, height, options)
    options = options or {}
    self.x = x
    self.y = y
    self.width = width
    self.height = height
    self.tiles = {}
    self.controls = options.controls or {up = "up",
                                         down = "down",
                                         left = "left",
                                         right = "right"}
    self.player = {}
    self.tileSize = options.tileSize or 16
    self.scrollThreshold = options.scrollThreshold or 1
    self.outOfBoundsColor = options.outOfBoundsColor or {0, 0, 0}
    self.tileCount = 0
end

function Coyote:loadTile(sprites, color, walkable)
    self.tileCount = self.tileCount + 1
    self.tiles[self.tileCount] = {}
    local tile = self.tiles[self.tileCount]
    if type(sprites) == "string" then
        tile.sprites = {image.new(sprites)}
    elseif type(sprites) == "table" then
        tile.sprites = {}
        for i = 1, #sprites do
            tile.sprites[i] = image.new(sprites[i])
        end
    end
    tile.color = color
    tile.walkable = walkable
    return self.tileCount
end

function Coyote:handleMoveKey(key)
    local direction = (key == self.controls.up and 1)
                    or (key == self.controls.right and 2)
                    or (key == self.controls.down and 3)
                    or (key == self.controls.left and 4)
    local map = self.area.map
    local player = self.player
    if direction == self.player.direction then
        local x = player.x + ((direction == 2 and 1) or (direction == 4 and -1) or 0)
        local y = player.y + ((direction == 1 and -1) or (direction == 3 and 1) or 0)
        if self.tiles[map.data[y][x]].walkable then
            local object = self.area:getObjectAt(x, y)
            if not object or self.tiles[object.tile].walkable then
                player.x = x
                player.y = y
            end
        end
        if self:processEvents() then
            return
        end
        map.x = map.x + ((player.x <= map.x + self.scrollThreshold and -1)
                         or (player.x + self.scrollThreshold > map.x + self.width and 1)
                         or 0)
        map.y = map.y + ((player.y <= map.y + self.scrollThreshold and -1)
                         or (player.y + self.scrollThreshold > map.y + self.height and 1)
                         or 0)
    end
    self.player.direction = direction
end

function Coyote:handleEventKey()
    self:processEvents(true)
end

function Coyote:processEvents(keyPressed)
    for i = 1, #self.area.events do
        local event = self.area.events[i]
        if event.x == self.player.x
        and event.y == self.player.y
        and event.keyPress == (keyPressed or false) then
            if not event.direction
            or event.direction == self.player.direction then
                event.callback()
                return true
            end
        end
    end
end

function Coyote:setPlayer(tile, x, y, offsetX, offsetY, direction)
    local player = self.player
    player.tile = tile
    player.x = x
    player.y = y
    player.offset = {x = offsetX or 0, y = offsetY or 0}
    player.direction = direction or 3
end

function Coyote:setArea(area)
    self.area = area
end

function Coyote:movePlayer(x, y)
    self.player.x = x
    self.player.y = y
end

function Coyote:relativeToAbsolutePosition(x, y)
    return ((x - self.area.map.x - 1) * self.tileSize) + self.x,
           ((y - self.area.map.y - 1) * self.tileSize) + self.y
end

function Coyote:drawTileMap(gc)
    local x = self.x
    local y = self.y
    local area = self.area
    for i = area.map.y + 1, area.map.y + self.height do
        for j = area.map.x + 1, area.map.x + self.width do
            if j > 0 and j <= area.map.width and i > 0 and i <= area.map.height
            and area.map.data[i][j] > 0 then
                local tile = self.tiles[area.map.data[i][j]]
                if tile.color then
                    gc:setColorRGB(tile.color[1], tile.color[2], tile.color[3])
                    gc:fillRect(x, y, self.tileSize, self.tileSize)
                end
                if tile.sprites then
                    gc:drawImage(tile.sprites[1], x, y)
                end
            elseif self.outOfBoundsColor then
                gc:setColorRGB(self.outOfBoundsColor[1],
                                    self.outOfBoundsColor[2],
                                    self.outOfBoundsColor[3])
                gc:fillRect(x, y, self.tileSize, self.tileSize)
            end
            x = x + self.tileSize
        end
        x = self.x
        y = y + self.tileSize
    end
end

function Coyote:drawObjects(gc)
    local map = self.area.map
    for name, object in pairs(self.area.objects) do
        if object.x > map.x and object.x <= map.x + self.width
        and object.y > map.y and object.y <= map.y + self.height then
            local x, y = self:relativeToAbsolutePosition(object.x, object.y)
            gc:drawImage(self.tiles[object.tile].sprites[object.currentSprite], x, y)
        end
    end
end

function Coyote:drawPlayer(gc)
    local x, y = self:relativeToAbsolutePosition(self.player.x, self.player.y)
    gc:drawImage(self.tiles[self.player.tile].sprites[self.player.direction],
                      x + self.player.offset.x, y + self.player.offset.y)
end

function Coyote:draw(gc)
    self:drawTileMap(gc)
    self:drawObjects(gc)
    self:drawPlayer(gc)
end

Area = class()

function Area:init(super, map, x, y)
    self.super = super
    self.map = {data = map,
                width = #map[1],
                height = #map,
                x = x or 0,
                y = y or 0}
    self.objects = {}
    self.events = {}
end

function Area:newObject(name, tile, x, y)
    self.objects[name] = {tile = tile, x = x, y = y, currentSprite = 1}
end

function Area:newEvent(x, y, direction, keyPress, callback)
    table.insert(self.events, {x = x, y = y,
                               direction = direction,
                               keyPress = keyPress,
                               callback = callback})
end

function Area:getObjectAt(x, y)
    for _, object in pairs(self.objects) do
        if object.x == x and object.y == y then
            return object
        end
    end
end

function Area:moveObject(name, x, y)
    self.objects[name].x = x
    self.objects[name].y = y
end

function Area:setObjectSprite(name, spriteNumber)
    self.objects[name].currentSprite = spriteNumber
end

function Area:destroyObject(name)
    self.objects[name] = nil
end

function a1Toa2()
    coyote:setArea(a2)
    coyote:movePlayer(4, 5)
end

function a2Toa1()
    coyote:setArea(a1)
    coyote:movePlayer(12, 2)
end

function signRead()
    a2:destroyObject("blocking_bush")
end

function on.arrowKey(key)
    coyote:handleMoveKey(key)
    platform.window:invalidate()
end

function on.enterKey()
    coyote:handleEventKey()
    platform.window:invalidate()
end

local bushS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0I\166I\166I\166\0\0\165\148\165\148\165\148\0\0\0\0\165\148\165\148\165\148\0\0I\166I\166I\166I\166I\166\0\0\165\148I\166I\166\0\0\165\148\165\148\0\0I\166I\166\165\148\0\0I\166I\166I\166\0\0\0\0\165\148I\166\0\0\0\0\165\148\165\148\0\0\0\0I\166\165\148\0\0\0\0I\166\0\0\165\148\165\148\165\148\165\148\0\0\0\0\165\148\165\148\0\0\0\0\165\148\165\148\165\148\165\148\231\149\165\148I\166I\166\0\0\0\0\165\148\165\148\0\0\0\0\165\148\165\148\0\0\0\0I\166I\166\165\148\165\148I\166\0\0\0\0\0\0\0\0\165\148I\166I\166\165\148\0\0\0\0\0\0\0\0I\166\165\148\165\148\165\148\0\0\0\0\0\0\0\0\165\148I\166I\166\165\148\0\0\0\0\0\0\0\0\165\148\165\148\0\0\165\148\165\148\165\148\165\148\165\148\165\148\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148\231\149\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\165\148I\166\0\0\0\0\0\0\165\148\165\148\0\0\0\0\165\148\165\148\0\0\0\0\0\0I\166\165\148\165\148I\166I\166\0\0\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\0\0I\166I\166\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148\0\0\165\148\165\148\0\0\0\0\165\148I\166\0\0\0\0I\166\165\148\0\0\0\0\165\148\165\148\0\0\0\0\0\0\165\148I\166\0\0\165\148\165\148I\166I\166\165\148\165\148\0\0I\166\165\148\0\0\0\0I\166\0\0\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0I\166I\166I\166\0\0\0\0\0\0\0\0\0\0\165\148\165\148\0\0\0\0\0\0\0\0\0\0I\166I\166"
local flowersS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\150\215\150\215\150\215\0\0\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\150\215\0\0\150\215\150\215\150\215\0\0\150\215\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\0\0\150\215\150\215\014\170\014\170\014\170\150\215\150\215\0\0\198\153\198\153\0\0\198\153\198\153\198\153\0\0\0\0e\149\150\215\014\170\014\170\014\170\150\215e\149\0\0\198\153\0\0\198\153\198\153\198\153\0\0\0\0\0\0e\149e\149\150\215\150\215\150\215e\149e\149\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0\0\0\150\215\150\215\150\215\0\0\0\0\0\0\0\0\0\0\0\0\0\0\198\153\198\153\0\0\0\0\150\215\0\0\150\215\150\215\150\215\0\0\150\215\0\0\198\153\198\153\198\153\0\0\198\153\198\153\0\0\0\0\150\215\150\215\014\170\014\170\014\170\150\215\150\215\0\0\0\0\198\153\198\153\198\153\0\0\198\153\0\0\0\0e\149\150\215\014\170\014\170\014\170\150\215e\149\0\0\0\0\0\0\198\153\198\153\0\0\0\0\0\0\0\0e\149e\149\150\215\150\215\150\215e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0e\149e\149e\149\0\0\0\0"
local fenceS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0I\166I\166\165\148\165\148\165\148\165\148I\166I\166I\166I\166\165\148\165\148\165\148\165\148I\166I\166I\166\165\148,\206,\206,\206,\206\165\148I\166I\166\165\148,\206,\206,\206,\206\165\148I\166\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206\201\197,\206,\206\201\197,\206\165\148\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148,\206,\206\201\197\201\197,\206,\206\165\148\165\148\201\197,\206,\206,\206,\206\201\197\165\148\165\148\201\197,\206,\206,\206,\206\201\197\165\148\165\148\165\148\201\197\201\197\201\197\201\197\165\148\165\148\165\148\165\148\201\197\201\197\201\197\201\197\165\148\165\148\165\148F\177\165\148\165\148\165\148\165\148F\177\165\148\165\148F\177\165\148\165\148\165\148\165\148F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177F\177F\177\165\148\165\148F\177\201\197\201\197F\177\201\197F\177\165\148\165\148F\177\201\197\201\197F\177\201\197F\177\165\148\165\148F\177F\177\201\197F\177\201\197F\177\165\148\165\148F\177F\177\201\197F\177\201\197F\177\165\148\165\148\165\148F\177\201\197F\177\201\197\165\148\165\148\165\148\165\148F\177\201\197F\177\201\197\165\148\165\148\231\149\165\148\165\148\165\148\165\148\165\148\165\148\231\149\231\149\165\148\165\148\165\148\165\148\165\148\165\148\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149\231\149"
local stonesS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\0\0\0\0\0\0\0\0\0\0\0\0\0\0\210\190\210\190\0\0\0\0\210\190\0\0\0\0\210\190\210\190\210\190\0\0\0\0\0\0\0\0\0\0\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190\210\190"
local signS = "\016\0\0\0\016\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148,\206,\206\165\148\165\148\165\148\165\148\165\148\165\148\0\0\165\148,\206,\206,\206,\206,\206\165\148,\206,\206\165\148,\206,\206,\206,\206,\206\165\148\165\148,\206,\206,\206,\206,\206,\206\165\148\165\148,\206,\206,\206,\206,\206,\206\165\148\165\148,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206\165\148\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0\165\148,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206\165\148\0\0\0\0\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148,\206\165\148\0\0\0\0\165\148,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206,\206\165\148,\206\165\148\0\0\0\0\165\148,\206\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148,\206\165\148\0\0\0\0\165\148,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206,\206\165\148\0\0\0\0\0\0\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148,\206,\206\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148,\206,\206\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\165\148\165\148\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
local linkS = {"\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144B\170B\170B\170B\170\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\0\0\164\144B\170B\170\196\186\196\186\196\186\196\186\196\186B\170\164\144\0\0\164\144\0\0\164\144l\246\164\144\164\144B\170\196\186\196\186\196\186B\170B\170B\170B\170\164\144\164\144l\246\164\144\164\144l\246\164\144\164\144B\170\196\186B\170B\170\164\144\164\144B\170B\170B\170\164\144l\246\164\144\164\144\164\213\164\144\224\245\164\144B\170\164\144B\170B\170B\170B\170\164\144\224\245\164\144\164\213\164\144\164\144\164\213\164\213\164\144\224\245\164\144B\170\196\186\196\186\196\186\221\247B\170\164\144\164\144\164\213\164\144\164\144\164\213\164\213\164\144\164\144\224\245\164\144B\170B\170\196\186\196\186B\170\164\144\164\213\164\213\164\144\0\0\164\144\164\144\149\237\164\144\164\144\164\144\164\144B\170\196\186\196\186B\170\164\144\149\237\164\144\0\0\0\0\0\0\164\144\149\237\149\237\149\237\164\144\164\144B\170B\170\196\186\164\144\149\237\164\144\0\0\0\0\0\0\164\144d\193\164\144\149\237\149\237\149\237\164\144B\170B\170\196\186\164\144\164\144\164\144\164\144\0\0\164\144d\193d\193d\193\164\144\164\144\149\237\149\237\164\144B\170\196\186\164\144\164\144d\193d\193\164\144\164\144\164\144\164\144\164\144L\154N\163\164\144\164\144\164\144\164\144\164\144L\154\164\144d\193d\193\164\144\164\144J\238J\238\164\144L\154L\154N\163N\163N\163N\163N\163L\154\164\144d\193\164\144\0\0\164\144J\238J\238\164\144L\154L\154N\163N\163N\163N\163L\154L\154L\154\164\144\0\0\0\0\0\0\164\144\164\144H\247L\154L\154L\154L\154N\163N\163L\154L\154L\154\164\144\0\0\0\0\0\0\0\0\164\144L\154H\247H\247L\154L\154L\154H\247L\154\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144L\154L\154H\247H\247H\247L\154\164\144d\220d\220\164\144\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144L\154L\154L\154\164\144d\220d\220d\220\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144d\220\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0",
               "\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\0\0\0\0\164\144\164\144\196\186B\170B\170\164\144\0\0\0\0\0\0\0\0\164\144B\170\196\186B\170\164\144\164\144B\170\196\186\196\186B\170\224\245B\170\164\144\164\144\164\144\0\0\0\0\164\144\196\186\196\186\164\144B\170\196\186\196\186B\170B\170\224\245\224\245\164\144\149\237\149\237\164\144\0\0\164\144B\170\196\186\196\186B\170B\170B\170\224\245\224\245\224\245\224\245\164\144\149\237\149\237\164\144\0\0\0\0\164\144B\170\196\186B\170\164\144\224\245\224\245\224\245\164\144\164\144\149\237\149\237\164\144\0\0\0\0\0\0\164\144B\170B\170\164\144l\246\164\144\164\144\164\144\149\237\149\237\149\237\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144l\246\164\213\164\144\149\237\149\237\164\144\164\144\164\213\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\213\164\144\149\237\149\237\164\144\221\247\164\144l\246\164\144\0\0\0\0\0\0\0\0\164\144\149\237\164\144\164\213\164\213\164\144\164\144\164\144\221\247\164\144l\246l\246\164\144\0\0\0\0\0\0\0\0\164\144\149\237\164\144\164\213\164\213l\246l\246\164\213l\246\164\213\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\213\164\213\164\213\164\213\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144d\193d\193d\193\164\144\164\144\164\144\164\144\164\144\164\144J\238\164\144\0\0\0\0\0\0\0\0\164\144\164\144d\193d\193\164\144L\154L\154L\154L\154\164\144\164\144\0\0\0\0\0\0\0\0\164\144J\238J\238\164\144\164\144L\154L\154N\163N\163L\154\164\144\0\0\0\0\0\0\0\0\0\0\164\144J\238J\238\164\144L\154L\154N\163N\163N\163\164\144H\247\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144H\247H\247L\154N\163N\163L\154H\247L\154\164\144\164\144\0\0\0\0\0\0\164\144d\220\164\144L\154L\154H\247H\247H\247H\247L\154\164\144\164\213\224\245\164\144\0\0\0\0\0\0\164\144\164\144\164\144\164\144L\154L\154L\154L\154\164\144\164\213d\220\224\245\164\144\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144d\220d\220d\220\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
               "\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144B\170B\170\196\186B\170\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144B\170B\170\196\186\196\186\196\186\196\186B\170\164\144\0\0\0\0\0\0\0\0\164\144\0\0\164\144\164\144\224\245B\170B\170\196\186B\170\224\245\164\144B\170\164\144\164\144\0\0\164\144l\246\164\144\149\237\164\144\164\144\224\245\224\245\224\245\224\245\164\144\164\144B\170\164\144l\246\164\144\164\144l\246\164\144\149\237\149\237\149\237\164\144\164\144\164\144\164\144\149\237\149\237\164\144\164\144l\246\164\144\164\144\164\213l\246\164\144\149\237\149\237\149\237\149\237\149\237\149\237\149\237\149\237\164\144l\246\164\213\164\144\164\144\164\213\164\144\149\237\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\149\237\164\144\164\213\164\144\0\0\164\144\164\213\164\144\164\213\221\247\221\247\164\213\164\213\221\247\221\247\164\213\164\144\164\213\164\144\0\0\0\0\0\0\164\144\164\213\164\213\221\247\164\144l\246l\246\164\144\221\247\164\213\164\213\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\213l\246\164\144l\246l\246\164\144l\246\164\213\164\144\164\144\0\0\0\0\0\0\164\144d\193d\193\164\144\164\213l\246l\246l\246l\246\164\213\164\144\164\144d\193\164\144\0\0\0\0\164\144d\193d\193d\193\164\144\164\144\164\213\164\213\164\144\164\144\164\144d\193d\193\164\144\0\0\0\0\164\144d\193d\193\164\144\164\144L\154\164\144\164\144L\154N\163L\154\164\144d\193\164\144\0\0\0\0\164\144d\193\164\144J\238J\238\164\144L\154N\163N\163L\154L\154L\154\164\144\0\0\0\0\0\0\0\0\164\144\164\144J\238J\238\164\144L\154N\163L\154L\154H\247H\247\164\144\0\0\0\0\0\0\0\0\164\144L\154\164\144\164\144\164\144H\247H\247\164\144H\247L\154L\154\164\144\0\0\0\0\0\0\0\0\164\144\164\144L\154L\154H\247H\247H\247\164\144L\154\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144L\154L\154L\154L\154\164\144d\220d\220\224\245\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144d\220\164\144\164\144\164\144\164\144\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0",
               "\016\0\0\0\024\0\0\0\0\0\0\0 \0\0\0\016\0\001\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144B\170B\170\196\186\164\144\164\144\0\0\0\0\164\144\164\144\164\144\0\0\0\0\164\144\164\144\164\144B\170\224\245B\170\196\186\196\186B\170\164\144\164\144B\170\196\186B\170\164\144\164\144\149\237\149\237\164\144\224\245\224\245B\170B\170\196\186\196\186B\170\164\144\196\186\196\186\164\144\0\0\164\144\149\237\149\237\164\144\224\245\224\245\224\245\224\245B\170B\170B\170\196\186\196\186B\170\164\144\0\0\0\0\164\144\149\237\149\237\164\144\164\144\224\245\224\245\224\245\164\144B\170\196\186B\170\164\144\0\0\0\0\0\0\164\144\164\144\149\237\149\237\149\237\164\144\164\144\164\144l\246\164\144B\170B\170\164\144\0\0\0\0\0\0\164\144\164\213\164\144\164\144\149\237\149\237\164\144\164\213l\246\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144l\246\164\144\221\247\164\144\149\237\149\237\164\144\164\213\164\144\164\144\0\0\0\0\0\0\0\0\164\144l\246l\246\164\144\221\247\164\144\164\144\164\144\164\213\164\213\164\144\149\237\164\144\0\0\0\0\0\0\0\0\164\144\164\213l\246\164\213l\246l\246\164\213\164\213\164\144\149\237\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\213\164\213\164\213\164\213\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144J\238\164\144\164\144\164\144\164\144\164\144\164\144d\193d\193d\193\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144L\154L\154L\154L\154\164\144d\193d\193\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\164\144L\154N\163N\163L\154L\154\164\144\164\144J\238J\238\164\144\0\0\0\0\0\0\0\0\164\144H\247\164\144N\163N\163N\163L\154L\154\164\144J\238J\238\164\144\0\0\0\0\0\0\164\144\164\144L\154H\247L\154N\163N\163L\154H\247H\247\164\144\164\144\164\144\0\0\0\0\164\144\224\245\164\213\164\144L\154H\247H\247H\247H\247L\154L\154\164\144d\220\164\144\0\0\0\0\164\144\224\245d\220\164\213\164\144L\154L\154L\154L\154\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144d\220d\220d\220\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\164\144\164\144\164\144\164\144\164\144\164\144\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}
local map1 = {{2,2,2,2,2,2,2,2,2,2,2,5,2,2,2},
              {2,1,1,1,1,1,1,1,1,4,3,5,3,3,2},
              {2,1,1,1,1,3,1,1,1,4,4,5,4,4,2},
              {2,3,1,5,5,5,5,5,1,1,1,5,1,1,2},
              {2,1,1,5,1,1,1,5,3,1,1,5,1,1,2},
              {2,1,1,5,1,1,1,5,1,1,1,5,1,1,2},
              {2,1,1,5,1,1,1,5,5,5,5,5,3,1,2},
              {2,1,1,5,3,1,1,1,1,1,1,1,1,1,2},
              {2,1,1,5,1,1,1,1,3,1,1,1,1,1,2},
              {2,4,4,2,4,4,1,1,1,1,1,1,3,1,2},
              {2,3,3,5,3,4,1,1,1,1,1,1,1,1,2},
              {2,2,2,5,2,2,2,2,2,2,2,2,2,2,2}}
local map2 = {{2,2,2,2,2,2},
              {2,3,1,1,1,2},
              {2,1,1,3,1,2},
              {2,1,4,1,4,2},
              {2,3,4,1,4,2},
              {2,2,2,5,2,2}}
local initialized = false
function on.paint(gc)
    if not initialized then
        coyote = Coyote(63, 26, 12, 10)
        coyote:loadTile(nil, {72, 152, 72}, true)
        local bushT = coyote:loadTile(bushS, {40, 120, 56}, false)
        coyote:loadTile(flowersS, {72, 152, 72}, true)
        coyote:loadTile(fenceS, nil, false)
        coyote:loadTile(stonesS, {160, 224, 168}, true)
        local signT = coyote:loadTile(signS, nil, false)
        local linkT = coyote:loadTile(linkS, nil, false)
        coyote:setPlayer(linkT, 2, 2, 0, -8)
        a1 = Area(coyote, map1)
        a1:newObject("sign", signT, 10, 6)
        a1:newEvent(10, 7, 1, true, signRead)
        a1:newEvent(12, 1, nil, false, a1Toa2)
        a2 = Area(coyote, map2, -3, -2)
        a2:newObject("blocking_bush", bushT, 4, 4)
        a2:newEvent(4, 6, nil, false, a2Toa1)
        coyote:setArea(a1)
        initialized = true
    end
    coyote:draw(gc)
    gc:drawRect(62, 25, 193, 161)
end
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: ExtendeD on December 25, 2011, 03:50:29 pm
Good idea hoffa :)
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: yunhua98 on December 25, 2011, 06:45:11 pm
Wow.  I will definitely use this at some point.  :o
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: cyanophycean314 on January 02, 2012, 05:56:54 pm
I'm getting a 404 when trying to access the source.  :(

Are those versions of source posted by adriweb the full source and most up to date?

Nice job though  :D
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: apcalc on January 02, 2012, 06:26:01 pm
Looks nice!  Excellent work!
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Adriweb on January 02, 2012, 07:02:22 pm
It looks like his project is now named "Owl" :

https://github.com/Hoffa/Owl (https://github.com/Hoffa/Owl)
Title: Re: Coyote — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 02, 2012, 07:34:30 pm
It looks like his project is now named "Owl" :

https://github.com/Hoffa/Owl (https://github.com/Hoffa/Owl)
It indeed is, haven't had the time to edit the thread, I'm working rather silently so I can get the most important things up. It'll also have a website and I'll use LuaDoc for the documentation.
Screenshot:
Spoiler For Spoiler:
(http://bb.xieke.com/files/5/derp.png)
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: DJ Omnimaga on January 02, 2012, 07:44:05 pm
Looks quite nice so far. By the way although smooth scrolling cannot be implemented, have you tried 8 pixel scrolling or even 4 pixel scrolling?
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 02, 2012, 07:47:21 pm
Looks quite nice so far. By the way although smooth scrolling cannot be implemented, have you tried 8 pixel scrolling or even 4 pixel scrolling?
No but I have tried some sort of smooth scrolling in the past. Way too slow for what it gives back, not worth the pain of implementing it. Well, at least not a this point, maybe if Lua gets a bit faster in the future, then why not.
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: cyanophycean314 on January 02, 2012, 09:21:36 pm
Okay. Thanks!
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Nick on January 03, 2012, 02:17:11 am
i know the scrolling issues with lua, for now it's too slow, maybe some improvement on the that in the future? let us hope :)

but it's really nice, why did you change the name to owl (i like it, just to know)?
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Adriweb on January 03, 2012, 06:59:06 am
Looks quite nice so far. By the way although smooth scrolling cannot be implemented, have you tried 8 pixel scrolling or even 4 pixel scrolling?
No but I have tried some sort of smooth scrolling in the past. Way too slow for what it gives back, not worth the pain of implementing it. Well, at least not a this point, maybe if Lua gets a bit faster in the future, then why not.
Smooth scrolling for the character's sprite is easily possible... just a for loops over the coordinates from source to destination (maybe with actually a partial window:invalidate() to accelerate the specific screen part refresh)
But yeah, smooth scrolling for the rest (background and tiles) would indeed be slow.
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 03, 2012, 07:08:14 am
but it's really nice, why did you change the name to owl (i like it, just to know)?
I like owls and it's shorter, and somehow feels a lot less clumsy.

Looks quite nice so far. By the way although smooth scrolling cannot be implemented, have you tried 8 pixel scrolling or even 4 pixel scrolling?
No but I have tried some sort of smooth scrolling in the past. Way too slow for what it gives back, not worth the pain of implementing it. Well, at least not a this point, maybe if Lua gets a bit faster in the future, then why not.
Smooth scrolling for the character's sprite is easily possible... just a for loops over the coordinates from source to destination (maybe with actually a partial window:invalidate() to accelerate the specific screen part refresh)
But yeah, smooth scrolling for the rest (background and tiles) would indeed be slow.
My experience with partially updating the screen is that it is pointless. The thing is the TI-Nspire stupidly clears the whole screen before calling on.paint, which means I am required to "draw" (or rather, copy the stuff into some buffer) the whole screen every single time anyway. That's what takes a lot of CPU time, not the actual flipping of the screen. So, just scrolling the characters would be just as slow as scrolling the background (unless I had some blank background).
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Jim Bauwens on January 03, 2012, 07:19:57 am
This is not the case if you only invalidate a certain spot (by giving arguments to invalidate() ).
I've made some stuff with it (smooth scrolling) and it works very good.
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 03, 2012, 07:38:22 am
This is not the case if you only invalidate a certain spot (by giving arguments to invalidate() ).
I've made some stuff with it (smooth scrolling) and it works very good.
I'd like to see how you do that, as this simple example does clear the whole screen whenever I press the enter key:
Code: [Select]
sprite = image.new("some 318*212 ti image")
drawn = false

function on.enterKey()
    platform.window:invalidate(10, 10, 10, 10)
end

function on.paint(gc)
    if not drawn then
        gc:drawImage(sprite, 0, 0)
        drawn = true
    end
end
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Nick on January 03, 2012, 07:41:08 am
well, you make drawn true when painting, so when you press enter, the drawn isn't false anymore and the sprite won't get drawn, just change that drawn=true in =false (or just delete it) and it should work
you still have to say what it has to paint on the screen..

the rest of the code is correct imo
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 03, 2012, 07:44:29 am
well, you make drawn true when painting, so when you press enter, the drawn isn't false anymore and the sprite won't get drawn, just change that drawn=true in =false (or just delete it) and it should work

the rest of the code is correct imo
Well that was to show that it does clear the screen every time, which is absolutely dumb speed-wise (i.e. I am forced to recopy all the data to the screen no matter what).
EDIT: If only TI had made their library simple and hassle-free like SDL, it would loads better.
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Jim Bauwens on January 03, 2012, 07:51:22 am
Your code works with me, although I did not use a fullscreen picture (32*32).
When pushing enter only a 10*10 square is cleared.

Edit:
Also, you can expect improvement in the next OS release.
TI did not create Lua for game programming, so its not hard to understand that its not optimized for games.
Anyway, I don't have any problem with TI.Image.
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 03, 2012, 08:10:25 am
Your code works with me, although I did not use a fullscreen picture (32*32).
When pushing enter only a 10*10 square is cleared.

Edit:
Also, you can expect improvement in the next OS release.
TI did not create Lua for game programming, so its not hard to understand that its not optimized for games.
Anyway, I don't have any problem with TI.Image.
Actually I tried it on the official emulator, maybe the behavior is different on the actual hardware. Once I return home I'll try it on the calculator, so hopefully that was the reason why it didn't seem to work. Thanks for clearing that up anyway.
Hopefully they will indeed improve it in the next OS!
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: Jim Bauwens on January 03, 2012, 08:13:11 am
Ah, yes. I never use the official emulator because I can't trust it :)

And about improving stuff, they are adding some nice stuff :)
Title: Re: Owl — A fast, lightweight, and flexible tile map engine for the TI-Nspire
Post by: hoffa on January 05, 2012, 01:55:05 pm
Just to let you know, Owl now runs at a good 50 FPS (from a previous 9 FPS) when not scrolling (thanks to jimbauwens for clearing me up).
Here is a small demo you can try out yourself to see how it runs speed-wise: http://bb.xieke.com/files/1/owl_test.tns (http://bb.xieke.com/files/1/owl_test.tns)
(The code itself is crappy, but I quickly did something dirty so I have a good base from which to write clean code)
It won't work on the official TI-Nspire emulator though, so you have to try it on the actual hardware if you want to actually see something. Also I changed Link to a Link that is the size of a tile (16x16 in this case), as it is currently too much of a mess to deal with arbitrary sized sprites.
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: DJ Omnimaga on January 05, 2012, 03:03:53 pm
Interesting. Could you sum up how you got to improve the speed? Also does it use any undocumented tricks? Because maybe that won't work in future OSes then :(

EDIT Weird I don't notice much of a frame difference. Is it just due to the getkey speed limitation and lack of smooth character movement?
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: hoffa on January 05, 2012, 03:10:04 pm
Interesting. Could you sum up how you got to improve the speed? Also does it use any undocumented tricks? Because maybe that won't work in future OSes then :(
Well it basically keeps track of tiles that need to be redrawn and only refreshes that part of the screen (which doesn't work on the official emulator). That speeds things up a lot. No undocumented stuff.
Edit: that also means that at some point I'll be able to add a feature to use animations for the characters, as it won't really slow things down.
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: Jim Bauwens on January 05, 2012, 03:35:35 pm
Glad I could be of a help :)
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: hoffa on January 05, 2012, 03:59:18 pm
EDIT Weird I don't notice much of a frame difference. Is it just due to the getkey speed limitation and lack of smooth character movement?
Actually I just noticed that that TNS used the timer to refresh the screen every 0.01s (I was measuring the FPS), rather than updating after moving Link (I uploaded again and updated the link). I think why it doesn't seem to be that much faster is because of the key repeat limitation indeed. Also if I had used a map with loads of sprites you would have seen a huge improvement, but even now it should be quite a bit more responsive.
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: ExtendeD on February 18, 2012, 03:12:38 am
hoffa, could anything done with Ndless Lua extensions to improve the engine?
An alternative to the default key press detection?
Scrolling?
A wrapper to nRGBlib's drawTile8Multicolors()?
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: Jim Bauwens on February 18, 2012, 04:32:45 am
Those things definitely could be used, but maybe we could try to improve the functions/event stuff TI made, so we keep compatibility.
I guess this is a bit more complex, but it might be worth the try :D
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: Yeong on February 18, 2012, 09:48:02 am
[offtopic]
hoffa, I wonder why you have the North Korea propaganda poster ???
[/offtopic]
dang, I really have to learn Lua X.x
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: DJ Omnimaga on February 19, 2012, 02:58:20 am
EDIT Weird I don't notice much of a frame difference. Is it just due to the getkey speed limitation and lack of smooth character movement?
Actually I just noticed that that TNS used the timer to refresh the screen every 0.01s (I was measuring the FPS), rather than updating after moving Link (I uploaded again and updated the link). I think why it doesn't seem to be that much faster is because of the key repeat limitation indeed. Also if I had used a map with loads of sprites you would have seen a huge improvement, but even now it should be quite a bit more responsive.
You should make a demo where the character gradually moves from a tile to another like in some RPGs. I wonder how smooth it would be on-calc.
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: Eiyeron on February 19, 2012, 05:36:12 am
I did this: a smooth tile by tile movement a la Pokemon, I thought that would be hard to code, but no!

I made something like this
Code: [Select]
If getkey
Set movement distance in one var
End
Else
Move by one pixel along the direction
Decrease the movement variable

The trick is to define movement if only the movements variables (not the positions) are null.
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: DJ Omnimaga on February 19, 2012, 05:38:29 am
In Lua you mean? Because the issue in Nspire Lua (for now) is that there could possibly be some delay between each moves. It would be nice to test, but if the character moves smoothly between tiles, but stops for 0.1 second between every tile, it probably won't look great unless you have a walking animation where your sprite does two step between each tile and the animation shows him stop for a bit in the middle of a tile.
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: Eiyeron on February 19, 2012, 06:28:16 am
Made That with axe, but should be easily portable...
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: Jim Bauwens on February 19, 2012, 09:05:01 am
Well, what I did in my bombermaze thing is move the character 4px (or a bit more) each time you press.
But this is done smoothly, using the timer. So, it feels quite responsive and looks good :)
Title: Re: Owl — A fast, lightweight, and flexible game engine for the TI-Nspire
Post by: hoffa on March 09, 2012, 05:50:12 am
Oh wow didn't notice there were new posts here. Owl is on hold while I work on the SDL port, so don't expect any updates right now.

hoffa, could anything done with Ndless Lua extensions to improve the engine?
An alternative to the default key press detection?
Scrolling?
A wrapper to nRGBlib's drawTile8Multicolors()?
I think I'll keep this project as TI-Nspire's official Lua only.

[offtopic]
hoffa, I wonder why you have the North Korea propaganda poster ???
[/offtopic]
It's ironical; I found the NK propaganda videos very amusing. Beware of anything I say. I'm also supporting the Free People of the Democratic People's Republic of Korea in their heroic struggle to crush the American Imperialists.