Million-Tile Engine; any interest? Feature requests?

Okay, cool. I asked about the streaming since at least one of the videos had a loading screen and I wondered if that was strictly necessary.

“Metatile” is a “tile of tiles”, e.g. recurring n-by-n tile patterns. Example lower down On some older consoles it was a rather common compression methods, what with ROM space at such a premium, though better schemes have obviously come along.

It probably complicates the drawing process and may not help much (indeed, it may hurt). I was curious mostly because in the screenshots there were some obvious patterns going on. [import]uid: 27791 topic_id: 32457 reply_id: 134079[/import]

A room full of robots. Clicking a robot moves the camera to- and sets focus on- the robot. Moving the camera while it is focused on a moving object will move the camera in relation to the object. Easing isn’t supported at the moment. I’ll see if I can make use of the easing functions on their own instead of within transitions.

There are discontinuities on the edges of the map where sprites will disappear and reappear depending on whether they’ve looped from your perspective. The problem is cosmetic. The objects’ positions in the level are all correct. I’ll have to look into that.

I don’t plan to support 2.5D isometric maps. That would open a whole 'nother can of worms.

I looked at the NES metatiling example link. I’m always amazed by what game designers of the day were able to achieve with such incredibly limited hardware capabilities!

http://www.youtube.com/watch?v=BmgX4wKC9P4

[code]
display.setStatusBar( display.HiddenStatusBar )
local mte = require “MTE.mte”

mte.loadMap(“robotRoomSteep.json”, “json”)

mte.goto({ locX = 12, locY = 11, blockScale = 64 })

local spriteSheet = graphics.newImageSheet(“spriteSheet.png”, {width = 32, height = 32, numFrames = 96})

local touchRobot = function(event)
if event.phase == “ended” then
mte.setCameraFocus(event.target)
mte.moveCameraTo({object = event.target, time = 30})
end
end

local robots = {}

–CREATE 100 ROBOTS, SET ANIMATIONS, ETC
for i = 1, 100, 1 do
local locX = math.random(9, 41)
local locY = math.random(9, 21)
local layer = mte.getSpriteLayer(mte.getVisibleLevel(locX, locY))
local setup = {kind = “sprite”, layer = layer, locX = locX, locY = locY, sourceWidth = 32, sourceHeight = 32}
local options = {
imageSheet = spriteSheet,
sequenceData =
{
{name = “walkUp”, sheet = spriteSheet, frames = {85, 86}, time = 500, loopCount = 0},
{name = “walkDown”, sheet = spriteSheet, frames = {49, 50}, time = 500, loopCount = 0},
{name = “walkLeft”, sheet = spriteSheet, frames = {61, 62}, time = 500, loopCount = 0},
{name = “walkRight”, sheet = spriteSheet, frames = {73, 74}, time = 500, loopCount = 0}
},
xScale = mte.findScale(32, layer),
yScale = mte.findScale(32, layer)
}
robots[i] = mte.addObject(setup, options)
local direction = math.random(1, 4)
if direction == 1 then
robots[i]:setSequence(“walkUp”)
robots[i]:play()
robots[i].velX = 0
robots[i].velY = -1 * math.random(4, 8)
robots[i].direction = direction
elseif direction == 2 then
robots[i]:setSequence(“walkRight”)
robots[i]:play()
robots[i].velX = math.random(4, 8)
robots[i].velY = 0
robots[i].direction = direction
elseif direction == 3 then
robots[i]:setSequence(“walkDown”)
robots[i]:play()
robots[i].velX = 0
robots[i].velY = math.random(4, 8)
robots[i].direction = direction
elseif direction == 4 then
robots[i]:setSequence(“walkLeft”)
robots[i]:play()
robots[i].velX = -1 * math.random(4, 8)
robots[i].velY = 0
robots[i].direction = direction
end
robots[i]:addEventListener(“touch”, touchRobot)
end

local velX = 0
local velY = 0
local gameLoop = function(event)
print(“frame”)
mte.moveCamera(velX, velY)
mte.debug() --Displays red on-screen debug values

for i = 1, #robots, 1 do
local tile = mte.getTileProperties({locX = robots[i].locX, locY = robots[i].locY})
if robots[i].layer + 1 <= 14 then
if tile[robots[i].layer + 1].tile ~= 0 then
print(“climb”)
mte.changeObjectLayer(robots[i], robots[i].layer + 2)
end
end
if tile[robots[i].layer - 1].tile == 0 and robots[i].layer >= 4 then
print(“fall”)
mte.changeObjectLayer(robots[i], robots[i].layer - 2)
end
mte.moveObject(robots[i], robots[i].velX, robots[i].velY)
end
end

Runtime:addEventListener(“enterFrame”, gameLoop)

[/code] [import]uid: 99903 topic_id: 32457 reply_id: 134664[/import]

A room full of robots. Clicking a robot moves the camera to- and sets focus on- the robot. Moving the camera while it is focused on a moving object will move the camera in relation to the object. Easing isn’t supported at the moment. I’ll see if I can make use of the easing functions on their own instead of within transitions.

There are discontinuities on the edges of the map where sprites will disappear and reappear depending on whether they’ve looped from your perspective. The problem is cosmetic. The objects’ positions in the level are all correct. I’ll have to look into that.

I don’t plan to support 2.5D isometric maps. That would open a whole 'nother can of worms.

I looked at the NES metatiling example link. I’m always amazed by what game designers of the day were able to achieve with such incredibly limited hardware capabilities!

http://www.youtube.com/watch?v=BmgX4wKC9P4

[code]
display.setStatusBar( display.HiddenStatusBar )
local mte = require “MTE.mte”

mte.loadMap(“robotRoomSteep.json”, “json”)

mte.goto({ locX = 12, locY = 11, blockScale = 64 })

local spriteSheet = graphics.newImageSheet(“spriteSheet.png”, {width = 32, height = 32, numFrames = 96})

local touchRobot = function(event)
if event.phase == “ended” then
mte.setCameraFocus(event.target)
mte.moveCameraTo({object = event.target, time = 30})
end
end

local robots = {}

–CREATE 100 ROBOTS, SET ANIMATIONS, ETC
for i = 1, 100, 1 do
local locX = math.random(9, 41)
local locY = math.random(9, 21)
local layer = mte.getSpriteLayer(mte.getVisibleLevel(locX, locY))
local setup = {kind = “sprite”, layer = layer, locX = locX, locY = locY, sourceWidth = 32, sourceHeight = 32}
local options = {
imageSheet = spriteSheet,
sequenceData =
{
{name = “walkUp”, sheet = spriteSheet, frames = {85, 86}, time = 500, loopCount = 0},
{name = “walkDown”, sheet = spriteSheet, frames = {49, 50}, time = 500, loopCount = 0},
{name = “walkLeft”, sheet = spriteSheet, frames = {61, 62}, time = 500, loopCount = 0},
{name = “walkRight”, sheet = spriteSheet, frames = {73, 74}, time = 500, loopCount = 0}
},
xScale = mte.findScale(32, layer),
yScale = mte.findScale(32, layer)
}
robots[i] = mte.addObject(setup, options)
local direction = math.random(1, 4)
if direction == 1 then
robots[i]:setSequence(“walkUp”)
robots[i]:play()
robots[i].velX = 0
robots[i].velY = -1 * math.random(4, 8)
robots[i].direction = direction
elseif direction == 2 then
robots[i]:setSequence(“walkRight”)
robots[i]:play()
robots[i].velX = math.random(4, 8)
robots[i].velY = 0
robots[i].direction = direction
elseif direction == 3 then
robots[i]:setSequence(“walkDown”)
robots[i]:play()
robots[i].velX = 0
robots[i].velY = math.random(4, 8)
robots[i].direction = direction
elseif direction == 4 then
robots[i]:setSequence(“walkLeft”)
robots[i]:play()
robots[i].velX = -1 * math.random(4, 8)
robots[i].velY = 0
robots[i].direction = direction
end
robots[i]:addEventListener(“touch”, touchRobot)
end

local velX = 0
local velY = 0
local gameLoop = function(event)
print(“frame”)
mte.moveCamera(velX, velY)
mte.debug() --Displays red on-screen debug values

for i = 1, #robots, 1 do
local tile = mte.getTileProperties({locX = robots[i].locX, locY = robots[i].locY})
if robots[i].layer + 1 <= 14 then
if tile[robots[i].layer + 1].tile ~= 0 then
print(“climb”)
mte.changeObjectLayer(robots[i], robots[i].layer + 2)
end
end
if tile[robots[i].layer - 1].tile == 0 and robots[i].layer >= 4 then
print(“fall”)
mte.changeObjectLayer(robots[i], robots[i].layer - 2)
end
mte.moveObject(robots[i], robots[i].velX, robots[i].velY)
end
end

Runtime:addEventListener(“enterFrame”, gameLoop)

[/code] [import]uid: 99903 topic_id: 32457 reply_id: 134664[/import]

Wow, that is again pretty impressive. I want to be testing this ASAP! :stuck_out_tongue:

My camera focus code wasn’t using easing or transitions at all, so those do seem interesting although I’m not sure how applicable they could be. (my player character moved according to a Runtime :translate() listener, so basically the camera would move in tune with each (x,y) pixel change.

The metatiling stuff is impressive, for sure, though more of a priority for old hardware like the NES since disk space was such a huge constraint. (Along similar lines, there’s a really interesting math doc on Dragon Quest 1 where the author literally just examined the hexcode output to get a step-by-step on how decisions were calculated, which gives you an appreciation of how compact assembler is.) [import]uid: 41884 topic_id: 32457 reply_id: 135012[/import]

Something like a delayed camera follow would be cool, but the easing I mentioned was for moveCameraTo, not setFocus. I didn’t play all that many classic RPG’s, but I always found it cool when the camera moved off the player character to show the “scheming villain scheming in another room” or “the really blatantly obvious ‘secret’ switch on the wall” or etc.

I did get all the easing functions working for moveCameraTo. I also made a few changes to allow for movements greater than ~blockscale units in any direction in a single frame.

http://www.youtube.com/watch?v=l5C3mcIzSq0

mte.moveCameraTo({object = robots[robot], time = 50, easing = "inOutExpo"}) [import]uid: 99903 topic_id: 32457 reply_id: 135117[/import]

Wow, that is again pretty impressive. I want to be testing this ASAP! :stuck_out_tongue:

My camera focus code wasn’t using easing or transitions at all, so those do seem interesting although I’m not sure how applicable they could be. (my player character moved according to a Runtime :translate() listener, so basically the camera would move in tune with each (x,y) pixel change.

The metatiling stuff is impressive, for sure, though more of a priority for old hardware like the NES since disk space was such a huge constraint. (Along similar lines, there’s a really interesting math doc on Dragon Quest 1 where the author literally just examined the hexcode output to get a step-by-step on how decisions were calculated, which gives you an appreciation of how compact assembler is.) [import]uid: 41884 topic_id: 32457 reply_id: 135012[/import]

Something like a delayed camera follow would be cool, but the easing I mentioned was for moveCameraTo, not setFocus. I didn’t play all that many classic RPG’s, but I always found it cool when the camera moved off the player character to show the “scheming villain scheming in another room” or “the really blatantly obvious ‘secret’ switch on the wall” or etc.

I did get all the easing functions working for moveCameraTo. I also made a few changes to allow for movements greater than ~blockscale units in any direction in a single frame.

http://www.youtube.com/watch?v=l5C3mcIzSq0

mte.moveCameraTo({object = robots[robot], time = 50, easing = "inOutExpo"}) [import]uid: 99903 topic_id: 32457 reply_id: 135117[/import]

I’m not dead!

I’m just finishing up the documentation now. Next week I’ll toss together some demonstration code to pack with it, and then it will be more or less finished. Then I’ll have to figure out how I want to go about actually selling it. I suppose the simplest solution would be to let people send money to my PayPal and then email it to them, but I’d prefer something more automated so folks don’t have to wait for me to check my email.

The final price will be $9.99. [import]uid: 99903 topic_id: 32457 reply_id: 140344[/import]

! Huzzah! I was starting to wonder if I needed to resume tile engine work, so this would be great. [import]uid: 41884 topic_id: 32457 reply_id: 140353[/import]

Will definitely pick this up when it’s finished.

Dare I say it, I think you’re under-pricing it at $9.99, would be willing to pay at least double that to save hours and hours of work. [import]uid: 93133 topic_id: 32457 reply_id: 140359[/import]

I’m not dead!

I’m just finishing up the documentation now. Next week I’ll toss together some demonstration code to pack with it, and then it will be more or less finished. Then I’ll have to figure out how I want to go about actually selling it. I suppose the simplest solution would be to let people send money to my PayPal and then email it to them, but I’d prefer something more automated so folks don’t have to wait for me to check my email.

The final price will be $9.99. [import]uid: 99903 topic_id: 32457 reply_id: 140344[/import]

! Huzzah! I was starting to wonder if I needed to resume tile engine work, so this would be great. [import]uid: 41884 topic_id: 32457 reply_id: 140353[/import]

Will definitely pick this up when it’s finished.

Dare I say it, I think you’re under-pricing it at $9.99, would be willing to pay at least double that to save hours and hours of work. [import]uid: 93133 topic_id: 32457 reply_id: 140359[/import]

I’m trying to get a community supported Tiled loader going… http://developer.coronalabs.com/forum/2013/01/31/basic-loader-tiled-maps-corona-json-formated
[import]uid: 51498 topic_id: 32457 reply_id: 141089[/import]

nick: Don’t make me argue the price up too! :stuck_out_tongue: Really interested to see this when it’s ready. [import]uid: 41884 topic_id: 32457 reply_id: 141203[/import]

This looks great, keep us posted! [import]uid: 84637 topic_id: 32457 reply_id: 141212[/import]

I’m trying to get a community supported Tiled loader going… http://developer.coronalabs.com/forum/2013/01/31/basic-loader-tiled-maps-corona-json-formated
[import]uid: 51498 topic_id: 32457 reply_id: 141089[/import]

nick: Don’t make me argue the price up too! :stuck_out_tongue: Really interested to see this when it’s ready. [import]uid: 41884 topic_id: 32457 reply_id: 141203[/import]

This looks great, keep us posted! [import]uid: 84637 topic_id: 32457 reply_id: 141212[/import]

Thanks for the shout-out Danny. I enjoy working within limits, because I enjoy having limits to break. I’ve seen it said many times that Corona is not a good tool for creating games using large tilemaps, and I knew immediately that something could be done about that.

Anyway, I was a little optimistic about the timeline I mentioned earlier. As usual, a few little things came up that needed my attention. The most significant change is that MTE now detects Object Layers created in Tiled and allows users to access and modify those objects. What I have been calling Objects up till now are now called Sprites to differentiate the two.

I’m working on a few example maps now. In the meantime, here are some of the reference files to look at:

API:
https://skydrive.live.com/redir?resid=73D2274FE560C959!346&authkey=!ANMCiIgC_W43Dbs

Reserved Properties:
https://skydrive.live.com/redir?resid=73D2274FE560C959!347&authkey=!AEI5sLQzVj6WzPw

Map Structure:
https://skydrive.live.com/redir?resid=73D2274FE560C959!349&authkey=!AD-sAE1HwfBwXwE

Creating Tilesets HOWTO:
https://skydrive.live.com/redir?resid=73D2274FE560C959!348&authkey=!ANTcTtww0HBCW7g

Let me know if something’s wrong with the files; I don’t use skydrive very often. [import]uid: 99903 topic_id: 32457 reply_id: 141993[/import]