Million Tile Engine Beta Release

Azmar, there are two bugs in the current release related to the problem you’re having. The first is that getSprites always returns a table whether it finds anything or not. you can fix this by going to line 814 and replacing the line return table with:

if #table \> 0 then return table end

The second is a bug which adds “1” to the end of a Tiled Object’s name when it is drawn. The bug alters the name of the sprite, but not the name of the Tiled Object. If you go to line ~1376 you’ll see this block of code:

local spriteName = setup.name if not spriteName or spriteName == "" then spriteName = ""..sprite.x.."\_"..sprite.y.."\_"..layer end if sprites[spriteName] then local tempName = spriteName local counter = 1 while sprites[tempName] do tempName = ""..spriteName..counter counter = counter + 1 end spriteName = tempName end

Replace it with the following:

local spriteName = sprite.name or setup.name if not spriteName or spriteName == "" then spriteName = ""..sprite.x.."\_"..sprite.y.."\_"..layer end if sprites[spriteName] and sprites[spriteName] ~= sprite then local tempName = spriteName local counter = 1 while sprites[tempName] do tempName = ""..spriteName..counter counter = counter + 1 end spriteName = tempName end

Kumarks, I would need to see enough of your code to put the bit you posted into context in order to help you with it. If you’d like to email the project to me I’ll have a look at it for you. 

Is there a tool to create levels?

The tool of choice for creating maps is Tiled. http://www.mapeditor.org

On an unrelated note, I just discovered that apparently I’d maxed out the number of conversations / PM’s I can store. I rather wish I’d been notified by email or something, and it bothers me to think people may have tried to PM me and found that they couldn’t. At any rate my inbox is now clear and should be accepting PM’s again.

Excellent!  Thanks!  That’s just what I needed!

Yay it finally destroys the freaken pot!! :slight_smile: Thanks a ton!

mte.removeSprite(potObject, false) physics.removeBody( potObject ) --potObject = nil ----------------------------------- mte.removeSprite(potObject, false) physics.removeBody( potObject ) potObject = nil

The above remove part works, but if I try to potObject = nil to totally get rid of it I get an error MTE.lua:1243 attempt to index local ‘sprite’ a nil value, also if I ever try mte.removeSprite(potObject, true) *true part* even when I don’t nil it out  I also get a seperate error mte.lua:1262: attempt to call method ‘removeSelf’ a nil value, but will always work for false.

This has been happening for my other parts of my game too when trying to remove stuff and I been doing mte.removeSprite(event, false) everywhere, but I don’t know why the true part will always give back an error.

Just bought MTE…can’t wait to get it all up and running. Is the “map rotate” feature a future development, or am I missing something in my reading of the APIs?

Hello Dave,

Which map rotate feature are you referring to, specifically? You can rotate a map by changing the rotation property of the map’s masterGroup like so:

local mapObj = mte.getMapObj() mapObj.rotation = 45

Wow…thanks for the fast response. I can see that the engine is very powerful and worth every cent (in fact worth every penny of the GBP £20.26). Good work.

Dave

Hi Dyson,

I have Two sprites moving opposite to each other . I would like to find the collision between them , when they reach a distance of one tile. How can i do it ?

Thanks,

Kumar KS. 

Hi Dyson,

As i asked earlier i am using spine with MTE , When i add  more characters in my map, there is some lag in the movement when the characters are under the camera . Why is this problem occurring ? Is there any solution to over come.

Thanks,

Kumar KS. 

That is a problem with the really sloppy early code for Spine. You’ll notice similar lag if you insert a spine character into a scroll view.

Hello I just bought this engine, first impressions of everything it for sure delivers what it says. All demo’s run perfectly/flawless on device for performance and documentation is actually pretty solid to easily find what I want.

Quick question all I did was was run Castle Demo and I also uploaded it to my phone, why is there that black line over the main sprite for both device and simulator, definitely don’t want that. How do I get rid of it?

Also I wanted to reload monsters/zones as I get to certain areas (like zelda), not have one giant zone so I can get monsters to respawn at certain points, possibly only load up zones/monsters when I get to edge of maps. How would I approach this, through the stitching method? Or can MTE handle this through a totally different method?

Hello Azmar, I’m glad you’re liking MTE so far!

The black line is an edge artifact caused by OpenGL linear interpolation used to scale 2D graphics. If you look at spriteSheet.png you’ll notice that all the sprite animation frames have shadows baked into them. What you’re seeing is the very bottom of the shadow on the the frame above the current animation frame. You can fix this one of two ways. First, you can use a program such as TexturePacker to generate an extruded imagesheet. Extrusion adds a perimeter of transparent pixels around each imagesheet frame. Other than extruding the imagesheet, you can set CoronaSDK to use nearest neighbor interpolation:

display.setDefault("magTextureFilter", "nearest") display.setDefault("minTextureFilter", "nearest")

You could approach spawning/despawning monsters dozens of different ways. This is a gameplay mechanic beyond the scope of MTE. I whipped up a quick-and-dirty implementation to see what it might entail:

--Get the map and set the size of your map regions/screens local map = mte.getMap() local regionSize = 16 --Define your sprites local spriteTemplates = { { "spriteSheet.png", {width = 32, height = 32, numFrames = 96}, { {name = "0", frames = {85, 86}, time = 400, loopCount = 0}, {name = "90", frames = {73, 74}, time = 400, loopCount = 0}, {name = "180", frames = {49, 50}, time = 400, loopCount = 0}, {name = "270", frames = {61, 62}, time = 400, loopCount = 0} } }, { "spriteSheet.png", {width = 32, height = 32, numFrames = 96}, { {name = "0", frames = {88, 89}, time = 400, loopCount = 0}, {name = "90", frames = {76, 77}, time = 400, loopCount = 0}, {name = "180", frames = {52, 53}, time = 400, loopCount = 0}, {name = "270", frames = {64, 65}, time = 400, loopCount = 0} } } } --Create a table for holding the sprites in a given region local spriteData = {} for x = 1, math.floor(map.width / regionSize), 1 do spriteData[x] = {} end --Add sprites to map regions 1,1 and 1,2 spriteData[1][1] = { {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, 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, 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, 1, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } spriteData[1][2] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 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, 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, 0, 0, 0, 0, 1, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } --Create array for storing active sprites local sprites = {} mte.update() local function gameLoop( event ) --Calculate the current map region local regionX, regionY = math.ceil(player.locX / regionSize), math.ceil(player.locY / regionSize) --If the player has entered a new region if not player.regionX or player.regionX ~= regionX or player.regionY ~= regionY then local time = 1000 if not player.regionX then time = 1 end mte.constrainCamera({ loc = {(regionX - 1) \* regionSize + 1, (regionY - 1) \* regionSize + 1, (regionX - 1) \* regionSize + regionSize, (regionY - 1) \* regionSize + regionSize}, time = time, transition = easing.inOutQuad }) print("Change region:", regionX, regionY) player.regionX = regionX player.regionY = regionY --Destroy the sprites from the previous region if desired for i = #sprites, 1, -1 do mte.removeSprite(sprites[i]) sprites[i] = nil end --Create the sprites for the new region if spriteData[regionX][regionY] then for x = 1, regionSize, 1 do for y = 1, regionSize, 1 do if spriteData[regionX][regionY][x][y] ~= 0 then local spriteType = spriteData[regionX][regionY][x][y] local imageSheet = spriteTemplates[spriteType][1] local frameData = spriteTemplates[spriteType][2] local spriteSheet = graphics.newImageSheet(imageSheet, frameData) local sequenceData = spriteTemplates[spriteType][3] sprites[#sprites + 1] = display.newSprite(spriteSheet, sequenceData) local setup = { kind = "sprite", layer = mte.getSpriteLayer(1), locY = (regionY - 1) \* regionSize + x, locX = (regionX - 1) \* regionSize + y } mte.addSprite(sprites[#sprites], setup) end end end end end --...the rest of the enterFrame event... end

https://www.youtube.com/watch?v=YPiD5bqCouk

Thank you very much for this exceptional answer and the video :slight_smile: I’m having lots of fun using MTE, I tried adding some more functionality to your robot movement, noticed its missing a few options (I know only demo) like holding down mouse when off dpad it should stop moving and the animation should be standing still when he stops moving in general. I know this is stuff we should be writing ourselves, and figured I could help expand the demos in a small way for beginners like me, and helps me learn lua quicker!

Lighting DEMO:

local m = “n”

local function move( event )
    if event.phase == “ended” or event.phase == “cancelled” then
        movement = nil
    elseif event.target.id then
        movement = event.target.id
        if (movement == “up”) then
            m = “u”
        elseif (movement == “down”) then
            m = “d”
        elseif (movement == “left”) then
            m = “l”
        elseif (movement == “right”) then
            m = “r”
        end
    end
  

    return true
end


local function gameLoop( event )
    if not player.isMoving then
        --MOVE PLAYER CHARACTER
        if movement then
            local xTile, yTile = player.locX + atlas[movement][1], player.locY + atlas[movement][2]
            local result = obstacle( player.level, xTile, yTile )
            if not result then
                if player.sequence ~= movement then
                    player:setSequence( movement )
                end
                player:play()
                mte.moveSpriteTo( { sprite = player, locX = xTile, locY = yTile, time = moveTime, easing = “linear” } )
            end
        else
            if (m == “u”) then
                player:setSequence(“stillUp”);
                player:pause()
            elseif (m == “d”) then
                player:setSequence(“stillDown”);
                player:pause()
            elseif (m == “l”) then
                player:setSequence(“stillLeft”);
                player:pause()
            elseif (m == “r”) then
                player:setSequence(“stillRight”);
                player:pause()
            end  
            player:pause()
        end
    end

    mte.debug()
    mte.update()
end

That fixes the animation (stillDown being a standing still down animation) and adds an option to move down facing a wall if you cannot move, still working on the holding down mouse button and stopping movement but its confusing the heck out of me with these handlers and can’t seem to solve it properly using demo, will hopefully update it when I can.

Hi Dyson,

I would like to know what all the things i have to change when i update Mte to v984-7, from its older version. I tried updating but it screwed my project, the spine animations are not playing , totally its behaving differently. 

Pls help me to sort out this. 

A quick bit of feedback. I was messing around with the Castle Demo and changing tilesets. (Accidentally), I used one tileset that was a 64x64 one that was a 32x32 and I ended up with some 64x64 tiles being culled even tough they were still partially on screen when moving around the screen. I can fully understand why this was the case and splicing the 64x64 tiles to 32x32 fixed the issue completely. Is it a feature, is it a bug…you decide.

@Azmar: A problem with setting up the code to play a “standing still” animation is that there are no standing animation frames in the imagesheet. Every frame of animation is one half of a two-frame movement animation. The third frame in each set is a duplicate of the last frame. 

Could you be more specific about what you mean by holding down the mouse button and stopping movement? The Dpad is meant to act like an analog stick- moving the mouse after clicking down on it is like dragging the analog stuck around. Movement should continue until the mouse button is release and the invisible imaginary analog stick is allowed to return to its centered position.

@kumarks102: mte.goto() is now mte.setCamera().

The map coordinates now match the original scale of the map, such that setting blockScale to 64 does not actually increase the size of the tiles to 64x64, rather it scales the group object holding the map so that the tiles appear that size on the screen. If you’re using a calculated scaleFactor from mte.worldScale and mte.blockScale you’ll have to rework those calculations to use just the native scale of your map.

sprite.getLevelPosX() and sprite.getLevelPosY() have been removed. A sprite’s x and y properties are now equal to its level position in most cases. sprite.levelPosX and sprite.levelPosY are equal to its level position in all cases.

The kind parameter of the setup table for addSprite(sprite,setup) now accepts the value “group” for sprites which are group objects composed of multiple objects. 

When you updated your project and tried to run it, did it give you any error messages?

@Dave8091: Thanks for the feedback, Dave! That is expected behavior of the culling system. You can adjust when tiles are culled by setting the cullingMargin parameter of setCamera. For example, if your map’s native scale is 32x32 and you’ve set the scale in MTE to 2, setting cullingMargin = {64, 64, 64, 64} will keep those 64x64 tiles from culling early. You want each value of cullingMargin to be half the dimension of your larger tiles, multiplied by the scale of the map.

Hi Dyson,

Mte version 0958

display.setStatusBar( display.HiddenStatusBar )

local mte = require(“mte”)

mte.enableSpriteSorting = true --Needed for Example 5.

mte.spriteSortResolution = 10

mte.loadMap(“1760_1248_32tmx.tmx”) --Load a map.

local blockScale = 24

local isoOverDraw = 1

local map = mte.getMap()

locX = math.ceil(map.width/2)

locY = math.ceil(map.height/2)

mte.setCamera({ locX = locX, locY = locY, blockScale = blockScale, isoOverDraw = isoOverDraw})

local mapProp = mte.getMap()

mte.constrainCamera({loc = {1,1,mapProp.width,mapProp.height}, holdSprite= false, transition = easing.linear, time = 300})

local image = display.newRect(locX,locY, 20, 50)

local setup = {

kind = “sprite”, 

layer =  mte.getSpriteLayer(1), 

locX = locX, 

locY = locY,

levelWidth = 64,

levelHeight = 64,

name = “player”

}

mte.addSprite(image, setup)

mte.setCameraFocus(image)

local cancelMovement = function(event)

mte.cancelSpriteMove(image)

mte.moveSpriteTo({sprite = image, locX = math.random(1,50), locY =  math.random(1,30), time = 3000})

end

timer.performWithDelay(3000, cancelMovement,-1)

local gameLoop = function(event)

mte.update() --Required to process camera and display map.

mte.debug() --Displays onscreen position/fps/memory text.

end

Runtime:addEventListener(“enterFrame”, gameLoop)

This is the code which i am using as a sample program. Tile size is 32x32, When my  object is under the constrain camera there is some lag y is that happening . Pls check and tell me as soon as possible.

That reminds me, Kumarks, you also have to change:

local mte = require("mte")

to:

local mte = require("mte").createMTE()

When you upgrade from 0v958 to 0v984.

I tried your code using 0v984 and did not experience any lag. Is the lag happening in the simulator or on an actual phone or tablet? How many layers are there in your map, and what does the “Total Tiles” debug readout say when you’re experiencing the lag? Could you post the contents of your config.lua?

Edit: Can I make objects or sprite in Tiled as my *NPC’s/monsters* and lets say influence them with mte.moveSpriteTo ? I have seen the examples for creating them in the main etc to move them, but would like to do it through Tiled. Having troubles identifying the sprite/object in my code through Tiled.

 I set sprites to layer 2 following the demo code, and I know my guy starts at layer one following the castle demo, if I give them physics.addBody(dynamic…etc), their physics are influenced by every layer above and beneath it and my character can interact with them layers below and above them…how do I make sure I can only interact with them if I am on the same layer as them and make sure they are on a specific layer and stay on that layer?

Also been doing my “pathfinding” based on light sources from sprites, it makes a lot of sense to do it this way and can easily implement, but I been noticing a good chunk of fps drop with doing this method, especially when i start going nuts on the dpad with all these lightListeners. I made sure to change the location of my functions above and below certain parts of main.lua etc, which makes a difference but still a noticeable drop of fps. Should I not be doing this through light sources?