I am trying to develop a simple soccer game including penalty kicks in which i have to animate a ball from player to the goal post...earlier i have been using simple animations using a timer to add to the axis of ball image so that it moves from 1 point to another..but i did not have the desired result as animations were not that smooth...So i was thinking of using a Game Engine...Since i am a New Programmer i have no idea about game engine and neither can i find any proper documentation regarding engines like box2d or chipmunks or sparrow..i was also thinking of using UIView animations instead of the earlier animations as i think that can achieve far better animations without scratching my head trying to work on a game engine....I am going no where with this so it would be really great if someone can put some light on this issue of mine???
Use UIView animations, like in:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // or whatever time
object.center=CGPointMake(object.center.x+2, object.center.y+4);
// or whatever
[UIView commitAnimations];
You should also use an NSTimer with the same interval so that you can call animations smoothly.
NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:0.3 target: self
selector:#selector(animation) userInfo: nil repeats: YES];
Then, implement the method:
- (void)animation {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // or whatever time
object.center=CGPointMake(object.center.x+5, object.center.y+7);
// or whatever
[UIView commitAnimations];
}
This should do for ANY simple game.
As you tagged the question with cocos2d, I guess you're using it, or planning to. Animating CCSprites is easy as you can see e.g. in this game https://github.com/haqu/tweejump.
In your onEnter implementation, just call
[self scheduleUpdate]
this will call routinely the update: where you can do your drawing
- (void)update:(ccTime)dt {
ball_pos.x += ball_velocity.x * dt;
ball_pos.y += ball_velocity.y * dt;
ball_velocity.x += ball_acc.x * dt;
ball_velocity.y += ball_acc.y * dt;
//game logic goes here (collision, goal, ...)
ball.position = ball_position;
}
That'll handle smooth movement of the ball. ball_pos, ball_velocity and ball_acc being vvCertex2F.
You probably don't even have to deal with acceleration, and only give an impulse to the ball when someone hit it (i.e. bump the velocity).
You probably also want some damping to slow the ball down. you do it by reducing the velocity at every step
Related
I was to able to move or animate my UIView by this code down here:
- (void) makeAnim1{
//downward animation
[UIView animateWithDuration:1.5
delay:0.15
options: UIViewAnimationCurveLinear
animations:^{
carousel.frame = CGRectOffset(carousel.frame, 0, 650);
}
completion:^(BOOL finished){ //task after an animation ends
[self performSelector:#selector(makeAnim1_1) withObject:nil afterDelay:2.0];
NSLog(#"Done!");
}];
}
- (void) makeAnim1_1{
//upward animation
[UIView animateWithDuration:1.5
delay:0.1
options: UIViewAnimationCurveLinear
animations:^{
carousel.frame = CGRectOffset(carousel.frame, 0, -650);
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
But it only move the UIView up and down. How can I make it spin like a Slot machine but only contains one image or view. Like rotate in z axis. But make it look like it contains more than one image.
Thanks for the help.
Instead of changing the frame inside the animation block you change the transform. The transform can be used to scale, rotate and translate (move) the view. You can only rotate around the z-axis but that is what you asked for. The transform property on the view takes a CGAffineTransform, like this:
// rotate pi/2 degrees clockwise
carousel.transform = CGAffineTransformMakeRotation(M_PI_2);
If you need to do more advanced transforms like rotating around another axis then you would need to use a little bit of Core Animation and to set the transform property of the views layer (which takes a CATransform3D instead of a CGAffineTransform).
As with all Core Animation code you need to import QuartzCore.framework and include QuartzCore/QuartzCore.h in your code.
The above animations you are doing is UIView animations which are only meant to animate views but the animation you are asking for requires more advanced animations of the views layer. I suggest that you look at the documentation for CABasicAnimation and also take a look at the Core Animation Programming Guide for iOS to learn more.
You can animate the x rotation of a views layer like this:
CABasicAnimation *slotAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
[slotAnimation setToValue:[NSNumber numberWithFloat:M_PI_2]];
// animation customizations like duration and timing
// that you can read about in the documentation
[[carousel layer] addAnimation:slotAnimation forKey:#"mySlotAnimation"];
The above code will indeed rotate the view around the x axis but will look very silly without perspective (search SO for "perspective Core Animation", it has been asked about before). There is probably a lot of tweaking to get the correct look but this should be enough to get you started.
I have done the coding for rotating a needle in a compass using:
NeedleView.transform=CGAffineTransformMakeRotation(theHeading);
but the rotation is not smooth. It is moving roughly.
Can anyone tell me how to do a smooth rotation of the compass needle with respect to angular movement?
You can compensate the jumpiness of the compass with the gyroscope. I have done a project using that method that you can see here: http://www.sundh.com/blog/2011/09/stabalize-compass-of-iphone-with-gyroscope/
Try this. Works well for me.
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
self.lblGrados.text = [NSString stringWithFormat:#"%.0f°", newHeading.magneticHeading];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
needle.transform = CGAffineTransformMakeRotation((degrees-newHeading.trueHeading) * M_PI / 180);
} completion:nil];
}
Do an animation with the transform, don't just set it. If you set it, it will change rotation right away. Animation will slow it. You can select the duration over which the animation occurs to slow it down. Look at the docs for UIView for the animation APIs.
Well here is my problem:
I have two images : flakeImage and ViewToRotate. What I want is that if flakeImage touches ViewToRotate, ViewToRotate.alpha=0.5; but when FlakeImage appears on the screen ViewToRotate.alpha=0.5; without touching it. I think it's a problem with my view beacause I have :
UIImageView* flakeView = [[UIImageView alloc] initWithImage:flakeImage];
here is the code :
UIImageView* flakeView = [[UIImageView alloc] initWithImage:flakeImage];
// use the random() function to randomize up our flake attributes
int startY = round(random() % 320);
// set the flake start position
flakeView.center = CGPointMake(490, startY);
flakeView.alpha = 1;
// put the flake in our main view
[self.view addSubview:flakeView];
[UIView beginAnimations:nil context:flakeView];
// set up how fast the flake will fall
[UIView setAnimationDuration:7 ];
// set the postion where flake will move to
flakeView.center = viewToRotate.center;
// set a stop callback so we can cleanup the flake when it reaches the
// end of its animation
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
How can I solve this please ?
if someone could help me it would be very cool.
I have a bit of sophomoric experience with this, having written http://itunes.apple.com/us/app/balls/id372269039?mt=8. If you check that app out, you will see a bit of the same problem. This topic is a pretty deep rabbit hole. WHen I started that app, I didn't even know how to write a decent game loop. You will need that first because you need to do precise time-step calculations. AFA the collisions, you update your model and view separately, so if you update the model and objects overlap, you need to back them up until they don't collide and then update your view with the result. If you plan to have a lot of colliding objects, you may hit a wall using UIViews. To complicate things more, if your objects are round, CGRectIntersectsRect won't exactly work. That complicates the math a bit, but it's not too bad. With my app, I found it quite difficult to get the physics to look realistic. THe problem became that ball A and B overlap, so you back them up, then they now intersect other balls, etc, etc. This link is a good starting point, but there are quite a few examples of code out there that "almost" work.
CGRect has a intersection function. The frames of UIViews are CGRects.
if (CGRectIntersectsRect(view1.frame, view2.frame) == 1)
NSLog(#"The views intersect");
else
NSLog(#"The views do not intersect");
The problem I foresee is that if the rects have lots of whitespace, they will appear to intersect before they actually touch
Secondly, you should switch up to block animations. It's strongly encouraged
UIImageView* flakeView = [[[UIImageView alloc] initWithImage:flakeImage] autorelease];
// use the random() function to randomize up our flake attributes
int startY = round(random() % 320);
// set the flake start position
flakeView.center = CGPointMake(490, startY);
flakeView.alpha = 1;
// put the flake in our main view
[self.view addSubview:flakeView];
[UIView animateWithDuration:.7
animations:^ {
// set the postion where flake will move to
flakeView.center = viewToRotate.center;
};
Did this all from memory, no idea if there are errors.
Circular Collision:
a^2 + b^2 < c^2 means they collide
if(pow(view2.frame.origin.x - view1.frame.origin.x, 2) +
pow(view2.frame.origin.y - view1.frame.origin.y, 2) <
pow(view1.frame.size.width/2, 2))
{
//collision
}
else
{
//no collision
}
Again, all from memory, check for errors on your own
CoreAnimation is a pretty easy thing, but:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:30];
MyImageView.frame = CGRectOffset(MyImageView.frame, 100, 0);
[UIView commitAnimations];
I want to move the ImageView by 100 Pixel veeeery slowly. Therefore all positioning values are double I expect the Layoutsystem to position the items with subpixel accuracy.
Butt when I watch this animation i see the ImageView "jumping" pixelwise instead of a smooth traveling.
Any ideas to come to a real subpixelpositioning?
I also tried to set the position with a timer and recalculate the frame-values, but same effect.
Update:
In an other part of my App I use the Accelerometer to update the position of a ImageView, and do basicly calculate the position ad size of the graphic an then do:
MyImageView.frame = newCGRect;
I get around 60 Updates/s from the Accelerometer and added the LowPass-Filter from the Accelerometer example from Apple.
Here the positioning is perfect?!?!
Why does this do not happen with CoreAnimation?
Thanks for any help.
Try using CGAffineTransformTranslate(MyImageView.transform, 100, 0) instead of CGRectOffset.
Reference here:
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGAffineTransform/Reference/reference.html
If you use CABasicAnimation in QuartzCore framework, you can smoothen your animation using "CAMediaTimingFunction". Built-in alternatives worked for me but as far as I know you can define your own timing functions as well.
CABasicAnimation *starShineAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
starShineAnimation.removedOnCompletion = NO;
starShineAnimation.fillMode = kCAFillModeForwards;
starShineAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
....
Hello all I am working an iphone app where I need to show the current time in a watch That is there is a watch which displays the static time or static image . Then we need to find the current time then move all the hrs,mins ,seconds pins such tht they should set to their time.
Do u have any ideas to do this
Thanks Everyone
Here is my code:
//Calculate angles:
float minutesAngle = (0/60)*360;
float hoursAngle = (10/12)*360;
//Begin the animation block
[UIView beginAnimations:#"moveHands" context:nil];
[UIView setAnimationDuration:0.5];
minsImageView.transform = CGAffineTransformRotate(minsImageView.transform, minutesAngle);
hoursImageView.transform = CGAffineTransformRotate(hoursImageView.transform, hoursAngle);
[UIView commitAnimations];
where as minsImageView ,hoursImageView are the imageViews set in the XIB who shows the static image
But its not effecting at all..
Once you have individual time values (it sounds like you've figured this out already) you can position your hands as needed.
This means it's time to brush up on your math skills. I think this'll give you a start:
A circle has 360 degrees in it. This means that for whatever time unit we get, we divide by the maximum value of that time unit to get a fraction and multiply the result by 360 (instead of 100 like a percentage) to get our number of degrees.
So, if we had 23 seconds:
23/60 = 3.83333.8333 x 360 = 138 degrees
Now we know how many degrees to rotate our object. I would get a designer to make you some nice hand images and put them in UIImageViews. Then, you can rotate them around their origins like so:
secondHandImage.transform = CGAffineTransformMakeRotate(secondAngle);
Good luck :)
EDIT: Let's assume that our hands are on 10:10. If we wanted to move them to 01:00 we would do something like the following. Tweak it as needed.
//Calculate angles:
float minutesAngle = (0/60)*360;
float hoursAngle = (10/12)*360;
//Begin the animation block
[UIView beginAnimations:#"moveHands" context:nil];
[UIView setAnimationDuration:0.5];
minutesHand.transform = CGAffineTransformRotate(minutesHand.transform, minutesAngle);
hoursHand.transform = CGAffineTransformRotate(hoursHand.transform, hoursAngle);
[UIView commitAnimations];
If you're trying to show a digital clock, your life is SOOOO much easier than my previous answer related to analog clocks.
Create images with the numbers 0-9 and put them in your bundle. Have four UIImageViews in your UI in this configuration:
[][]:[][]
[ ] = UIImageVIew
Then, you can simply change the images in each slot to reflect the time. If you use transparent backgrounds and high resolution graphics, you can create really convincing effects.