Weird Stuck Sprite Problem

Fellow MTE Users,

I’ve started adding NPC’s to my level with MTE and addSprite, but I’m getting this really weird problem where when the NPC should move offscreen it gets stuck to the side of the map. Has anyone else had this happen and know what might be the problem ?

I’ve tried turning off the world wrap but that didn’t help, and I tried adding the sprite as an imageRect but that didn’t change anything either.

Here is a video I took of the problem:

http://www.youtube.com/watch?v=vnQRZTgr-pc

Anyone have any ideas ?

The problem here is that the right edge of the culling region is visible; you can see the rightmost column of tiles disappear one after another as you move to the left and load one after another as you move right again. Sprites park when they reach the edge of the culling region in order to reduce performance overhead, but this is only ever supposed to happen offscreen.

A few questions;

Which version of MTE are you using? What device border are you using in the Corona simulator? What does your config.lua look like? Have you zoomed out or adjusted the scale of the map object?

I’m using MTE v821

The frameborder on my  simulator is the Iphone5, with the simulator zoomed out as far as possible.

I’m not using any mte zoom functions.

Here is my config.lua:

application = { content = { width = 320, height = 480, scale = "letterBox", fps = 30, --[[imageSuffix = { ["@2x"] = 2, } --]] }, --[[-- Push notifications notification = { iphone = { types = { "badge", "sound", "alert", "newsstand" } } } --]] }

Here is what i’m using to setup my world and the sprites:

function scene:willEnterScene( event ) local group = self.view --LOAD MAP ------------------------------------------------------------ mte.toggleWorldWrapX(true) mte.toggleWorldWrapY(true) mte.loadTileSet("basicTileset", "tilesets/tileset.png") print("Loading: maps/" .. worldData.nextMap .. ".json") mte.loadMap("maps/" .. worldData.nextMap .. ".json") setEnemyPool() setNPCSprites() --SETUP D-PAD ------------------------------------------------------------ controlGroup = display.newGroup() DpadBack = display.newImageRect(controlGroup, "images/dpad.png", 60, 60) DpadBack.x = 60 DpadBack.y = display.viewableContentHeight - 60 DpadUp = display.newRect(controlGroup, DpadBack.x - 12, DpadBack.y - 34, 25, 25) DpadDown = display.newRect(controlGroup, DpadBack.x - 12, DpadBack.y + 7, 25, 25) DpadLeft = display.newRect(controlGroup, DpadBack.x - 34, DpadBack.y - 13, 25, 25) DpadRight = display.newRect(controlGroup, DpadBack.x + 7, DpadBack.y - 13, 25, 25) DpadBack:toFront() --HIDE LEVELS ------------------------------------------------------------ playerSprite = player:getSprite() playerSprite:addEventListener("touch", displayMenu) layers = mte.getLayers() layerObjects = mte.getLayerObj() startPos = mte.getObject({name="startPos"}) if playerSprite.locX == nil and playerSprite.locY == nil then playerSprite.locX = tonumber(startPos[1].properties.x) + 1 playerSprite.locY = tonumber(startPos[1].properties.y) + 1 end for i = 1, #layers, 1 do if not layers[i].properties.objectLayer then end if layers[i].properties.level \> 2 then mte.fadeLayer(i, 0, 0) end end mte.goto({ locX = playerSprite.locX, locY = playerSprite.locY, blockScaleX = 32, blockScaleY = 32}) --CREATE playerSprite SPRITE ------------------------------------------------------------ setup = { kind = "sprite", layer = mte.getSpriteLayer(1), locX = playerSprite.locX, locY = playerSprite.locY, levelWidth = 32, levelHeight = 32 } mte.addSprite(playerSprite, setup) mte.setCameraFocus(playerSprite) -- CREATE NPC SPRITES ON THE MAP -- for name, npc in pairs(worldData.npcs) do setup = { kind = "sprite", layer = mte.getSpriteLayer(1), locX = npc:getLocX(), locY = npc:getLocY(), levelWidth = 32, levelHeight = 32 } mte.addSprite(npc:getSprite(), setup) end -- DETECT MOVEMENT ------------------------------------------------------------ DpadUp.id = "up" DpadDown.id = "down" DpadLeft.id = "left" DpadRight.id = "right" movement = nil battleCount = 0 DpadUp:addEventListener("touch", move) DpadDown:addEventListener("touch", move) DpadLeft:addEventListener("touch", move) DpadRight:addEventListener("touch", move) Runtime:addEventListener("enterFrame", gameLoop) end

All of my tiles are 32x32 sized tiles.

The simplest way to fix this problem would be to alter your config.lua file or use mte.zoom to zoom in a little. Both have the same effect of properly hiding the edges of the culling region.

For the config.lua, try changing your scale to zoomEven and adding xAlign and yAlign parameters as follows:

application = { content = { width = 320, height = 480, scale = "zoomEven", xAlign = "left", yAlign = "center", fps = 30, --[[imageSuffix = { ["@2x"] = 2, } --]] }, --[[-- Push notifications notification = { iphone = { types = { "badge", "sound", "alert", "newsstand" } } } --]] }

Alternatively you can use mte.zoom to scale the map to 1.1 or so.

local newScale = 1.1 local time = 1 mte.zoom(newScale, time)

Currently, MTE always expects those three config.lua properties to have those specific values. This is a remnant of MTE’s ancestor-game. In the next update I’ll improve the way it detects screen size to prevent unexpected config.lua parameters from causing these kinds of problems.

Thanks a ton, that fixed the problem. I’ll have to adjust some other assets in the game to compensate for losing some of the screen area (Menus and whatnot) but now I know it can be fixed I can tweak things to achieve the desired result.

Thanks for investigating this with me, I appreciate your hard work and support!

The problem here is that the right edge of the culling region is visible; you can see the rightmost column of tiles disappear one after another as you move to the left and load one after another as you move right again. Sprites park when they reach the edge of the culling region in order to reduce performance overhead, but this is only ever supposed to happen offscreen.

A few questions;

Which version of MTE are you using? What device border are you using in the Corona simulator? What does your config.lua look like? Have you zoomed out or adjusted the scale of the map object?

I’m using MTE v821

The frameborder on my  simulator is the Iphone5, with the simulator zoomed out as far as possible.

I’m not using any mte zoom functions.

Here is my config.lua:

application = { content = { width = 320, height = 480, scale = "letterBox", fps = 30, --[[imageSuffix = { ["@2x"] = 2, } --]] }, --[[-- Push notifications notification = { iphone = { types = { "badge", "sound", "alert", "newsstand" } } } --]] }

Here is what i’m using to setup my world and the sprites:

function scene:willEnterScene( event ) local group = self.view --LOAD MAP ------------------------------------------------------------ mte.toggleWorldWrapX(true) mte.toggleWorldWrapY(true) mte.loadTileSet("basicTileset", "tilesets/tileset.png") print("Loading: maps/" .. worldData.nextMap .. ".json") mte.loadMap("maps/" .. worldData.nextMap .. ".json") setEnemyPool() setNPCSprites() --SETUP D-PAD ------------------------------------------------------------ controlGroup = display.newGroup() DpadBack = display.newImageRect(controlGroup, "images/dpad.png", 60, 60) DpadBack.x = 60 DpadBack.y = display.viewableContentHeight - 60 DpadUp = display.newRect(controlGroup, DpadBack.x - 12, DpadBack.y - 34, 25, 25) DpadDown = display.newRect(controlGroup, DpadBack.x - 12, DpadBack.y + 7, 25, 25) DpadLeft = display.newRect(controlGroup, DpadBack.x - 34, DpadBack.y - 13, 25, 25) DpadRight = display.newRect(controlGroup, DpadBack.x + 7, DpadBack.y - 13, 25, 25) DpadBack:toFront() --HIDE LEVELS ------------------------------------------------------------ playerSprite = player:getSprite() playerSprite:addEventListener("touch", displayMenu) layers = mte.getLayers() layerObjects = mte.getLayerObj() startPos = mte.getObject({name="startPos"}) if playerSprite.locX == nil and playerSprite.locY == nil then playerSprite.locX = tonumber(startPos[1].properties.x) + 1 playerSprite.locY = tonumber(startPos[1].properties.y) + 1 end for i = 1, #layers, 1 do if not layers[i].properties.objectLayer then end if layers[i].properties.level \> 2 then mte.fadeLayer(i, 0, 0) end end mte.goto({ locX = playerSprite.locX, locY = playerSprite.locY, blockScaleX = 32, blockScaleY = 32}) --CREATE playerSprite SPRITE ------------------------------------------------------------ setup = { kind = "sprite", layer = mte.getSpriteLayer(1), locX = playerSprite.locX, locY = playerSprite.locY, levelWidth = 32, levelHeight = 32 } mte.addSprite(playerSprite, setup) mte.setCameraFocus(playerSprite) -- CREATE NPC SPRITES ON THE MAP -- for name, npc in pairs(worldData.npcs) do setup = { kind = "sprite", layer = mte.getSpriteLayer(1), locX = npc:getLocX(), locY = npc:getLocY(), levelWidth = 32, levelHeight = 32 } mte.addSprite(npc:getSprite(), setup) end -- DETECT MOVEMENT ------------------------------------------------------------ DpadUp.id = "up" DpadDown.id = "down" DpadLeft.id = "left" DpadRight.id = "right" movement = nil battleCount = 0 DpadUp:addEventListener("touch", move) DpadDown:addEventListener("touch", move) DpadLeft:addEventListener("touch", move) DpadRight:addEventListener("touch", move) Runtime:addEventListener("enterFrame", gameLoop) end

All of my tiles are 32x32 sized tiles.

The simplest way to fix this problem would be to alter your config.lua file or use mte.zoom to zoom in a little. Both have the same effect of properly hiding the edges of the culling region.

For the config.lua, try changing your scale to zoomEven and adding xAlign and yAlign parameters as follows:

application = { content = { width = 320, height = 480, scale = "zoomEven", xAlign = "left", yAlign = "center", fps = 30, --[[imageSuffix = { ["@2x"] = 2, } --]] }, --[[-- Push notifications notification = { iphone = { types = { "badge", "sound", "alert", "newsstand" } } } --]] }

Alternatively you can use mte.zoom to scale the map to 1.1 or so.

local newScale = 1.1 local time = 1 mte.zoom(newScale, time)

Currently, MTE always expects those three config.lua properties to have those specific values. This is a remnant of MTE’s ancestor-game. In the next update I’ll improve the way it detects screen size to prevent unexpected config.lua parameters from causing these kinds of problems.

Thanks a ton, that fixed the problem. I’ll have to adjust some other assets in the game to compensate for losing some of the screen area (Menus and whatnot) but now I know it can be fixed I can tweak things to achieve the desired result.

Thanks for investigating this with me, I appreciate your hard work and support!

Hey guys,

Is there a way we can just disable this animation culling functionality? I’m thinking it may be a simple hack that could  allow us to set a flag on 1 or more sprites so that they can be positioned anywhere. I need to be able to  allow sprites to start at a level position outside of the tilemap i.e -100 or similar  and then end at a level pos that is greater than the size of the map. 

I can’t implement solution above due to the config of our game (Letterbox scaling). Ive tried to set the culling bounds in goto but this doesn’t work either.

what is happening in my game (which has NPCs sliding from left to right, and right to left) is that sprites are popping onto the screen on the left side (rather than sliding on) and getting stuck at the  right side of the screen before reaching the desired location.

I am using 

self._mte.moveSprite(sprite,vc.dirx*vc.speed* dt,vc.diry*vc.speed* dt)

to move the Sprites

/Steven

This is actually unrelated to culling. At the moment the movement functions will not move a sprite to a location outside of the map. I’ll add a flag in the next update to control this behavior, but in the meantime it is pretty simple to disable. Go into mte.lua and scroll down to the moveSpriteTo() function at line 10264. You’ll see the following block of code repeated twice in this function, at lines 10291 and 10382:

if parameters.levelPosX \> layerWidth[layer] \* blockScaleX - object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX then parameters.levelPosX = layerWidth[layer] \* blockScaleX - object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX end if parameters.levelPosX \< 0 + object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX then parameters.levelPosX = 0 + object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX end

These blocks force the sprite onto the map. Comment them out to allow your sprites to leave the map/start off the map. 

Thanks,

I had actually found these lines yesterday and they work as suggested.

Having the flag implemented in the next update would be awesome.

btw, this library is spot on. Well worth the money we paid. Congrats.

/Steven 

Hey guys,

Is there a way we can just disable this animation culling functionality? I’m thinking it may be a simple hack that could  allow us to set a flag on 1 or more sprites so that they can be positioned anywhere. I need to be able to  allow sprites to start at a level position outside of the tilemap i.e -100 or similar  and then end at a level pos that is greater than the size of the map. 

I can’t implement solution above due to the config of our game (Letterbox scaling). Ive tried to set the culling bounds in goto but this doesn’t work either.

what is happening in my game (which has NPCs sliding from left to right, and right to left) is that sprites are popping onto the screen on the left side (rather than sliding on) and getting stuck at the  right side of the screen before reaching the desired location.

I am using 

self._mte.moveSprite(sprite,vc.dirx*vc.speed* dt,vc.diry*vc.speed* dt)

to move the Sprites

/Steven

This is actually unrelated to culling. At the moment the movement functions will not move a sprite to a location outside of the map. I’ll add a flag in the next update to control this behavior, but in the meantime it is pretty simple to disable. Go into mte.lua and scroll down to the moveSpriteTo() function at line 10264. You’ll see the following block of code repeated twice in this function, at lines 10291 and 10382:

if parameters.levelPosX \> layerWidth[layer] \* blockScaleX - object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX then parameters.levelPosX = layerWidth[layer] \* blockScaleX - object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX end if parameters.levelPosX \< 0 + object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX then parameters.levelPosX = 0 + object.levelWidth \* scaleFactorX \* 0.5 - object.offsetX \* scaleFactorX end

These blocks force the sprite onto the map. Comment them out to allow your sprites to leave the map/start off the map. 

Thanks,

I had actually found these lines yesterday and they work as suggested.

Having the flag implemented in the next update would be awesome.

btw, this library is spot on. Well worth the money we paid. Congrats.

/Steven