I'm testing the response time differences between the native accelerometer method and the cocos2d udpate method (which is every frame, or 60 times a second if using the maximum frame rate) where update takes variable information that is updated in accelerometer.
Of course, when moving sprites across the screen using just the accelerometer method, they are not smooth and even if the sprite's position is calculated the same with the acceleration response in either accelerometer and update the accelerometer method clearly doesn't update as often as the sprite moves much more slowly across the screen.
I'm guessing this is because iOS does not natively update the UIAccelerometer anywhere near 60 times a second, so does anyone know where I can find out how often it does?
its up to you.
the UIAccelerometer object has Updateinterval property that you defined
how many times the accelerometer will update.
Ex:
UIAccelerometer *Accel;
Accel.updateInterval = 1.0f/30.0f;
which mean 30 times per one seconed.
it can take up to 60.
Related
I have searched for hours now and still didn't find a definitive answer to my problem.
The scenario is this: the user throw an iPhone as high as he can and I want to measure the height that the iPhone has done.
I want to use the accelerometer with Core Motion and I successfully implemented a simple system that gives me the acceleration on the 3 axis. This is an acceleration though.
Based on my physics knowledge, the formula to calculate the maximum height is (V0^2)/2*g where V0 is the starting velocity.
I have the acceleration velocity though.
Any idea how can I convert the acceleration to velocity or directly get the velocity from my accelerometer?
I know it's not a completely programming related question, but I just want to have some help on this :)
First of all there is alredy an app that does exactly what you are up to: Send Me To Heaven. You won't find it in Apple's App Store because it never passed the review, guess why ;-)
As you stated you only have access to accelerations. h = v02/(2*g) is correct. To get the starting velocity v0 you need to integrate the acceleration numerically over the time. The trickiest part will be to find necessary and sufficient conditions to determine the time interval [t1, t2]. When did the acceleration phase start and when did it stop.
Another thing to consider is to avoid cheating users who just perform a rotation around there axis for a couple of seconds, then simulate the flying phase. There you might consider the landing phase too: when the user grabs the device you should register a strong deceleration.
However, don't expect this app to ever get in the store and at Google Play the competitors were faster.
Problems:
There's a number of problems physics impose on you (other than the velocity), to get the result.
The angle of the throw, relative to the direction of gravity. You cant know the relative vertical distance, unless you know this angle.
Orientation of reference throughout the throw (you cannot deduct the speed from the acceleration, from the device itself, unless you account for the changes in rotation while the phone accelerates).
However! You can decide to assume certain things, which will make these annoying problems go away!
Reasonable assumption:
The device is caught again, at the same relative height it was thrown.
This assumption reduce the problem to a much simpler one, in which we only really need to find the duration of time, where the device is in free fall, in order to determine the relative height of the throw.
All you have to do:
To determine if the device is in free fall, is relatively easy, since the total gravity would be near 0 m/s^2.
However, there's still one smallish problem to this, because the accelerometer is probably not located at the center of mass of the phone, so it will experience a constant acceleration (if the phone rotates around itself) in exactly one particular direction, throughout the free fall.
The maths of determining the height of a vertical throw, based on the airtime duration is left as an exercise to the reader :-)
I remember from WWDC that there was a talk showing a teapot in OpenGL ES, which rotated with movement of device. It appeared like the teapot stood still in space.
When the app launched, the teapot started in a specific position. Then when device got rotated, the teapot rotated too to stand still in space.
At this talk, they mentioned that we must get the "reference frame" e.g. upon app launch, which tells us how the user initially held the device.
For instance here's the accelerometer axis:
I want to know rotation around Y axis, but relative to how the user holds the device.
So when the user holds it upright and rotates around Y, I need to know that rotation value.
I think the key is removing the gravity from the readings? Also I target iPhone 4 / 4S with gyros, but I think CoreMotion would sensor-fusion them automatically.
How could I figure out by how much the user rotated the device around the Y-axis?
From your other question Why is this CMDeviceMotionHandler never called by CoreMotion? I know that you working on iOS 4 - things have changed slightly in iOS5. In general gyro data or even better sensor fusion of accelerometer and gyro data as done in DeviceMotion is the best approach for getting proper results.
So if you got this up and running, you will need to work with CMAttitude's multiplyByInverseOfAttitude method to get all CMDeviceMotion results relative to your reference frame. Just store a reference of the very first CMAttitude in a class member and call multiplyByInverseOfAttitude with it on all subsequent calls. Then all members of CMDeviceMotion.attitude will refer to this reference frame.
For getting the rotation around Y axis, a first approach is to take Euler angles i.e. CMAttitude.roll. If you just need to track small motions this might be fine. If motions are more extensive, you will run into trouble regarding Gimbal Lock. Then you need advanced techniques like quaternion operation to get stable results, but this sounds like an own question.
I noticed that if I call the startDeviceMotionUpdates method of the CMMotionManager class and then rotate the device and put it back on the table the reported device attitude is changing constantly, every time the reported rotation matrix is different from the last time. Has anyone else noticed the same behavior ?
Apparently drifting of the gyro reference frame is a common issue and this is because it computes current attitude by aggregating rotation rates around axes over time
I am building a 2d OpenGL es application For iPad it displays a background texture and numerous textures on top of it which are always in motion.
Every frame their location is recalculated based on time delta and speed and the entire thing is being rendered at 60 fps successfully, but still as the movement speed of the sprites raises, thing look stuttering.
Any ideas? Are there inherit problems with what I'm doing? Are there known design patterns for smooth animation?
Try to compute time delta as average of last N frames because it's possible to have some frames that take more time than others. Do you use time delta for animations? It is very important to use it! Also try to load all resources at loading time instead loading them when you use them. This also may slow some frames.
If you take a look at the time deltas, you'll probably find they're not very consistent frame-to-frame. This probably isn't because the frames are taking different amounts of time to render, it's just an artifact of the batched, pipelined nature of the GLES driver.
Try using some kind of moving average of the time deltas instead: http://en.wikipedia.org/wiki/Moving_average
Note that even though the time deltas you're observing in your application aren't very consistent, the fact that you're getting 60fps implies the frames are probably getting displayed at fixed intervals (I'm assuming you're getting one frame per display v-sync). What this means is that the delay between your application making GL calls and the resulting frame appearing on the display is changing. It's this change that you're trying to hide with a moving average.
I am developing an iPhone version of this game. http://www.students.uni-mainz.de/rathb000/Fillit/Game.html
I am using an NSTimer to change the position of the ship by 1 pixel and the time interval for the timer is 0.002.
However, i have noticed that the ship doesnt move faster if i reduce the time interval furthur. Infact, there is no difference between 0.05 and 0.002. Is there is a restriction on the minimum time you have to give as NSTimeInterval?
The ship currently moves too slow for the game to be exciting.
Also, the movement of birds (which is also achieved by NSTimer) becomes slow when i press any button for moving the ship.
Any idea about how this can be solved?
NSTimer is not a real-time mechanism; it fires as part of the run loop and is not ideal for creating smooth, fluid animations. However, there is an SDK that is part of the iPhone OS called Core Animation - it provides a library of functions for performing smooth animation of layers and views. Here is a reasonably good series of video tutorials that you may find useful. There is also an excellent book called Core Animation for Mac OS X and iPhone that you may find useful.
There is also the core animation documentation from Apple that describes how to use the CABasicAnimation class to animate properties of any layer or view. Here is an example of an explicit layer animation from the docs:
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"opacity"];
theAnimation.duration=3.0;
theAnimation.repeatCount=1;
theAnimation.autoreverses=NO;
theAnimation.fromValue=CATransform3DTranslate(0,0,0);
theAnimation.toValue=CATransform3DTranslate(20,20,0);
[theLayer addAnimation:theAnimation forKey:#"animateTransform"];
From NSTimer docs:
A timer is not a real-time mechanism; it fires only when one of the run loop modes to which the timer has been added is running and able to check if the timer’s firing time has passed. Because of the various input sources a typical run loop manages, the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds. If a timer’s firing time occurs while the run loop is in a mode that is not monitoring the timer or during a long callout, the timer does not fire until the next time the run loop checks the timer. Therefore, the actual time at which the timer fires potentially can be a significant period of time after the scheduled firing time.
Maybe you can try moving the UIView using UIView animations instead of a timer.
You could consider increasing the distance size: move the ship 3 or 4 pixels every .05 seconds rather than 1 pixel every .002 seconds.
In my opinion, you should be using the same timestep globally across all entities in your game, not a timestep exclusively for the player's ship. If the ship is moving too slowly with your timestep, increase the amount of distance it is moving per frame.
Really, you should be thinking of moving your player's ship in terms of pixels/second. When the NSTimer event fires, get the elapsed time since the last update. Use this elapsed time to move your game entities. For instance, if your update timestep is 0.05 seconds and you want to move the player's ship 100 pixels per second, then you should move it 100 * 0.05 = 5 pixels in this update. This method will account for varying size timesteps and your game entities will always appear to moving at a consistent speed, even if your timer mechanism is not that consistent.
Not only is NSTimer not the right tool for this type of animation your design is wrong.
A timer with an inteval of 0002 fires 500 times per second. That's a crazy way to animate this game.
I suggest you read up on 2D game design and find out a better way to do collision detection - like anonymous suggests you should have a collision rectangle round the ship rather than relying on the actual pixels.
You should also check out Cocos-2D for iPhone
Figured this out.
Had to use Core Animation to move the ship and made the birds move by NSTimer. Works fine this way but only upto a certain limit. Birds again slow down when the speed of the ship increases more than a certain limit.