Huge map support
Demonstrating how well Qiso performs with a 1000x1000 tile grid of 256x192px grass sprites and 50 animated NPC sprites from a 2048x4096px sheet of 64 256x512px frames.
Qiso looks after all of the complex stuff for you. The entire code for this demo app is shown below. Documentation for all of these functions is available from the function reference on the right.
-- First, tell qisoengine where maps and sprite files are.
qiso.setAssetsFolder("assets")
-- Load a Lua formatted Tiled Map Editor tilemap into a Qiso map.
qiso.loadTiledMap("sample-tilemap-huge")
-- Load a spritemap for use as a character. Sequences must be given compass names, like this...
local wizardMap = graphics.newImageSheet(qiso.getAssetsFolder() .. "/wizard.png", { width = 256, height = 512, numFrames = 64, border = 0 })
local wizardSprites = {
{ name = 'standing-north', frames = { 25 } },
{ name = 'standing-north-east', frames = { 17 } },
{ name = 'standing-east', frames = { 9 } },
{ name = 'standing-south-east', frames = { 1 } },
{ name = 'standing-south', frames = { 57 } },
{ name = 'standing-south-west', frames = { 49 } },
{ name = 'standing-west', frames = { 41 } },
{ name = 'standing-north-west', frames = { 33 } },
{ name = 'walking-north', frames = { 25, 26, 27, 28, 29, 30, 31, 32 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-north-east', frames = { 17, 18, 19, 20, 21, 22, 23, 24 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-east', frames = { 9, 10, 11, 12, 13, 14, 15, 16 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south-east', frames = { 1, 2, 3, 4, 5, 6, 7, 8 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south', frames = { 57, 58, 59, 60, 61, 62, 63, 64 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south-west', frames = { 49, 50, 51, 52, 53, 54, 55, 56 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-west', frames = { 41, 42, 43, 44, 45, 46, 47, 48 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-north-west', frames = { 33, 34, 35, 36, 37, 38, 39, 40 }, time = 750, loopCount = 0, loopDirection = 'forward' }
}
-- Focus the camera at the middle of the world
qiso.goTo(500, 500)
-- Add some wizards...
local npcCount = 50
for n = 1, npcCount, 1 do
qiso.addCharacter("NPC" .. n, wizardMap, wizardSprites, "standing", math.random(480, 520), math.random(480, 520))
end
-- Move an NPC every 3 seconds to a random tile
local moveNPCtimer = 0
function moveNPC()
moveNPCtimer = moveNPCtimer + 1
if(moveNPCtimer == 3 * display.fps) then
-- Character to move
local randomCharacter = "NPC" .. math.random(1, npcCount)
local randomCharacterData = qiso.getCharacterData(randomCharacter)
-- We should be careful not to try to move a ridiculous amount in one go, else the path-finding algorithms might run out of memory.
-- So here we just pick a random tile that's within a 10 tile radious of the current position
local newX = math.min(1000, math.max(1, math.random(randomCharacterData.x - 10, randomCharacterData.x + 10)))
local newY = math.min(1000, math.max(1, math.random(randomCharacterData.y - 10, randomCharacterData.y + 10)))
qiso.moveCharacter(randomCharacter, newX, newY, "walking", 60)
moveNPCtimer = 0
end
end
Runtime:addEventListener('enterFrame', moveNPC)
-- Enable zooming when the screen is pinched
qiso.enablePinchZoom()
-- This is a large map, so we should be careful not to end up with too many sprites on screen at once as low-end devices might struggle
qiso.setMinZoomLevel(.5)
-- Enable camera panning when the screen is dragged
qiso.enableCameraPan()
-- Enable the main Qiso loop to render/update our world
qiso.activate()
Camera Panning, Pinch Zoom, and Character Movement
This video demonstrates Qiso's ability to load in a fairly large map built from a reasonable quality set of isometric sprites, and handle camera panning, pinch zoom, and character placement/movement within the world.
Qiso handles all of the grunt work for you, so the entire code for this demo app equates to only a few lines, as shown below. Documentation for all of these functions is available from the function reference on the right.
-- First, tell qisoengine where maps and sprite files are.
qiso.setAssetsFolder("assets")
-- Load a Lua formatted Tiled Map Editor tilemap into a Qiso map.
qiso.loadTiledMap("sample-tilemap")
-- Load a spritemap for use as a character. Sequences must be given compass names, like this...
local playerMap = graphics.newImageSheet(qiso.getAssetsFolder() .. "/wizard.png", { width = 256, height = 512, numFrames = 64, border = 0 })
local playerSprites = {
{ name = 'standing-north', frames = { 25 } },
{ name = 'standing-north-east', frames = { 17 } },
{ name = 'standing-east', frames = { 9 } },
{ name = 'standing-south-east', frames = { 1 } },
{ name = 'standing-south', frames = { 57 } },
{ name = 'standing-south-west', frames = { 49 } },
{ name = 'standing-west', frames = { 41 } },
{ name = 'standing-north-west', frames = { 33 } },
{ name = 'walking-north', frames = { 25, 26, 27, 28, 29, 30, 31, 32 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-north-east', frames = { 17, 18, 19, 20, 21, 22, 23, 24 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-east', frames = { 9, 10, 11, 12, 13, 14, 15, 16 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south-east', frames = { 1, 2, 3, 4, 5, 6, 7, 8 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south', frames = { 57, 58, 59, 60, 61, 62, 63, 64 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south-west', frames = { 49, 50, 51, 52, 53, 54, 55, 56 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-west', frames = { 41, 42, 43, 44, 45, 46, 47, 48 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-north-west', frames = { 33, 34, 35, 36, 37, 38, 39, 40 }, time = 750, loopCount = 0, loopDirection = 'forward' }
}
-- Add a character at tile 6x8 using the wizard spritemap, and then focus the camera on that tile.
qiso.addCharacter("Player", playerMap, playerSprites, "standing", 6, 8)
qiso.goTo(6, 8)
-- Create an open/close door animation as the character passes through those tiles, by setting spritesheet frame replacements.
qiso.replaceOnEnter(45, 61)
qiso.replaceOnEnter(46, 62)
qiso.replaceOnEnter(47, 63)
qiso.replaceOnEnter(48, 64)
qiso.replaceOnLeave(61, 45)
qiso.replaceOnLeave(62, 46)
qiso.replaceOnLeave(63, 47)
qiso.replaceOnLeave(64, 48)
-- Walk the player to the tapped tile
function tapTile(event)
-- Get the tile located where the screen was tapped. If there is no tile here, getTile returns nil.
local tile = qiso.getTile(event.x, event.y)
if(tile ~= nil) then
-- path-find to the tapped location, using the walking sequences defined above.
qiso.moveCharacter("Player", tile.x, tile.y, "walking", 60)
end
end
-- Do something when the screen is tapped
Runtime:addEventListener('tap', tapTile)
-- Enable zooming when the screen is pinched
qiso.enablePinchZoom()
-- Enable camera panning when the screen is dragged
qiso.enableCameraPan()
-- Enable the main Qiso loop to render/update our world
qiso.activate()
Multiple Character Movement and ReplaceOnLeave() "once" Mode
This video demonstrates how you might handle NPC movement within a world, by simply picking a random tile and telling Qiso to move a random character there.
Also shows how you could use the "once" mode of replaceOnLeave() to create a door that only closes after all characters have moved away.
Again, Qiso handles everything for you. The entire code for this demo app is shown below. Documentation for all of these functions is available from the function reference on the right.
-- First, tell qisoengine where maps and sprite files are.
qiso.setAssetsFolder("assets")
-- Load a Lua formatted Tiled Map Editor tilemap into a Qiso map.
qiso.loadTiledMap("sample-tilemap")
-- Load a spritemap for use as a character. Sequences must be given compass names, like this...
local playerMap = graphics.newImageSheet(qiso.getAssetsFolder() .. "/wizard.png", { width = 256, height = 512, numFrames = 64, border = 0 })
local playerSprites = {
{ name = 'standing-north', frames = { 25 } },
{ name = 'standing-north-east', frames = { 17 } },
{ name = 'standing-east', frames = { 9 } },
{ name = 'standing-south-east', frames = { 1 } },
{ name = 'standing-south', frames = { 57 } },
{ name = 'standing-south-west', frames = { 49 } },
{ name = 'standing-west', frames = { 41 } },
{ name = 'standing-north-west', frames = { 33 } },
{ name = 'walking-north', frames = { 25, 26, 27, 28, 29, 30, 31, 32 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-north-east', frames = { 17, 18, 19, 20, 21, 22, 23, 24 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-east', frames = { 9, 10, 11, 12, 13, 14, 15, 16 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south-east', frames = { 1, 2, 3, 4, 5, 6, 7, 8 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south', frames = { 57, 58, 59, 60, 61, 62, 63, 64 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-south-west', frames = { 49, 50, 51, 52, 53, 54, 55, 56 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-west', frames = { 41, 42, 43, 44, 45, 46, 47, 48 }, time = 750, loopCount = 0, loopDirection = 'forward' },
{ name = 'walking-north-west', frames = { 33, 34, 35, 36, 37, 38, 39, 40 }, time = 750, loopCount = 0, loopDirection = 'forward' }
}
-- Add a character at tile 6x8 using the wizard spritemap, and then focus the camera on that tile.
qiso.addCharacter("Player", playerMap, playerSprites, "standing", 6, 8)
qiso.goTo(6, 8)
-- Add some NPC's from the same sprite sheet...
qiso.addCharacter("NPC1", playerMap, playerSprites, "standing", 16, 12)
qiso.addCharacter("NPC2", playerMap, playerSprites, "standing", 9, 18)
qiso.addCharacter("NPC3", playerMap, playerSprites, "standing", 10, 20)
qiso.addCharacter("NPC4", playerMap, playerSprites, "standing", 4, 10)
-- Create an open/close door animation as the characters pass through those tiles.
qiso.replaceOnEnter(45, 61)
qiso.replaceOnEnter(46, 62)
qiso.replaceOnEnter(47, 63)
qiso.replaceOnEnter(48, 64)
qiso.replaceOnLeave(61, 45, "once")
qiso.replaceOnLeave(62, 46, "once")
qiso.replaceOnLeave(63, 47, "once")
qiso.replaceOnLeave(64, 48, "once")
-- Walk the player to the tapped tile
function tapTile(event)
-- Get the tile located where the screen was tapped. If there is no tile here, getTile returns nil.
local tile = qiso.getTile(event.x, event.y)
if(tile ~= nil) then
-- path-find to the tapped location, using the walking sequences defined above.
qiso.moveCharacter("Player", tile.x, tile.y, "walking", 60)
end
end
-- Do something when the screen is tapped
Runtime:addEventListener('tap', tapTile)
-- Move an NPC every 3 seconds
local moveNPCtimer = 0
function moveNPC()
moveNPCtimer = moveNPCtimer + 1
if(moveNPCtimer == 3 * display.fps) then
-- Sample tilemap is 20x20 tiles, so pick a random number between 1 and 20 for each axis and move a random NPC there.
qiso.moveCharacter("NPC" .. math.random(1, 4), math.random(1, 20), math.random(1, 20), "walking", 60)
moveNPCtimer = 0
end
end
Runtime:addEventListener('enterFrame', moveNPC)
-- Enable zooming when the screen is pinched
qiso.enablePinchZoom()
-- Enable camera panning when the screen is dragged
qiso.enableCameraPan()
-- Enable the main Qiso loop to render/update our world
qiso.activate()