controlling the number of random generating elements - iphone

I am generating random fireballs, but my problem that it's generating much number of fireballs .
How can I control the number of generated fireballs?
- (void)onTimer
{
// build a view from our fire image
UIImageView* fireView = [[UIImageView alloc] initWithImage:fireballs];
int startX = round(random() % 320);
int endX = round(random() % 320);
double scale = 1 / round(random() % 100) + 1.0;
double speed = 1 / round(random() % 100) + 1.0;
fireView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
[self.view addSubview:fireView];
[UIView beginAnimations:nil context:fireView];
[UIView setAnimationDuration:5 * speed];
fireView.frame = CGRectMake(endX, 500.0, 25.0 * scale, 25.0 * scale);
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}

You probably need to adjust how often your are firing your timer. Here's an example, just change your code where the "2.0" is below:
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:NO];

Related

Rotating image round a fix point

Firstly I am new to Objective C, any help will be most appreciated. I trying to write a Gauge app (which will eventually show the Angle of the phone). The issue I have is when I rotate the Needle image, it rotates to the correct angle, but not from the Anchor point - the image moves position. Even when I move, say from 0 dregs to 90 and back to 0, the image is does not end up back in its original position! The code I am using is below: .
(PS I am only currently only running the app on the simulator)
*** Rotate Invoked by ....
// Rotate Image
[self rotateImage:_imgNeedle duration: vAnimationDuration curve: UIViewAnimationCurveLinear degrees:vValue];
-(void)rotateImage:(UIImageView *)image
duration:(NSTimeInterval)duration
curve:(int)curve
degrees:(CGFloat)degrees
{
// Setup the animation
[self setAnchorPoint:CGPointMake(.44,.85) forView:image];
// image.transform = CGAffineTransformMakeRotation(d2r(degrees));
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeRotation(d2r(degrees));
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
// Set Anchor Point
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}
I am not sure about the layer position, but when I change the anchorPoint, the frame changes, so I will adjust the frame.
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
/*
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
*/
view.frame = CGRectOffset(view.frame, newPoint.x-oldPoint.x, newPoint.y-oldPoint.y);
view.layer.anchorPoint = anchorPoint;
}
And also if you want to go back to the original position with multiple calling of rotateImage, I think you should only set the anchor point once before that. Since if you make two separate animation with the same rotateImage method, the anchor point will be recalculated with your current implementation.
-(void)rotateImage:(UIImageView *)image
duration:(NSTimeInterval)duration
curve:(int)curve
degrees:(CGFloat)degrees
{
// Setup the animation
// [self setAnchorPoint:CGPointMake(.44,.85) forView:image];
// image.transform = CGAffineTransformMakeRotation(d2r(degrees));
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeRotation(d2r(degrees));
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}

how do I stack the UIImage together and wavering or swing in UIKit

I would like to know how this app stacks up uiimage and wavering in UIKit.
I'm following this xcode: Using a UIImageView subclass with NSTimers
to have images dropping down in random, but how do I catch it and stack the UIImage together ?
Thanks for the reply... EDIT: for clarity
https://www.youtube.com/watch?v=2dpZCoi4xFk 40sec onwards will show how it stack on top each other and swing with accerometer
This will emulate the dropping of UIIimageView
- (void)viewDidLoad {
[super viewDidLoad];
// set the background color to something COLD
self.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.5 blue:1.0 alpha:1.0];
// load our ph image we will use the same image over and over
phImage = [UIImage imageNamed:#"placeholder.png"];
// start a timet that will fire 1 times per second
[NSTimer scheduledTimerWithTimeInterval:(1) target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
}
// Timer event is called whenever the timer fires
- (void)onTimer
{
// build a view from our ph image
UIImageView* placeholderView = [[UIImageView alloc] initWithImage:phImage];
// use the random() function to randomize up our ph attributes
//int startX = round(random() % 300);
int startX = round(random() % 275);
//int endX = round(random() % 300);
int endX = startX;
double scale = 1 / round(random() % 100) + 1.0;
double speed = 1 / round(random() % 50) + 1.0;
// set the PH start position
phView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
phView.alpha = 0.25;
// put the ph in our main view
[self.view addSubview:phView];
[UIView beginAnimations:nil context:phView];
// set up how fast the ph will fall
[UIView setAnimationDuration:5 * speed];
// set the postion where ph will move to
phView.frame = CGRectMake(endX, 500.0, 25.0 * scale, 25.0 * scale);
// set a stop callback so we can cleanup the ph when it reaches the
// end of its animation
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}
- (void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIImageView *phView = context;
[phView removeFromSuperview];
NSLog(#"[phView retainCount] = %d",[phView retainCount]);
}
Thanks for reading and commenting.
For stacking, just make a UIView that holds all the placed images together.
UIView *stackView = [UIView new];
-(void) addView: (UIView*) view toStack: (UIView*) stackView
{
if ([stackView subviews].count > 0)
{
CGRect frame = [[[stackView subviews] lastObject] frame];
view.frame = CGRectOffset(frame, 0, 20);
}
[stackView addSubview:view];
}
For tilting, set up an accelerometer and use the x and y to determine the tilt.
-(void)configureAccelerometer
{
UIAccelerometer* theAccelerometer = [UIAccelerometer sharedAccelerometer];
theAccelerometer.updateInterval = 0.20;
theAccelerometer.delegate = self;
// Delegate events begin immediately.
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
UIAccelerationValue x, y, z;
x = acceleration.x;
y = acceleration.y;
//[stackView tiltForX: x Y: y]
}
More info on Motion Events
For the collision detection, you can probably do something like
if (CGRectIntersectsRect([[[stackView subviews] lastObject] frame], fallingView.frame))
[self addView: fallingView toStack: stackView];

Looping multiple methods

I've made a program that generates an image at a random x-coordinate at the top of the screen. The image then falls down to the bottom. However, I want to keep generating new images (of the same image) every few seconds so that it's as though these duplicates of the same image are continually "raining" from the top.
How can I make all of this code repeat every 0.5 seconds?
#implementation ViewController {
UIImageView *_myImage;
}
- (void)viewDidLoad
{
srand(time(NULL));e
int random_x_coordinate = rand() % 286;
CGRect myImageRect = CGRectMake(random_x_coordinate, 0.0f, 40.0f, 40.0f);
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"flake.png"]];
myImage.opaque = YES;
[self.view addSubview:myImage];
_myImage = myImage;
//FALLING BIRDS TIMER
moveObjectTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:#selector(moveObject) userInfo:nil repeats:YES];
}
//FALLING BIRDS MOVER
-(void) moveObject { // + means down and the number next to it is how many pixels y moves down per each tick of the TIMER above
_myImage.center = CGPointMake(_myImage.center.x, _myImage.center.y +1);
}
Just put animation cycle inside the method you call on timer, something like
- (void)viewDidLoad
{
[super viewDidLoad];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(animate)
userInfo:nil repeats:YES];
[timer fire];
}
- (void)animate
{
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view.backgroundColor = color;
[self.view addSubview:view];
[UIView animateWithDuration:1.0 animations:^{
view.frame = CGRectMake(0, 200, 50, 50);
}];
}
Will give you squares dropping down from top, continuously. Just remember to clean up unused views regularly to avoid memory issues.

how to detect wether the UIImage is moving

I am creating an UIImageView through timer which is called in touchesended and moving it. After completion of animation I am removing its object. If I touch the screen continuously 6 to 7 times, one of the image(created from the timer code block) is not moving and so not deallocating..
this is my code:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
flakeImage = [UIImage imageNamed:#"bubble.png"];
TimerView1=[NSTimer scheduledTimerWithTimeInterval:(0.1) target:self selector:#selector(onTimer:) userInfo:[NSValue valueWithCGPoint:location] repeats:NO];
}
- (void)onTimer:(id) sender {
NSValue *value=[TimerView1 userInfo];
CGPoint location = [value CGPointValue];
int time= [secLabel.text intValue];
int tick = 0;
tick = time+1;
secLabel.text = [NSString stringWithFormat:#"%.2i", tick];
double scale = 1 / round(random() % 100) + 1.0;
double speed = 1 / round(random() % 100) + 1.0;
UIImageView* flakeView1 = [[UIImageView alloc]initWithImage:flakeImage];
flakeView1.tag=100;
int endX = round(random() % 320);
int endY = round(random() % 480);
flakeView1.frame = CGRectMake(location.x, location.y, 35.0 * scale, 35.0 * scale);
[self.view addSubview:flakeView1];
[UIView beginAnimations:nil context:flakeView1];
[UIView setAnimationDuration:6 * speed];
flakeView1.frame = CGRectMake(endX,endY, 5.0 * scale, 5.0 * scale);
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
if(tick == 1)
{
[TimerView1 invalidate];
secLabel.text=[NSString stringWithFormat:#"0"];
}
}
- (void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIImageView *flakeView1 = context;
[flakeView1 removeFromSuperview];
[flakeView1 release];
flakeView1=nil;
}
I dont know why it is happening..Is there any way to detect if that image is moving or not?
I have seen many posts, they suggest to use animationKeys.How to use that for detecting if image is Animating or not?

Need to get frame co-ordinate of image while animation

I am using an app, in that am image is animating from top to bottom of screen using the animation.
code:
- (void)onTimer
{
// build a view from our flake image
flakeView = [[UIImageView alloc] initWithImage:flakeImage];
flakeView.backgroundColor=[UIColor blueColor];
// use the random() function to randomize up our flake attributes
int startX =round(random() % 460);
printf("\n ===== startX :%d",startX);
int endX = round(random() % 460);
printf("\n ===== endX :%d",endX);
double scale = 1 / round(random() % 100) - 1.0;
double speed = 1 / round(random() %100) + 1.0;
// set the flake start position
flakeView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
flakeView.alpha = 1.0;
// put the flake in our main view
[mView addSubview:flakeView];
[UIView beginAnimations:nil context:flakeView];
[UIView setAnimationDuration:20 * speed];
// code to get current position of image on view
CALayer mainLayer = flakeView.layer.presentationLayer;
CGRect layerFrame = mainLayer.frame;
BOOL intersects = CGRectIntersectsRect(layerFrame, dragger.frame);
// end position on screen
flakeView.frame = CGRectMake(endX, 500.0, 15.0 * scale, 15.0 * scale);
// set a stop callback so we can cleanup the flake when it reaches the
// end of its animation
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}
- (id)init
{
if(self = [super init])
{
mView = [[UIView alloc]initWithFrame:CGRectMake(0,0,320,440)];
mView.backgroundColor = [UIColor whiteColor];
mainLayer =[CALayer layer];
// load our flake image we will use the same image over and over
flakeImage = [UIImage imageNamed:#"apple.png"];
[mView.layer addSublayer:mainLayer];
// start a timet that will fire 20 times per second
[NSTimer scheduledTimerWithTimeInterval:(0.8) target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
self.view=mView;
}
return self;
}
I used this to get position of an image that is animating from top to bottom of the screen.
but I am getting the connstant values of x and y for the image that is animating.
Can any one help in this.
Thank U.
One thing I have noted from above code is that you are adding flakeView each time on mView. Do you want so? Please try with following code.
- (void)onTimer
{
int startX =round(random() % 460);
printf("\n ===== startX :%d",startX);
int endX = round(random() % 460);
printf("\n ===== endX :%d",endX);
double scale = 1 / round(random() % 100) - 1.0;
double speed = 1 / round(random() %100) + 1.0;
if(flakeView == nil)
{
// build a view from our flake image
flakeView = [[UIImageView alloc] initWithImage:flakeImage];
flakeView.backgroundColor=[UIColor blueColor];
// use the random() function to randomize up our flake attributes
// set the flake start position
flakeView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
flakeView.alpha = 1.0;
// put the flake in our main view
[mView addSubview:flakeView];
}
[UIView beginAnimations:nil context:flakeView];
[UIView setAnimationDuration:20 * speed];
// code to get current position of image on view
CALayer mainLayer = flakeView.layer.presentationLayer;
CGRect layerFrame = mainLayer.frame;
BOOL intersects = CGRectIntersectsRect(layerFrame, dragger.frame);
// end position on screen
flakeView.frame = CGRectMake(endX, 500.0, 15.0 * scale, 15.0 * scale);
// set a stop callback so we can cleanup the flake when it reaches the
// end of its animation
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
NSLog(#"Co-ordinates of imageview : (%f, %f, %f, %f) %#",flakeView.frame.origin.x,flakeView.frame.origin.y,flakeView.frame.size.width,flakeView.frame.size.height);
}
Thanks,
I'm wondering why you could use the dot-notation to access the presentationLayer. It is a method, not a property of CALayer.
Note: "Use of [UIView beginAnimations:context:] is discouraged in iPhone OS 4.0 and later. You should use the block-based animation methods instead." (Apple Docs). If you don't know what block-based animations are, read: What are block-based animation methods in iPhone OS 4.0?
If it still doesn't work with block-based animations, try to set the layer's delegate to nil or use CABasicAnimation either implicitly or explicitly.