Moving object back and forth on screen? - ios

I'm just starting out with my first Xcode project and I'm trying to create a square that moves back and forth on the screen using two timers, because I eventually want to make it so that the user can stop the object (which is a square) by tapping a button on the screen.
For now though, I've made the square move to the right side of the screen and move back, but unfortunately I cannot get it to stop at the other side of the screen.
My code right now is this:
- (void)viewDidLoad
{
Square.center = CGPointMake(-9, 246);
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare1)userInfo:nil repeats:YES];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)moveSquare1
{
Square.center = CGPointMake(Square.center.x + 0.3, Square.center.y);
if (Square.center.x > 290){
[SquareTimer1 invalidate];
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare2) userInfo:nil repeats:YES];
}
if (Square.center.x < -9){
[SquareTimer1 invalidate];
}
}
-(void) moveSquare2
{
Square.center = CGPointMake(Square.center.x - 0.3, Square.center.y);
}
The only part of my code that is not working is my second if statement. How can I fix this?

This should do it. Remove that second if from moveSquare1 and place it in moveSquare2
- (void)viewDidLoad
{
Square.center = CGPointMake(-9, 246);
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare1)userInfo:nil repeats:YES];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)moveSquare1
{
Square.center = CGPointMake(Square.center.x + 0.3, Square.center.y);
if (Square.center.x > 290){
[SquareTimer1 invalidate];
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare2) userInfo:nil repeats:YES];
}
}
-(void) moveSquare2
{
Square.center = CGPointMake(Square.center.x - 0.3, Square.center.y);
if (Square.center.x < -9){
[SquareTimer1 invalidate];
// If you want to move the Square back in the right side. Otherwise, comment this below line.
SquareTimer1 = [NSTimer scheduledTimerWithTimeInterval:0.004 target:self selector:#selector(moveSquare1) userInfo:nil repeats:YES];
}
}
Let me know if you have any doubts.

Related

NSTimer stops my image from moving

When I hold down on a button my image will move to a direction.
The game objective is that they are going to move image to hit another image, and to do that I'm using an NSTimer.
Then they also have another NSTimer because they only have 15 seconds on them to hit the other image. If they don't the game will [self gameover] but, the NSTimer that counts the 15 seconds is started and I move the image the image moves a bit and then it goes back to center again.
When I delete the countdown timer, the image does not go back to center after I stop pressing the button but it stops on its current position.
And that's what I want it to do while I'm using the countdown timer as well.
Code:
-(void)goLeft
{
ball.center = CGPointMake(ball.center.x -5, ball.center.y);
}
-(IBAction)left
{
goLeft = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(goLeft) userInfo:nil repeats:YES];
if (goLeft == nil) goLeft = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(goLeft) userInfo:nil repeats:YES];
}
-(IBAction)stopLeft
{
[goLeft invalidate];
goLeft = nil;
}
//And heres the timer :
-(IBAction)doCountdown: (id)sender;{
if (countdownTimer)
return;
remainingTicks = 25;
[self updateLabel];
countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: #selector(handleTimerTick) userInfo: nil repeats: YES];
}
-(void)handleTimerTick
{
remainingTicks--;
[self updateLabel];
if (remainingTicks <= 0) {
[countdownTimer invalidate];
countdownTimer = nil;
}
}
-(void)updateLabel
{
theLabel.text = [[NSNumber numberWithUnsignedInt: remainingTicks] stringValue];
}

Slow down NSTimer with a for loop in Objective-C

I have a button that when pressed generates random numbers triggered by NSTimer at a certain frequency, and when released I would like it to keep generating them, just more slower and slower until it stops.
- (void)buttonPressed {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(generateNumber) userInfo:nil repeats:YES];
}
- (void)buttonReleased {
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
for (float i=0.20; i<1; i += 0.1) {
_timer = [NSTimer scheduledTimerWithTimeInterval:i target:self selector:#selector(generateNumber) userInfo:nil repeats:NO];
}
}
It works fine while the button is pressed, but once I release it actually accelerate and then stops all in a sudden. Any idea why it wouldn't be working or any alternative way I can reach the wanted result?
Once your button is released, generation accelerates because at that moment you schedule 8 timers with intervals 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 and 0.9 starting at the time of button release, which means each will execute 0.1s after the other, which is a smaller interval than your original timer (0.2s).
This is an alternative
#interface ViewController ()
#property (nonatomic, retain) NSTimer *timer;
#property (nonatomic) float curInterval;
#end
#implementation ViewController
- (IBAction)buttonDown {
self.curInterval = 0.1;
[self updatePressed];
}
- (void)updatePressed {
[self generateNumber];
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.curInterval target:self selector:#selector(updatePressed) userInfo:nil repeats:NO];
}
- (IBAction)buttonUp {
[self.timer invalidate];
[self updateUp];
}
- (void)updateUp {
[self generateNumber];
self.curInterval += 0.1;
if (self.curInterval < 1.0f) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.curInterval target:self selector:#selector(updateUp) userInfo:nil repeats:NO];
}
}
#end
In Button release method you are using for loop which keeps on executing untill it reaches interval of 1. What you need to do is take a global float value and initialize it to 0.20 at start. On button pressed pass that value. On button release increment the global variable and pass that value to NSTimer instead of for loop
float numTimer = 0.20f;
- (void)buttonPressed {
_timer = [NSTimer scheduledTimerWithTimeInterval:numTimer target:self selector:#selector(generateNumber) userInfo:nil repeats:YES];
}
- (void)buttonReleased {
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
numTimer = numTimer + 0.1f;
_timer = [NSTimer scheduledTimerWithTimeInterval:numTimer target:self selector:#selector(reGenerateNumber) userInfo:nil repeats:NO]; }
}
-(void) reGenerateNumber {
[self generateNumber];
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
numTimer = numTimer + 0.1f;
_timer = [NSTimer scheduledTimerWithTimeInterval:numTimer target:self selector:#selector(reGenerateNumber) userInfo:nil repeats:NO];
}

NSTimer move UIImageView faster

I use an NSTimer to move a UIImageView every 1 second, I want to decrease the time every 2 seconds from 1 to 0.5 as result the image will move faster inside the view. Any ideas will be very help full.
This is the timer that i use for moving the UIImageView
float obstaclesSpeed = 1.0;
movementTimer = [NSTimer scheduledTimerWithTimeInterval:obstaclesSpeed target:self selector:#selector(updateSpeed) userInfo:nil repeats:YES];
This is my code
-(void)updateSpeed {
obstaclesSpeed = obstaclesSpeed / 2;
[self startMoveObstacles];
}
I believe something I do wrong
Are you wanting to move the image every 2 seconds, or make it move increasingly faster? It won't move faster, if you only move it every 2 seconds.
You can read the docs for NSTimer, but to take some of the headache out of it, here's some examples of how to use NSTimer for this.
If you're wanting to move it every two seconds, you can do the following.
- (void) startTimer {
[_myTimer invalidate];
_myTimer = nil;
_myTimer = [NSTimer timerWithTimeInterval:2. target:self selector:#selector(respondToTimer:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_myTimer forMode:NSRunLoopCommonModes];
}
- (void)respondToTimer:(NSTimer*)timer {
//Code to move your UIImageView
}
If you're wanting to move it increasingly faster, you can do the following.
- (void) startTimer {
[_myTimer invalidate];
_myTimer = nil;
_myTimer = [NSTimer timerWithTimeInterval:_timeInterval target:self selector:#selector(respondToTimer:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:_myTimer forMode:NSRunLoopCommonModes];
}
- (void)respondToTimer:(NSTimer*)timer {
//Code to move your UIImageView
_numberOfMoves++;
if (_numberOfMoves < MAX_MOVES) {
_timeInterval /= 2;
[self startTimer];
}
}

Where do I properly start and invalidate an NSTimer?

in xcode, when i log my NSTimer, It starts atviewDidAppear and stops on viewdiddisappear which is fine, but when I go to an exit segue, the timer resumes (which I don't want to happen because its getting doubled).how do I properly stop it so it won't get doubled when called again?
..when I put in on viewdidload.sure it doesn't get doubled, but it won't start again since I invalidate it viewDidDisappear here is my code
-(void)viewDidAppear:(BOOL)animated{
if (self.timeInc.isValid == NO){
self.timeInc = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateDetailCounter:) userInfo:([Dateformatter2() dateFromString:_DetailModal[1]]) repeats:YES];
}
}
-(void)viewDidDisappear:(BOOL)animated{
[self.timeInc invalidate];
}
You can try this, in the past I had the same problem in viewDidAppear, viewDidDisappear
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (self.timerInc) {
[self.timerInc invalidate];
self.timerInc = nil;
}
_timerInc = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(doSth) userInfo:nil repeats:YES];
}
- (void) viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.timerInc invalidate];
self.timerInc = nil;
}

How to make a button appear and disappear throughout a timer

I have this app which has a timer in it and I want to be able to display a button at random points in that timer. Sort Of like a game setting where you have to get the button to get more time before it disappears. I already have some code , but the problem is that the timer that i already have is being messed up ( i can tell because it is linked to a label. It messed up because it goes down by 2 instead of 1 and this only happens when i have the code to make the button appear and disappear with the timer.
Here is the code to my timer that is being messed up:
-(IBAction)Ready:(id)sender {
[self performSelector:#selector(TimerDelay) withObject:nil afterDelay:1.0];
[self performSelector:#selector(randomTimer) withObject:nil afterDelay:0.5];
}
-(void)TimerDelay {
MainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
Here is the code to the button:
-(IBAction)Ready:(id)sender { //the same ready action as above
[self performSelector:#selector(TimerDelay) withObject:nil afterDelay:1.0];
[self performSelector:#selector(randomTimer) withObject:nil afterDelay:0.5];
}
-(void)TimerDelay {
MainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
- (void)randomTimer {
NSInteger randomTime = arc4random_uniform(0); //Some number between 0 and 9
timer = [NSTimer scheduledTimerWithTimeInterval:randomTime
target:self
selector:#selector(showButton)
userInfo:nil
repeats:NO];
}
- (void)showButton {
if(self.plus5.hidden == YES) {
self.plus5.hidden = NO;
}
else {
self.plus5.hidden = YES;
}
[self TimerDelay]; //Call random timer function again to run this method at a future random time
}
You are calling "randomTimer" and "TimerDelay" (this should be "timerDelay") one after the other and scheduling and REscheduling "timer".
I think you should reconsider your architecture, here...
EDIT: Use just one timer and let it manage your button.
- (void)somewhereInYourCode
{
shouldShowButton = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timeFired)
userInfo:nil
repeats:YES];
}
- (void)timeFired
{
// Here your countdown and...
if (shouldShowButton) {
NSInteger randomTimeInt = arc4random_uniform(9); // as suggested by Bergasms
float randomTimeFloat = randomTimeInt;
[self performSelector:#selector(showButton) withObject:nil afterDelay:randomTimeFloat];
shouldShowButton = NO;
}
}
This way your timer won't (probably) mess up.
This:
arc4random_uniform() will return a uniformly distributed random number
less than upper_bound.
is one of your problems.
NSInteger randomTime = arc4random_uniform(0); //Some number between 0 and 9
needs to be
NSInteger randomTime = arc4random_uniform(9); //Some number between 0 and 9
I cannot say for the rest of your code. But the line you have will always return 0, which means the random timer will always execute instantly.

Resources