I'm writing this game on Android where I have a bunch of characters moving around who collide with each other. Everything works fine but when I get passed a certain number of characters on the screen at the same time, the performance of the app gets hit severely. I did my tests and drawing is not causing the low frame rate, it is the algorithm for collision detection, since every time they move they have to check their location to all the other characters. So currently I'm just looping through them all for each character. Is there a way to improve on this? Is there a performance trick to collision detection on a big number of objects that I don't know about?
Yes, there is a technique based on a first broad-phase and second narrow-phase colission detection.
I'll quote some paragraps from: Beginning Android Games, by Mario Zechner.
Broad phase: In this phase we try to figure out which objects can
potentially collide. Imagine having 100 objects that could each
collide with each other. We’d need to perform 100 * 100 / 2 overlap
tests if we chose to naively test each object against each other
object. This naive overlap testing approach is of O(n^2) asymptotic
complexity, meaning it would take n^2 steps to complete (it actually
finished in half that many steps, but the asymptotic complexity
leaves out any constants). In a good, non-brute-force broad phase, we
try to figure out which pairs of objects are actually in danger of
colliding. Other pairs (e .g., two objects that are too far apart for
a collision to happen) will not be checked . We can reduce the
computational load this way, as narrow-phase testing is usually pretty
expensive.
Narrow phase: Once we know which pairs of objects can potentially
collide, we test whether they really collide or not by doi ng an
overlap test of their bounding shapes.
The broad phase involves dividing the world in large cells, making some sort of grid.
Each cell has the exact same size, and the whole world is covered in cells. If two objects are not in the same cell, a narrow phase for those two objects is not needed.
Quote once again:
All we need to do is the following:
Update all objects in the world based on our physics and controller step.
Update the position of each bounding shape of each object according to the object’s position. We can of course also include the orientation and scale as well here.
Figure out which cell or cells each object is contained in based on its bounding shape, and add it to the list of objects contained in those cells.
Check for collisions, but only between object pairs that can collide (e.g., Goombas don’t collide with other Goombas) and are in the same cell.
This is called a spatial hash grid broad phase, and it is very easy to implement. The first thing we have to define is the size of each cell. This is highly dependent on the scale and units we use for our game’s world.
It also depends on the bounding shape you're using. A simple rectangle or circle around the characters and it's euclidean distance is one simple thing to calculate, but a finer shape (including details as "the head", "the legs" with little additional bounding shapes) will be more a lot more computationally expensive to calculate.
If all objects are free to move to any part of the screen, then the best you can do is your O(n^2) algorithm. You can improve it by a constant factor by realizing that when you check if object A collides with object B, then you don't have to later check if object B collides with object A.
enclose each character within a fixed size square. Before you check for character collision, check if the squares in which they are enclosed collide. If and only if the squares collide, there would be a chance for the characters to collide. Now checking for squares collision is easy as you have to just compare the x & y co-ordinates.
Dividing into a broad phase and narrow phase as Federico suggests only helps if your collision detection algorithm is expensive, i.e. it's not a simple bounding box.
Fortunately there are other options.
You could try a collision mask technique. Since you don't seem to be limited by rendering speed, render a bounding box for each object into a hidden bitmap. Before rendering the next object, check the pixels at the four corners of its bounding box to see if they have already been written. You can even use a different colour for each object so that the colour tells you which object the collision was with.
Another popular trick is to simply not do every collision check every frame. For example, games like Super Mario Bros actually only check for collisions between the player and enemies every other frame. You can do a more advanced version where you check all objects in a round-robin fashion, doing as many as it can per frame. When things get busy each object might only be checked every other or even every third frame, but the player is unlikely to notice. This works best if your objects are not moving so fast that they can pass through each other one only one frame of collision.
Related
I have two ArrayLists with double data. I am already using moving average smoothing. Data is collected every 200-500ms. This is what a typical graph (using GraphView in Android) looks like:
Since the data collection rate is limited by the hardware I am using, this is how jagged the result looks. Very easy to see individual points.
How do I make the function look smooth and continuous (either mathematically by altering the ArrayLists or by changing some setting in GraphView?
Is polynomial fit the way to go, or should I use a combination of filtering and moving average?
I appreciate it!
It depends on how you want to smooth out the functions. Your problem is that you do not have enough data points to make it look smooth since graphview draws a straight line between two data points. I do not think there is a way to draw a curve between two points in GraphView without using custom views. Custom view is another beast so I do not think you want to do that. There are two ways now that you can solve this problem.
First way, if your know beforehand that your data does not contain high noise, then you can perform polynomial interpolation of all the points in your arraylist. From that, you will get a function which you can use to create a new arraylist and calculate the y-values in smaller x-steps than what your data has. This way, you can simulate a curve. But do note that interpolation is costly especially as you go to higher orders of polynomials.
Now, if you know that your data is noisy, interpolation will interpolate (fit) all of the noises and that is not what you want. Then you want to use the least squares method. You can go for any orders of polynomial. Use the one that makes the most sense. Least squares will be less time consuming to compute than interpolation and it has the advantage that if your noises are bias-free (meaning the sum of the noises add up to 0), it might provide you with a better approximation of real values. Also note that in least squares, your computation becomes significantly easier if your x-values in your data are separated from each other uniformly. In your case, this could be true since you mention that you collect data every 200-500ms. If you can poll at a fixed rate, then do it. There are various equations on the internet which provides easy least squares calculations given fixed intervals.
I try to use Dynamic Time Warping (DTW) to detect gestures performed with a smartphone by using the accelerometer sensor. I already implemented a simple DTW-algorithm.
So basicly I am comparing arrays of accelerometer-data (x,y,z) with DTW. The one array contains my predefiend gesture, the other should contain the measured values. My problem is, that the accelerometer-sensor measures continously new values and I don't know when to start the comparison with my predefined value-sequence.
I would need to know when the gesture starts and when it ends, but this might be different with different gestures. In my case all supported gestures start and end at the same point, but as far as I know I can't calculate the traveled distance from acceleration reliably.
So to sum things up: How would you determine the right time to compare my arrays using DTW?
Thanks in advance!
The answer is, you compare your predefined gesture to EVERY
subsequence.
You can do this in much faster than real time (see [a]).
You need to z-normalize EVERY subsequence, and z-normalize your predefined gesture.
So, by analogy, if you stream was.....
NOW IS THE WINTER OF OUR DISCONTENT, MADE GLORIOUS SUMMER..
And your predefined word was made, you can compare with every marked word beginning (denoted by white space)
DTW(MADE,NOW)
DTW(MADE,IS)
DTW(MADE,THE)
DTW(MADE,WINTER)
etc
In your case, you don’t have makers, you have this...
NOWISTHEWINTEROFOURDISCONTENTMADEGLORIOUSSUMMER..
So you just test every offset
DTW(MADE,NOWI)
DTW(MADE, OWIS)
DTW(MADE, WIST)
DTW(MADE, ISTH)
::
DTW(MADE, TMAD)
DTW(MADE, MADE) // Success!
eamonn
[a] https://www.youtube.com/watch?v=d_qLzMMuVQg
You want to apply DTW not only to a time-series, but to a continously evolving stream. Therefore you will have to use a sliding window of n recent data points.
This is exactly, what eamonn described in his second example. His target pattern consists of 4 events (M,A,D,E) and therefore he uses a sliding window with length of 4.
Yet in this case, he makes the assumption, that the data stream contains no distortions, such as (M,A,A,D,E). The advantage of DTW is that it allows these kind of distortions and yet recognizes the distorted target pattern as a match. In your case, distortions in time are likely to happen. I assume that you want equal gestures performed either slow or fast as the same gesture.
Thus, the length of the sliding window must be higher than the length of the target pattern (to be able to detect a slow target gesture). This is computationally expensive.
Finally, my point is: I want to recommed you this paper
Spring algorithm by Sakurai, Faloutsos and Yamamuro.
They optimized the DTW algorithm for datastreams. You will no longer need more than n*n computations per incoming event but only n. It basically is DTW but cutting down all unneccesary computations and only taking the best possible alignment of the template onto the stream into account.
p.s. most of what I know about time-series and pattern matching, I learned by reading what Eamonn Keogh provided. Thanks a lot, Mr. Keogh.
Currently I am doing app allowing user to draw. Simple think, just extend Canvas class and most of the thing is done.
That was my initial thinking and idea. But as the canvas is rather small because this is only what user see on the screen there is not much possible space to draw. Going through documentation I found translate() method allowing me to move canvas. What I did find out is when I move it, there is some kind of blank space just as you would move piece of paper. I understand that this is totally normal, as I've said before - canvas is only "the screen".
My question is - is there a possibility to make something like infinite canvas so you can make a huge painting and move everything around?
Before this question I was thinking about two things how something like this can be done:
Move all objects on canvas simultaneously - bad idea, because if you have a lot of them then the speed of moving is very bad.
Do something similar as it is done in ListView when you move it (or better see on the screen) only views that are on the screen together with one before and one after are loaded to memory and rest is uploaded dynamically when needed. I think this is the best option to achieve this goal.
EDIT:
Question/answer given by Kai showed me that it is worth to edit my question to clarify some of the things.
Basic assumptions about what can be done by user:
User is given opportunity to draw only circles and rectangles with some (around 80%) having drawable (bitmap) on them on canvas.
I assume that on all screens there will be maximum 500-800 rectangles or circles.
First of all thinking about infinity I was thinking about quite big number of screens - at least 30 on zoom 1x in each side. I just need to give my users bigger freedom in what they are doing.
On this screen everything can be done as on normal - draw, scale (TouchListener, ScaleListener, DoubleTapListener). When talking about scaling, there is another thing that has to be concerned and connected with "infinity" of canvas. When user is zooming out then screens, or more precise objects on the invisible "neighbours" should appear with proper scaling as you would zoom out camera in real life.
The other thing that I've just realised is possibility of drawing at small zoom level - that is on two or three screens and then zooming in - I suppose it should cut and recalculate it as a smaller part.
I would like to support devices at least from API 10 and not only high-end.
The question about time is the most crucial. I want everything to be as smooth as possible, so user wouldn't know that new canvas is being created each time.
I think it really depends on a number of things:
The complexity of this "infinite canvas": how "infinite" would it really be, what operations can be done on it, etc
The devices that you want to support
The amount of time/resource you wish to spend on it
If there are really not that many objects/commands to be drawn and you don't plan to support older/lower end phones, then you can get away with just draw everything. The gfx system would do the checking and only draws what would actually be shown, so you only waste some time to send commands pass JNI boundary to the gfx system and the associated rect check.
If you decided that you needs a more efficient method, you can store all the gfx objects' positions in 4 tree structures, so when you search the upper-left/upper-right/lower-left/lower-right "window" that the screen should show, it'll fast to find the gfx objects that intersects this window and then only draw those.
[Edit]
First of all thinking about infinity I was thinking about quite big
number of screens - at least 30 on zoom 1x in each side. I just need
to give my users bigger freedom in what they are doing.
If you just story the relative position of canvas objects, there's practically no limit on the size of your canvas, but may have to provide a button to take users to some point on canvas that they are familiar lest they got themselves lost.
When talking about scaling, there is another thing that has to be
concerned and connected with "infinity" of canvas. When user is
zooming out then screens, or more precise objects on the invisible
"neighbours" should appear with proper scaling as you would zoom out
camera in real life.
If you store canvas objects in a "virtual space", and using a "translation factor" to translate objects from virtual space to screen space then things like zoom-in/out would be quite trivial, something like
screenObj.left=obj.left*transFactor-offsetX;
screenObj.right=obj.right*transFactor-offsetX;
screenObj.top=obj.top*transFactor-offsetY;
screenObj.bottom=obj.bottom*transFactor-offsetY;
//draw screenObj
As an example here's a screenshot of my movie-booking app:
The lower window shows all the seats of a movie theater, and the upper window is a zoomed-in view of the same theater. They are implemented as two instances of the same SurfaceView class, besides user input handling, the only difference is that the upper one applies the above-mentioned "translation factor".
I assume that on all screens there will be maximum 500-800 rectangles
or circles.
It is actually not too bad. Reading your edit, I think a potentially bigger issue would be if an user adds a large number of objects to the same portion of your canvas. Then it wouldn't matter if you only draw the objects that are actually shown and nothing else - you'd still get bad FPS since the GPU's fill-rate is saturated.
So there are actually two potential sources of issues:
Too many draw commands (if drawing everything on canvas instead of just drawing visible ones)
Too many large objects in the same part of the screen (eats up GPU fill-rate)
The two issues requires very different strategy (1st one using tree structures to sort objects, 2nd one using dynamically generated Bitmap cache). Since how users use your app are likely to different than how you envisioned it to be, I would strongly recommend implementing the functions without the above optimizations, try to get as many people as possible to do testing, and then apply optimizations to each of the bottlenecks you encounter until the satisfactory performance is achieved.
[Edit 2]
Actually with just 500~800 objects, you can just calculate the position of all the objects, and then check to see if they are visible on screen, you don't even really need to use some fancy data structures like a tree with its own overheads.
I need pixel-perfect collision detection for my Android game. I've written some code to detect collision with "normal" bitmaps (not rotated); works fine. However, I don’t get it for rotated bitmaps. Unfortunately, Java doesn’t have a class for rotated rectangles, so I implemented one myself. It holds the position of the four corners in relation to the screen and describes the exact location/layer of its bitmap; called "itemSurface". My plan for solving the detection was to:
Detect intersection of the different itemSurfaces
Calculating the overlapping area
Set these areas in relation to its superior itemSurface/bitmap
Compare each single pixel with the corresponding pixel of the other bitmap
Well, I’m having trouble with the first one and the second one. Does anybody has an idea or got some code? Maybe there is already code in Java/Android libs and I just didn’t find it.
I understand that you want a collision detection between rectangles (rotated in different way). You don't need to calculate the overlapping area. Moreover, comparing every pixel will be ineffective.
Implement a static boolean isCollision function which will tell you is there a collision between one rectangle and another. Before you should take a piece of paper do some geometry to find out the exact formulas. For performance reasons do not wrap a rectangle in some Rectangle class, just use primitive types like doubles etc.
Then (pseudo code):
for (every rectangle a)
for (every rectangle b)
if (a != b && isCollision(a, b))
bounce(a, b)
This is O(n^2), where n is number of rectangles. There are better algorithms if you need more performance. bounce function changes vectors of moving rectangles so that imitates a collision. If the weight of objects was the same (you can aproximate weight with size of the rectangles), you just need to swap two speed vectors.
To bounce elements correctly you could need to store auxiliary table boolean alreadyBounced[][] to determine which rectangles do not need a change of their vectors after bounce (collision), because they were already bounced.
One more tip:
If you are making a game under Android you have to watch out to not allocate memory during gameplay, because it will faster invoke GC, which takes a long time and slow downs your game. I recommend you watching this video and related. Good luck.
So in my game my View gets drawn an inconsistent rates. Which in turn makes it glitchy. Ive been running into alot of problems with the invalidate(); meathod. Any simple ideas- Everywhere i look I get thrown up on by tons of intense code.
You haven't provided us with much information, specifically code.
A few things you could do are:
Set the initial frame rate to the lowest value you observe your application runs at, i.e., if currently set to 1/60, but the frame rate continuously dips to 1/30, set to 1/30 etc.
Rework your drawing calls to be more efficient.
Try to combine multiple transformations into a single transformation by multiplying matrices, i.e. if you need to scale, translate, and rotate, multiply those three matrices together and apply that single transformation to the vertices instead of applying three separate transformations.
Try not to iterate through entire lists/arrays if unnecessary.
Attempt to use the lowest level / most primitive structure possible for anything you have to process in the loop to avoid the overhead of unboxing.
[edit on 2012-08-27]
helpful link for fixing you timestep: http://gafferongames.com/game-physics/fix-your-timestep/
It sounds like your game loop doesn't take into account the actual time that has passed between iterations.
The problem is the assumption that there is a fixed amount of time between loop iterations. But this time can be variable depending on the number of objects in the scene, other processes on the computer, or even the computer itself.
This is a common, somewhat subtle, mistake in game programming, but it can easily be remedied. The trick is to store the time at the end of each draw loop and then take the difference of the last update with the current time at the start. Then you should scale all animations and game changes based on the actual elapsed time.
I've wrote more about this on my blog a while back here: http://laststop.spaceislimited.org/2008/05/17/programming-a-pong-clone-in-c-and-opengl-part-i/
Part II specifically covers this issue:
http://laststop.spaceislimited.org/2008/06/02/programming-pong-in-c-and-opengl-part-ii/