I have a UIImageView setup called needleImageView which i need to rotate 360degrees over 10 seconds the point 20.00 20.00 of the ImageView.
Anybody able to show me sample code for this functionality?
Thanks,
-Code
Here is the logic... Try implementing.
On starting timer
//in header file
fireInterval = 10;
mStartingAngle = 0;
mEndingAngle = 360;
//Implementation
-(void) startTimer
{
mPreviousTime = [NSDate timeIntervalSinceReferenceDate];
}
In the loop
-(void) updateFunction
{
NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate];
//NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
//Mapping values between mStartAngle and mEndAngle
mCurrentAngle = (((timeNow - mPreviousTime) * (mEndingAngle - mStartingAngle)) / (previousTime+fireInterval - mPreviousTime)) + mStartingAngle;
if( mPreviousTime + fireInterval <= timeNow )
{
NSLog(#"10 seconds completed");
mPreviousTime = timeNow;
}
}
Related
i used bellow code for scrolling speed on UIWebview,
compare to previous scrolling its fine and good, but my clint was not satisfied and he asked like this
Scrolling still feels stiff.
webviews.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
[webviews loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"site URL"]]];
webviews.scalesPageToFit =YES;`
is there any option to increase scrolling speed?
Have these properties on your UIScrollViewDelegate
CGPoint lastOffset;
NSTimeInterval lastOffsetCapture;
BOOL isScrollingFast;
Then have this code for your scrollViewDidScroll:
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint currentOffset = self.currentChannelTableView.contentOffset;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval timeDiff = currentTime - lastOffsetCapture;
if(timeDiff > 0.1) {
CGFloat distance = currentOffset.y - lastOffset.y;
//The multiply by 10, / 1000 isn't really necessary.......
CGFloat scrollSpeedNotAbs = (distance * 10) / 1000; //in pixels per millisecond
CGFloat scrollSpeed = fabsf(scrollSpeedNotAbs);
if (scrollSpeed > 0.5) {
isScrollingFast = YES;
NSLog(#"Fast");
} else {
isScrollingFast = NO;
NSLog(#"Slow");
}
lastOffset = currentOffset;
lastOffsetCapture = currentTime;
}
}
I am developing a QuiZ app. It needs a countdown timer, In that I want to start a timer at 75:00.00 (mm:ss.SS) and decrease it to 00:00.00 (mm:ss.SS) by reducing 1 millisecond. I want to display an alert that Time UP! when time reaches to 00:00.00 (mm:ss.SS).
I am displaying the time by following below link
Stopwatch using NSTimer incorrectly includes paused time in display
Here is a simple solutions to your problem.
Declarations
#interface ViewController : UIViewController
{
IBOutlet UILabel * result;
NSTimer * timer;
int currentTime;
}
- (void)populateLabelwithTime:(int)milliseconds;
-(IBAction)start;
-(IBAction)pause;
#end
Definition
- (void)viewDidLoad
{
[super viewDidLoad];
currentTime = 270000000; // Since 75 hours = 270000000 milli seconds
}
-(IBAction)start{
timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(updateTimer:) userInfo:nil repeats:YES];
}
-(IBAction)pause{
[timer invalidate];
}
- (void)updateTimer:(NSTimer *)timer {
currentTime -= 10 ;
[self populateLabelwithTime:currentTime];
}
- (void)populateLabelwithTime:(int)milliseconds {
int seconds = milliseconds/1000;
int minutes = seconds / 60;
int hours = minutes / 60;
seconds -= minutes * 60;
minutes -= hours * 60;
NSString * result1 = [NSString stringWithFormat:#"%#%02dh:%02dm:%02ds:%02dms", (milliseconds<0?#"-":#""), hours, minutes, seconds,milliseconds%1000];
result.text = result1;
}
Use following code for reducing timer.
double dblRemainingTime=60; //1 minute
if(dblRemainingTime >0)
{
dblRemainingTime -= 1;
int hours,minutes, seconds;
hours = dblRemainingTime / 3600;
minutes = (dblRemainingTime - (hours*3600)) / 60;
seconds = fmod(dblRemainingTime, 60);
[lblRemainingTime setText:[NSString stringWithFormat:#"%02d:%02d",minutes, seconds]];
}
else
alert('Time up buddy');
I'm trying to implement a gauge animation using (+ and - buttons) on iphone, but i have no idea where to start? Any help is really welcome. See the image below (this is what I'm trying to do). Thanks for your help.
Here is some open source code (with an example) that implements the gauge view. You of course would still need to do the buttons yourself, and possible add a different visual style.
http://www.cocoacontrols.com/platforms/ios/controls/meterview
You need to rotate the needle based on the angle... Here is the logic
You can refer my answer here... Rotating a UIImageView around a point over 10 seconds?
fireInterval = 10;
//Adjust starting and ending angle
mStartingAngle = 45;
mEndingAngle = 180;
//Implementation
-(void) startTimer
{
mPreviousTime = [NSDate timeIntervalSinceReferenceDate];
}
In the loop
-(void) updateFunction
{
NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate];
//NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
//Mapping values between mStartAngle and mEndAngle
mCurrentAngle = (((timeNow - mPreviousTime) * (mEndingAngle - mStartingAngle)) / (previousTime+fireInterval - mPreviousTime)) + mStartingAngle;
if( mPreviousTime + fireInterval <= timeNow )
{
NSLog(#"10 seconds completed");
mPreviousTime = timeNow;
}
}
And rotate the needle based on mCurrentAngle....
I have posted something similar before and I got some suggestion which I have tried but I am still having problems...thus, will like to ask for any assistance on reviewing this code.
I am actually trying to get the ball object in the code to have a better or smoother animation and to increase in its speed constantly until it attains a maximum speed but right now what I am getting is the ball starting at the specified speed and then its movement becomes erratic as the speed increases and after a few second the ball just moves off the iphone simulator screen.
Can someone help me run this code(please add an image to represent the ball in IB) to see what I am not doing correctly.
Thanks in advance for your help.
.h
#interface ViewController : UIViewController
{
UIImageView *ball;
int speedX;
int speedY;
CGPoint ballMovement;
}
#property (nonatomic, retain) IBOutlet UILabel *scoreLabel;
#property (nonatomic, retain) IBOutlet UIImageView *ball;
- (void)initializeTimer;
- (void)animateBall:(NSTimer *)theTimer;
#end
.m
#implementation ViewController
#synthesize ball;
- (void)dealloc {
[ball release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
ball.center = CGPointMake(50,50);
speedX = 1;
speedY = 1;
ballMovement = CGPointMake(speedX,speedY);
[self initializeTimer];
}
- (void)initializeTimer {
float theInterval = 0.1f;
[NSTimer scheduledTimerWithTimeInterval:theInterval target:self selector:#selector(animateBall:) userInfo:nil repeats:YES];
}
- (void)animateBall:(NSTimer *)theTimer {
ball.center = CGPointMake(ball.center.x+speedX, ball.center.y+speedY);
speedX += 1;
speedY += 1;
NSLog(#"%d,%d", speedX, speedY);
if (speedX <= 1)
speedX ==1;
if (speedY <= 1)
speedY ==1;
if(ball.center.x > 300 || ball.center.x < 20)
speedX = -abs(speedX);
if(ball.center.y > 440 || ball.center.y < 40)
speedY = -abs(speedY);
}
You are not capping the speed anywhere, so how is it supposed to reach a constant speed? From your code, once you pass ball.center.x > 300, you reverse the speed.
The rows
if (speedX <= 1) speedX ==1;
if (speedY <= 1) speedY ==1;
Do nothing, since they don't actually assign a value to speedX / speedY. It looks like this is what you mean:
if (speedX <= 1) speedX = 1;
if (speedY <= 1) speedY = 1;
Even so, this won't actually do what you want. If you want a max speed, then it should be something like this:
// Compact version
speedX = MIN(speedX + 1, TARGET_SPEED_X);
// More like your code:
speedX += 1;
if (speedX > TARGET_SPEED_X) speedX = TARGET_SPEED_X;
If you want the ball to bounce off the bottom, with gravity along the y axis:
- (void)animateBall:(NSTimer *)theTimer {
ball.center = CGPointMake(ball.center.x+speedX, ball.center.y+speedY);
speedY += 1;
if(ball.center.x > 300) {
speedX = -abs(speedX);
}
if(ball.center.y > 440)
speedY = -abs(speedY);
}
The main cause of the erratic movement you see is probably because of the bounce off the top/side of the screen. For instance:
if(ball.center.y > 440 || ball.center.y < 40)
speedY = -abs(speedY);
What happens when the ball is speeding towards the top here? Say ball.center.y = 30, speedY = -4.
Your speedY will then stay at -4. Next pass it's -3, then -2, then -1, and then it'll oscillate between -1 and 0. The same happens for speedX eventually.
The question is what sort of movement you are looking for. Your original code had something that looked like constant acceleration in the (1, 1) direction, with a bounce effect in the right and bottom corner, but your description said you wanted acceleration to a maximum speed.
For an accelerating ball with a maximum speed:
#interface ViewController : UIViewController {
UIImageView *ball;
double speedX;
double speedY;
int maxSpeed;
double acceleration;
CGPoint ballMovement;
}
#property (nonatomic, retain) IBOutlet UIImageView *ball;
- (void)initializeTimer;
- (void)animateBall:(NSTimer *)theTimer;
#end
#implementation ViewController
#synthesize ball;
- (void)dealloc {
[ball release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
ball.center = CGPointMake(50,50);
speedX = 1;
speedY = 1;
maxSpeed = 20;
acceleration = 1;
ballMovement = CGPointMake(speedX,speedY);
[self initializeTimer];
}
- (void)initializeTimer {
float theInterval = 0.1f;
[NSTimer scheduledTimerWithTimeInterval:theInterval target:self selector:#selector(animateBall:) userInfo:nil repeats:YES];
}
- (void)animateBall:(NSTimer *)theTimer {
ball.center = CGPointMake(ball.center.x + speedX, ball.center.y + speedY);
// Discover the actual speed.
double actualSpeed = sqrt(speedX * speedX + speedY * speedY);
// Increase the speed by the acceleration (actually acceleration * time interval),
// Cap at max speed
double newSpeed = MIN(acceleration + actualSpeed, maxSpeed);
// Increase velocity uniformly along both x and y axis
// (This example does not properly handle when speedX and speedY both start at zero)
speedX = speedX * newSpeed / actualSpeed;
speedY = speedY * newSpeed / actualSpeed;
// Make sure to bounce
if (ball.center.x > 300) speedX = -abs(speedX);
if (ball.center.x < 20) speedX = abs(speedX);
if (ball.center.y > 440) speedY = -abs(speedY);
if (ball.center.y < 40) speedY = abs(speedY);
}
#end
Acceleration = Speed / Delta_time
So you have to modify the code:
- (void)animateBall:(NSTimer *)theTimer {
ball.center = CGPointMake(ball.center.x+speedX, ball.center.y+speedY);
static float acceleration = 1.0f;
speedX += acceleration*theTimer.timeInterval;
speedY += acceleration*theTimer.timeInterval;
NSLog(#"%d,%d", speedX, speedY);
if (speedX <= 1)
speedX ==1;
if (speedY <= 1)
speedY ==1;
if(ball.center.x > 300 || ball.center.x < 20)
speedX = -abs(speedX);
if(ball.center.y > 440 || ball.center.y < 40)
speedY = -abs(speedY);
}
I'm making a game on iPhone using cocos2d, and I have a question.
In my init method I'm doing this :
[self schedule:#selector(newMonster:) interval:1];
It create a new monster every second.
But I'd like that the interval change over time. For example :
The 10 first seconds of the game: a new monster appears every 1 second.
Then for 10 seconds: a new monster appears every 0.8 second.
And after every 0.5 second...
How can I do that?
Thanks !
You may try this- (I have copied some code from #bddckr)
Initial time:
self.monsterSpawnStartDate = [NSDate date];
self.lastTimeScheduledBefore = 0;//new var
Scheduled Method to create monster
- (void)scheduledMethod {
NSTimeInterval seconds = [[NSDate date] timeIntervalSinceDate:monsterSpawnStartDate];
[self newMonster]; // Let a new monster spawn
if (seconds >= 20.0 && lastTimeScheduledBefore == 10){
[self unschedule:#(scheduledMethod)];
[self unschedule:#(scheduledMethod) interval:0.5];
lastTimeScheduledBefore = 20;
}
else if (seconds >= 10.0 && lastTimeScheduledBefore == 0){
[self unschedule:#(scheduledMethod)];
[self unschedule:#(scheduledMethod) interval:0.8]
lastTimeScheduledBefore = 10;
}
}
You can modify it as your need. You can use mod if it goes through a cycle.
Make an instance variable and property of NSDate called monsterSpawnStartDate, make it an retaining property and synthesize it.
As soon as your first monster should be created, set it:
self.monsterSpawnStartDate = [NSDate date]; // Current date and time
And replace your code by this:
[self schedule:#selector(adjustMonsterSpawnRate) interval:0.1]; // Seems like you want it to fire every 0.1 seconds
Implement adjustMonsterSpawnRate like this:
- (void)adjustMonsterSpawnRate {
NSTimeInterval seconds = [[NSDate date] timeIntervalSinceDate:monsterSpawnStartDate];
if (((seconds <= 10.0) && (seconds % 1.0)) || ((seconds <= 20.0) && (seconds % 0.8)) ((seconds > 20.0) && (seconds % 0.5)))
[self newMonster]; // Let a new monster spawn
}
I think a better option would be to use a scheduled function for timing and use accumulated time to trigger the enemy creation as follows
self.time_since_last_monster = 0
[self schedule:#selector(new_monster:) interval:0.3];
-(void) new_monster:(ccTime)dt{
self.time_since_last_monster += dt;
if(self.time_since_last_monster > monster_interval){
self.time_since_last_monster -= monster_interval;
[self create_new_monster];
// at this point based on some condition, you can now change monster_interval
}
}
This would give more flexibility.
I'm pretty dumb, so here's what I'd do:
in the .h set a float
float nextMonsterIn;
then in the body
nextMonsterIn = 1.0;
[self scheduleOnce:#selector(newMonster:) interval:nextMonsterIn];
[self schedule:#selector(kickUpDifficulty:) interval:10];
- (void) newMonster : (ccTime) dt
{
[self scheduleOnce:#selector(newMonster:) interval:nextMonsterIn];
//-----make a monster-----
}
- (void) kickUpDifficulty : (ccTime) dt
{
if(nextMonsterIn == 1.0)
nextMonsterIn = 0.8;
else if(nextMonsterIn == 0.8)
{
nextMonsterIn = 0.5;
[self unschedule:#selector(kickUpDifficulty:)];
}
}
Basically every time I call newMonster i'd recursively re-schedule the newMonster based on my current delay, then I can adjust the delay in a timer or every time a monster is killed or wherever.