Is it possible to make a listener that is fired whenever an object passes a certain x or y threshold? Basically I have lots of stars that move in a background and I only want them to relocate themselves whenever they float offscreen. Right now I am infinitely checking if all 150 of them have passed the boundaries of the screen and it is taking a huge amount of CPU to handle.
You could:
- least efficient - use a runtime enterFrame listener to check each star individually each frame
- slightly more efficient - use an optimised runtime enterFrame listener that checks the stars in batches: for example, the first 10 stars on frame 1, the second 10 stars on frame 2, the third 10 stars on frame 3, back to the first 10 stars again on frame 4 etc. This is faster than checking every single star on every frame update, and it doesn’t really matter if the star has floated offscreen for a few frames (the user can’t see them anyway).
- most efficient but involves more mathematics in the setup - when you initialise the transitions on your stars, calculate the exactly coordinate where they will have left the screen plus a safe margin - then you set up an listener at the end of transition to reposition the star.
This post was similar and contains answers that will help you solve your question:
https://forums.coronalabs.com/topic/60870-removing-object-at-certain-position/
Also, as part of an answer I gave long ago, I provided a ‘on screen’ tester:
Full answer that uses on-screen test: http://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2014/10/Texture%20Memory%20Management.zip
Just the on-screen code:
(You’ll have to dig a little to get it out).
Here is a cleaner example (I’ve answered this a few times):
https://forums.coronalabs.com/topic/55035-how-to-determine-if-sprite-is-on-screen/
I don’t think any of this is what I am looking for. I know how to tell if the star is on the screen or not. I have functionality the exact way I want it right now, my problem is efficiency. I basically want 4 listeners that respectively get called if one of the stars go off each of the 4 edges of the screen. Is this possible?
Looking at the list of events, all I can think of right now is giving each star a physics body and then making physics body rectangles at each of the 4 edges of the screen and detecting a collision between a star and one of the edge rectangles. I feel like this would work but seems very backwards.
You’ll have to write your own testing code. There is no listener for this.
Consider this. I assume you want this for a speedup? However, if the SDK were already testing this, it would be a costly feature only occasionally used.
Sorry, but you’ll want to write your own and simply skip testing every other frame or so to get better performance. Also, optimized your test calculations for better results. The code I’ve given you can be further optimized.
PS -
If you want to use physics,
-
Create a single static body that covers the whole region you want to consider on-screen. (set isvisible to false)
-
Make that body a sensor (obj.isSensor = true)
-
Add bodies and collision listeners to the ‘to be tested’ objects.
-
Check for “began” and “ended” phases, where “began” indicates entered on screen space, and “ended” indicates left on-screen space.
I’m trying out this physics solution, I’ll let you know how it turns out.
Okay I have it working with the screen sensor and the stars as individual objects, but to save of resources, I am grouping the stars and then changing the x and y position of the group. I’m noticing this does not change the x and y position of the group. Is there a way to apply group position locations to its children efficiently?
“I feel like this would work but seems very backwards.”
You’ll get over it. ;)
The “correct” way to tackle these sorts of problems is by splitting up the world so you can deal with (approximately) only the part you need: space partitions
These are, unfortunately, a lot of work to write and debug. However, Box2D (any physics library, for that matter) would have found itself in more or less the same straits you are now, just as a matter of course, so the author already went ahead and implemented one, e.g. see here and here. So it’s a perfectly good solution.
On your last comment (posted while I was writing this), you could group several stars together and just move the entire group when it’s all offscreen. In this case you could just have an invisible boundary object, say a rect, around them and test collisions only against that.
Thank you for your response, but I have a new idea that I am going to try to implement. Up to this point I have by updating the position of the stars by a certain number of pixels each frame. Now I am going to try to set them each on a never ending moveBy() call. Early implementation of this is that the stars are killing themselves off and disappearing shortly after they hit the bottom of the screen and are being reset to the top…
Does changing the x or y position of an object while a moveBy() call is being performed on it not a good idea? Or should this be okay?
While it’s being performed is a bad idea, yes… the next update will just undo it; if you notice it all it will just look glitchy. However, the onComplete handler is provided for this sort of thing.
If you do go this route, note that you’ll want to use different time parameters on your initial transition than on your resets after that, just because the first batch will already be in progress.
Thank you for providing this information, I will factor this in while forming my solution.
This ended up working out by resetting the MoveBy() call every time a star leaves the screen sensor. Thanks everyone!
You could:
- least efficient - use a runtime enterFrame listener to check each star individually each frame
- slightly more efficient - use an optimised runtime enterFrame listener that checks the stars in batches: for example, the first 10 stars on frame 1, the second 10 stars on frame 2, the third 10 stars on frame 3, back to the first 10 stars again on frame 4 etc. This is faster than checking every single star on every frame update, and it doesn’t really matter if the star has floated offscreen for a few frames (the user can’t see them anyway).
- most efficient but involves more mathematics in the setup - when you initialise the transitions on your stars, calculate the exactly coordinate where they will have left the screen plus a safe margin - then you set up an listener at the end of transition to reposition the star.
This post was similar and contains answers that will help you solve your question:
https://forums.coronalabs.com/topic/60870-removing-object-at-certain-position/
Also, as part of an answer I gave long ago, I provided a ‘on screen’ tester:
Full answer that uses on-screen test: http://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2014/10/Texture%20Memory%20Management.zip
Just the on-screen code:
(You’ll have to dig a little to get it out).
Here is a cleaner example (I’ve answered this a few times):
https://forums.coronalabs.com/topic/55035-how-to-determine-if-sprite-is-on-screen/
I don’t think any of this is what I am looking for. I know how to tell if the star is on the screen or not. I have functionality the exact way I want it right now, my problem is efficiency. I basically want 4 listeners that respectively get called if one of the stars go off each of the 4 edges of the screen. Is this possible?