How to increase scrolling speed on uiwebview - iphone

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;
}
}

Related

How to change a UISlider value using a single touch?

I'm developing my first iOS app which contains a UISlider. I know how to get the value when the UISlider is dragged. But for my app I need to get the slider's value in a single touch; i.e. if I touch somewhere in the UISlider, a UILabel should display its correct value.
Is it possible to this way. Any tutorial or code will very helpful.
Here tapCount is int variable that declare in .h file
- (void)viewDidLoad
{
tapCount = 0; // Count tap on Slider
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(sliderTapped:)];
[slider addGestureRecognizer:gr];
}
- (void)sliderTapped:(UIGestureRecognizer *)g
{
/////////////// For TapCount////////////
tapCount = tapCount + 1;
NSLog(#"Tap Count -- %d",tapCount);
/////////////// For TapCount////////////
UISlider* s = (UISlider*)g.view;
if (s.highlighted)
return; // tap on thumb, let slider deal with it
CGPoint pt = [g locationInView: s];
CGFloat percentage = pt.x / s.bounds.size.width;
CGFloat delta = percentage * (s.maximumValue - s.minimumValue);
CGFloat value = s.minimumValue + delta;
[s setValue:value animated:YES];
NSString *str=[NSString stringWithFormat:#"%.f",[self.slider value]];
self.lbl.text=str;
}
For Swift User
override func viewDidLoad()
{
super.viewDidLoad()
tapCount = 0
let gr = UITapGestureRecognizer(target: self, action: #selector(self.sliderTapped(_:)))
slider.addGestureRecognizer(gr)
}
func sliderTapped(_ g: UIGestureRecognizer) {
/////////////// For TapCount////////////
tapCount = tapCount + 1
print("Tap Count -- \(tapCount)")
/////////////// For TapCount////////////
let s: UISlider? = (g.view as? UISlider)
if (s?.isHighlighted)! {
return
}
// tap on thumb, let slider deal with it
let pt: CGPoint = g.location(in: s)
let percentage = pt.x / (s?.bounds.size.width)!
let delta = Float(percentage) * Float((s?.maximumValue)! - (s?.minimumValue)!)
let value = (s?.minimumValue)! + delta
s?.setValue(Float(value), animated: true)
let str = String(format: "%.f", slider.value)
lbl.text = str
}
Correction #ipatel: Math in previous answers is incomplete and causes jitter due to missing thumb width considerations.
Here is what it should look like if you choose to subclass UISlider:
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
[super beginTrackingWithTouch:touch withEvent:event];
CGPoint touchLocation = [touch locationInView:self];
CGFloat value = self.minimumValue + (self.maximumValue - self.minimumValue) *
((touchLocation.x - self.currentThumbImage.size.width/2) /
(self.frame.size.width-self.currentThumbImage.size.width));
[self setValue:value animated:YES];
return YES;
}
Swift version for accepted answer,
#IBAction func sliderTappedAction(sender: UITapGestureRecognizer)
{
if let slider = sender.view as? UISlider {
if slider.highlighted { return }
let point = sender.locationInView(slider)
let percentage = Float(point.x / CGRectGetWidth(slider.bounds))
let delta = percentage * (slider.maximumValue - slider.minimumValue)
let value = slider.minimumValue + delta
slider.setValue(value, animated: true)
}
}
You can display the current value of UISlider with its action method like below.
- (IBAction) sliderValueChanged:(UISlider *)sender {
yourLable.text = [NSString stringWithFormat:#"%.1f", [sender value]];
}
See these tutorials and examples of UISlider:
UISlider-tutorial-example-how-to-use-slider-in-iphone-sdk-xcode.
iphone-slider-control-uislider-control-tutorial.
This second tutorial with example which display the current (Latest) value of UISlider in UILable see the image below for example.

Show UIImageView in a random position on the screen

I am developing a game that uses the gyroscope to keep enemies in relatively the same place, with the following code:
if([motionManager isGyroAvailable])
{
[motionManager setGyroUpdateInterval:0.05];
[motionManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMGyroData *gyroData, NSError *error)
{
valueX3 = gyroData.rotationRate.y* 50;
valueY3 = gyroData.rotationRate.x* 50;
int newX3 = (int)(enemyufoG.center.x +valueY3);
int newY3 = (int)(enemyufoG.center.y -valueX3);
CGPoint newCenter2 = CGPointMake(newX3, newY3);
enemyufoG.center = newCenter2;
valueX2 = gyroData.rotationRate.y* 50;
valueY2 = gyroData.rotationRate.x* 50;
int newX2 = (int)(enemyufoR.center.x +valueY2);
int newY2 = (int)(enemyufoR.center.y -valueX2);
CGPoint newCenter = CGPointMake(newX2, newY2);
enemyufoR.center = newCenter;
valueX = gyroData.rotationRate.y* 50;
valueY = gyroData.rotationRate.x* 50;
int newX = (int)(enemyAlien.center.x +valueY);
int newY = (int)(enemyAlien.center.y -valueX);
CGPoint newCenter3 = CGPointMake(newX, newY);
enemyAlien.center = newCenter3;
}];
}
Once you shoot an enemy that is in the crosshairs of the gun, it hides the UIImageView, then uses NSTimer to call a different method that shows it again. I would like to have the enemies reappear in random positions on the screen.
CGPoint pos = enemyAlien.center;
if ((pos.x > 254) && (pos.x < 304) && (pos.y > 140) && (pos.y < 160 && _ammoCount != 0))
{
enemyAlien.hidden = YES;
[dangerBar setProgress:dangerBar.progress-0.10];
_killCount = _killCount+3;
[killCountField setText: [NSString stringWithFormat:#"%d", _killCount]];
timer = [NSTimer scheduledTimerWithTimeInterval: 4.0
target: self
selector: #selector(showAlien)
userInfo: nil
repeats: NO];
}
- (void) showAlien {
enemyAlien.hidden = NO;
}
When I try and use enemyAlien.center = enemyAlien.center + arc4random()%100; above enemyAlien.hidden = NO, I get the following error:
'Invalid operands to binary expression ('CGPoint (aka 'struct CGPoint') and 'unsigned int').
You're trying to add an integer to a cgpoint.
try this.
enemyAlien.center = CGPointMake(enemyAlien.center.x + (arc4random()%100),enemyAlien.center.y + (arc4random()%100));
although this will only move the alien in a diagonal direction. You should probably change it to the following for a better experience.
enemyAlien.center = CGPointMake((arc4random()%SCREEN_WIDTH),(arc4random()%SCREEN_HEIGHT));
where SCREEN_WIDTH and SCREEN_HEIGHT are the dimensions of your playing field.

How to implement powerUps and other game altering objects in objective-C or cocos2d

Ok, so I have these powerups that I want to slow/speed up the movement of the other objects in the game for a few seconds.
I have an array of objects that I have a variable called spawnInterval that gets faster and faster as the game progresses, making the ame get harder after a few mins.
But I can't really grasp how to make it so the character in the game will react differently to different objects as in when the fastPowerUp is hit by the character sprite, the spawn interval doesn't change.
And vice versa with the slowPowerUp.
the code I have at the moment is this in a move sequence method that gets called in an update method:
-
(void) updateObstacles:(ccTime)delta{
for (int i = 0; i < 20; i++) {
//int randomizer = CCRANDOM_0_1() * [obstacles count];
//NSLog(#"randomizer: %i",randomizer);
CCSprite* randomObject = [obstacles randomObject];
currentObject = [obstacles indexOfObject:randomObject];
if ([randomObject numberOfRunningActions] == 0) {
[self runObstacleMoveSequence:randomObject withTimer:delta];
break;
}
}
}
-(void) runObstacleMoveSequence:(CCSprite *)object withTimer:(ccTime)delta{
static int time;
//Slowly increase object speed
numObstaclesMoved++;
if (!slowPowerUp && !fastPowerUp) {
time += delta;
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration -= 0.2f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
}
}
}else if (slowPowerUp && !fastPowerUp) {
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration += 3.0f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
if (time >= (delta + 3)) {
slowPowerUp = NO;
obstacleMoveDuration -= 3.0f;
}
}
}
}else if (!slowPowerUp && fastPowerUp) {
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration -= 3.0f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
if (time >= (delta + 3)) {
fastPowerUp = NO;
obstacleMoveDuration += 3.0f;
}
}
}
}
CGSize screenSize = [[CCDirector sharedDirector]winSize];
CGPoint aboveScreenPosition = CGPointMake(object.position.x, screenSize.height - object.position.y);
int rotations = (CCRANDOM_0_1()*3) * 360;
float duration = (CCRANDOM_0_1()*5.0f) + 8.0f;
CCMoveTo* move = [CCMoveTo actionWithDuration:obstacleMoveDuration position:aboveScreenPosition];
CCRotateTo* rotate = [CCRotateBy actionWithDuration:duration angle:rotations];
CCSpawn* moveRotate = [CCSpawn actions: move, rotate, nil];
CCCallFuncN* call = [CCCallFuncN actionWithTarget:self selector:#selector(objectAboveScreen:)];
CCSequence* sequence = [CCSequence actions:moveRotate, call, nil];
[object runAction:sequence];
if (time >= (delta + 3)) {
fastPowerUp = NO;
}
}
-(void) objectAboveScreen:(id) sender{
//make sure sender is actually of the right class
NSAssert([sender isKindOfClass:[CCSprite class]], #"sender is not a CCSprite!");
CCSprite* obstacle = (CCSprite*)sender;
//move the back to the bottom of the screen
CGPoint pos = obstacle.position;
CGSize screenSize = [[CCDirector sharedDirector]winSize];
pos.y = (-screenSize.height - [obstacle texture].contentSize.height);
pos.x = CCRANDOM_0_1() * screenSize.width;
obstacle.position = pos;
}
I really just don't know where to go from here... Should I make the powerUps a different class? If so, how would I implement something like this? I really hate trying to ask for someone to solve my question, but I really just can't rack my brain around this and I'm rather new... if it were explained to me, then I know I would be able to implement it in future games on my own...
Thanks in advance, and let me know if more information is needed...
I'd do something like
in the .h file
float speedModifier;
-(void)resetPowerUp;
in the .m
-(void)resetPowerUp
{
speedModifier = 1;
}
wherever you are initializing the level
[self resetPowerUp];
upon collision with powerup:
speedModifier = 2;
[self performSelector:#selector(resetPowerUp) withObject:nil afterDelay:5];
then wherever you are moving whatever it is which speed should be effected by the powerup mode, multiply the speed of the animation (or divide the duration it takes for it to get wherever it's going) by speedModified
hope that helps

increasing and maintaing a constant speed of an object in objective C

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);
}

Rotating a UIImageView around a point over 10 seconds?

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;
}
}