Dealing with offscreen sprites

Hey,

I’m wondering if it’s possible to use mte to move/apply physics to sprites that are currently off the screen? 

I have a beat’em up style game where a bunch of enemies are following the player, using physics-based steering. The problem I’m having is that when my enemy sprites move off the screen, suddenly they no longer receive the forces I’m applying to them. I’ve tried increasing the culling margins, but this does not seem to help. I’ve also tried using mte.moveSprite to move the sprite when it is offscreen, but this only seems to work if the sprite is very close to the edge (I’m guessing they aren’t fully offscreen yet).

Thanks!

William

Hello William,

MTE versions up to and including 0.958 were designed to freeze offscreen physics objects because when tiles move offscreen they’re culled to maintain high performance. A character standing on a platform would suddenly fall through the world as it disappears under him. Similarly, in a dungeon or maze-like map, the enemies would suddenly begin walking through offscreen walls because there aren’t any offscreen walls. Freezing the sprites when they move offscreen prevents this. These versions of MTE also contain a bug which causes the engine to ignore the cullingMargin in this situation.

If the above problems don’t apply to you, you can modify the engine file to keep the sprites from freezing. The check for offscreen sprites takes place on lines 12799 and 12800:

local screenPosX = ((screenPosX - (display.viewableContentWidth / 2)) / masterGroup.xScale) + (display.viewableContentWidth / 2) local screenPosY = ((screenPosY - (display.viewableContentHeight / 2)) / masterGroup.yScale) + (display.viewableContentHeight / 2) if not object.isMoving and (screenPosX - (object.width / 2) \> screen.right or screenPosX + (object.width / 2) \< screen.left or screenPosY - (object.height / 2) \> screen.bottom or screenPosY + (object.height / 2) \< screen.top) then object.isAwake = false --MTE control local tempPosX = object.levelPosX local tempPosY = object.levelPosY ...

If you change this check to something else which is always false, all the sprites will behave is if they’re onscreen all the time:

local screenPosX = ((screenPosX - (display.viewableContentWidth / 2)) / masterGroup.xScale) + (display.viewableContentWidth / 2) local screenPosY = ((screenPosY - (display.viewableContentHeight / 2)) / masterGroup.yScale) + (display.viewableContentHeight / 2) local test = false if test then object.isAwake = false --MTE control local tempPosX = object.levelPosX local tempPosY = object.levelPosY ...

MTE 0.980 is coming out in a few days. Aside from fixing the cullingMargin bug, the new engine rewrite can be configured so that offscreen physics objects remain active. As they move they spawn a tiny area of the map around themselves so that they can collide with it just as they would if they were onscreen.

Great! Update sounds like just what I’m looking for, will wait for it.

So I’ve been having some weird behaviour with this offscreen physics property. 

I’ve enabled it for my enemy, and now it can move offscreen. However, it seems to be messing up the tiles around it when I it moves outside the screen.

For example, here is my character standing in the map.

Now I leave this area of the map and let the enemy fly around it for a while. When I come back, some of the tiles have disappeared.

Thanks for bringing this to my attention. It looks to be related to another bug I ran into earlier today with 0v980. I’m working on a patch now.

Hello William,

MTE versions up to and including 0.958 were designed to freeze offscreen physics objects because when tiles move offscreen they’re culled to maintain high performance. A character standing on a platform would suddenly fall through the world as it disappears under him. Similarly, in a dungeon or maze-like map, the enemies would suddenly begin walking through offscreen walls because there aren’t any offscreen walls. Freezing the sprites when they move offscreen prevents this. These versions of MTE also contain a bug which causes the engine to ignore the cullingMargin in this situation.

If the above problems don’t apply to you, you can modify the engine file to keep the sprites from freezing. The check for offscreen sprites takes place on lines 12799 and 12800:

local screenPosX = ((screenPosX - (display.viewableContentWidth / 2)) / masterGroup.xScale) + (display.viewableContentWidth / 2) local screenPosY = ((screenPosY - (display.viewableContentHeight / 2)) / masterGroup.yScale) + (display.viewableContentHeight / 2) if not object.isMoving and (screenPosX - (object.width / 2) \> screen.right or screenPosX + (object.width / 2) \< screen.left or screenPosY - (object.height / 2) \> screen.bottom or screenPosY + (object.height / 2) \< screen.top) then object.isAwake = false --MTE control local tempPosX = object.levelPosX local tempPosY = object.levelPosY ...

If you change this check to something else which is always false, all the sprites will behave is if they’re onscreen all the time:

local screenPosX = ((screenPosX - (display.viewableContentWidth / 2)) / masterGroup.xScale) + (display.viewableContentWidth / 2) local screenPosY = ((screenPosY - (display.viewableContentHeight / 2)) / masterGroup.yScale) + (display.viewableContentHeight / 2) local test = false if test then object.isAwake = false --MTE control local tempPosX = object.levelPosX local tempPosY = object.levelPosY ...

MTE 0.980 is coming out in a few days. Aside from fixing the cullingMargin bug, the new engine rewrite can be configured so that offscreen physics objects remain active. As they move they spawn a tiny area of the map around themselves so that they can collide with it just as they would if they were onscreen.

Great! Update sounds like just what I’m looking for, will wait for it.

So I’ve been having some weird behaviour with this offscreen physics property. 

I’ve enabled it for my enemy, and now it can move offscreen. However, it seems to be messing up the tiles around it when I it moves outside the screen.

For example, here is my character standing in the map.

Now I leave this area of the map and let the enemy fly around it for a while. When I come back, some of the tiles have disappeared.

Thanks for bringing this to my attention. It looks to be related to another bug I ran into earlier today with 0v980. I’m working on a patch now.

Hi, 

I have just rewritten my game using latest verson of MTE and I cannot get offscreenPhysics to work, I have set offscreenPhysics = true on my sprites for the enemy and for the end point, but the enemy passes through the end point when they are off screen

Hello lukestirk,

OffscreenPhysics appears to be working on my end, at least in those situations I test for. More information would be useful. What is supposed to happen when your enemies reach the end point? Is the endpoint an obstacle or are you detecting a collision? A helpful technique for debugging this functionality is to set the scale of your map to whatever it should be at the beginning of the enterFrame, so that the map is rendered at the size it would be, and then setting the scale much lower at the end of your enterFrame so you can see the empty space around it. For example:

local mapObj = mte.getMapObj() local scale = 2 --The scale you set in setCamera. --ENTERFRAME---------------------------------------------------------------------------- local gameLoop = function(event) mapObj.xScale = scale mapObj.yScale = scale --The rest of your code... --... mapObj.xScale = scale / 4 mapObj.yScale = scale / 4 end

Make sure you have physics.setDrawMode(“hybrid”) set as well. What you should see are yellow squares around active dynamic physics objects, green squares around static physics objects (if you have any), and grey or dark/faded yellow squares around sleeping or otherwise inactive physics objects. As your enemies move offscreen their squares should remain yellow. If the endpoint is a physics object it should also remain bright yellow or green unless it is motionless. If the endpoint is motionless the square will turn dim as it sleeps, but it should light back up the moment another object- such as the enemy- touches it.

Hi, 

I have just rewritten my game using latest verson of MTE and I cannot get offscreenPhysics to work, I have set offscreenPhysics = true on my sprites for the enemy and for the end point, but the enemy passes through the end point when they are off screen

Hello lukestirk,

OffscreenPhysics appears to be working on my end, at least in those situations I test for. More information would be useful. What is supposed to happen when your enemies reach the end point? Is the endpoint an obstacle or are you detecting a collision? A helpful technique for debugging this functionality is to set the scale of your map to whatever it should be at the beginning of the enterFrame, so that the map is rendered at the size it would be, and then setting the scale much lower at the end of your enterFrame so you can see the empty space around it. For example:

local mapObj = mte.getMapObj() local scale = 2 --The scale you set in setCamera. --ENTERFRAME---------------------------------------------------------------------------- local gameLoop = function(event) mapObj.xScale = scale mapObj.yScale = scale --The rest of your code... --... mapObj.xScale = scale / 4 mapObj.yScale = scale / 4 end

Make sure you have physics.setDrawMode(“hybrid”) set as well. What you should see are yellow squares around active dynamic physics objects, green squares around static physics objects (if you have any), and grey or dark/faded yellow squares around sleeping or otherwise inactive physics objects. As your enemies move offscreen their squares should remain yellow. If the endpoint is a physics object it should also remain bright yellow or green unless it is motionless. If the endpoint is motionless the square will turn dim as it sleeps, but it should light back up the moment another object- such as the enemy- touches it.