Problem with the counter of collisions - iphone

Here is my code :
-(void)detectCollision{
imageView.center = CGPointMake(imageView.center.x + X, imageView.center.y + Y);
if(CGRectIntersectsRect(imageView.frame,centre.frame)){
label.text= [NSString stringWithFormat:#"%d", count];
++count;
}
I have a CADisplayLink(60fps) on detectCollision.
I want to increment "count" of one every time "imageView" collide with "centre", but my problem is that count increment too fast, every time there is a collision it increment of near 100 or 200, I don't know why. How can I solve this ?

Its because everytime the frames start intersecting in,
if(CGRectIntersectsRect(imageView.frame,centre.frame))
your condition will be true until the frames separate and the count increases over 100 in the CADisplayLink
so you can use a BOOL and set it to true when the frames first intersects. then check whether they are separate and make the BOOL back to false.
initialize BOOL intersectFlag to false in init. I assume that the frames wont intersect initially.
-(void)detectCollision
{
imageView.center = CGPointMake(imageView.center.x + X, imageView.center.y + Y);
if(!intersectFlag)
{
if(CGRectIntersectsRect(imageView.frame,centre.frame))
{
intersectFlag = YES;
label.text= [NSString stringWithFormat:#"%d", count];
++count;
}
}
else
{
if(!CGRectIntersectsRect(imageView.frame,centre.frame))
{
intersectFlag = NO;
}
}
}

to find out collision u should use with bounds not frame
bounds - size inside of object
frame - offset from superview x,y + size(bounds)
here i assume u are in portrait mode
-(void)detectCollision{
if(CGRectContainsPoint( imageView.bounds, CGPointMake(160, 240)) ){
label.text= [NSString stringWithFormat:#"%d", count];
++count;
}
}

Related

How to move image in the background of the view? [duplicate]

This question already has answers here:
Closed 10 years ago.
I have a problem in my application i have a moving image it works fine.
But my image is also moving over a button, that i can't click when the image is before the button. How can i make sure that the image is moving on the background of my view so i can still press the button.
This is the code for the moving image
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[self navigationController] setNavigationBarHidden:YES animated:YES];
[self loadImage];
image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cow.png"]];
image.frame =self.view.bounds;
[[self view] addSubview:image];
[NSTimer scheduledTimerWithTimeInterval: 3
target: self
selector:#selector(moveImage:)
userInfo: nil repeats:YES];
}
-(void) moveImage: (NSTimer*)timer {
CGFloat x = (CGFloat) (arc4random() % (int) self.view.bounds.size.width);
CGFloat y = (CGFloat) (arc4random() % (int) self.view.bounds.size.height);
CGPoint pointOne=CGPointMake(x,y);
image.center=pointOne;
}
}
The problem lies in the fact that arc4random_uniform() calls take an upper bounds, not a 0-based count of args (as you, cleverly some would say, extrapolated). Your equation is nearly-sound, however flawed in a few places, which I've tried to correct with some documentation:
-(void)someAction:(id)sender {
NSInteger imageIndex1 = arc4random_uniform(self.images.count); //upper bounds, so no -1
NSInteger imageIndex2 = arc4random_uniform(self.images.count); //upper bounds, so no -1
NSInteger imageIndex3 = arc4random_uniform(self.images.count); //upper bounds, so no -1
_Bool b1 = true, b2 = true, b3 = true; //I can only assume you've been declaring GNU C booleans because of the lowercase false.
//be careful, in Objective-C land, BOOL is signed char.
if (imageIndex1 == imageIndex2) {
b1 = false;
imageIndex2 = arc4random_uniform(self.images.count); //upper bounds, so no -1
}
if(imageIndex1 == imageIndex3) {
b2 = false;
imageIndex1 = arc4random_uniform(self.images.count); //upper bounds, so no -1
}
if (imageIndex2 == imageIndex3) {
b3 = false;
imageIndex3 = arc4random_uniform(self.images.count); //upper bounds, so no -1
}
//You have to use ors here, otherwise your UI will never actually update, considering that in checking
//for unique factors, then reassigning to another unique factor if a check fails, one of them has got
//to be true before the UI can update, rather than all 3 at once.
//Perhaps an individual check of each boolean would be more effective.
if(b1 == true || b2 == true || b3 == true ) {
[self.picture1 setImage:self.images[imageIndex1]];
[self.picture2 setImage:self.images[imageIndex2]];
[self.picture3 setImage:self.images[imageIndex3]];
}
}
I'm guessing you're looking for a random index that isn't the current index, so that you can pick a random, different index, rather than just a random index.
- (NSUInteger)randomUnsignedLessThan:(NSInteger)max excluding:(NSUInteger)exclude {
NSInteger firstTry = -1;
while (firstTry == exclude) firstTry = arc4random() % max;
return firstTry;
}
Note that this approach will always call arc4random once, and require 1+N calls with a probability of 1/max^N, so for low ranges, and high performance requirements, you might consider a different algorithm to exclude the one index.

Reduce number in text box by one for each button tap

I'm relatively new to Objective-C so this might be really simple to do: I have a text box in my application that displays an ammo count, so each time the user taps a fire button the number in the text box will go down by one (12 > 11 > 10, etc) to 0. I have tried using for and if statements, but they are not working (I may have used incorrect syntax). This is what I'm using right now, but obviously I need the
- (IBAction)fire {
[ammoField setText:#"11"];
}
- (IBAction)reload {
[ammoField setText: #"12"];
}
The simplest way would be to convert the text to a number, decrement that and the reset the text, i.e. replace the code in the fire method with:
NSInteger ammoCount = [ammoField.text integerValue];
ammoCount--;
ammoField.text = [NSString stringWithFormat:#"%d", ammoCount];
But don't do this, it will make baby Steve Jobs cry.
A better way would be to add a new variable to the class of type UIInteger that tracks the the number of bullets, i.e.:
// in interface
NSInteger _ammoCount;
...
// in implementation
- (IBAction)fire {
_ammoCount--;
if (_ammoCount <= 0) {
_ammoCount = 0;
fireButton.enabled = NO;
}
[ammoField setText: [NSString stringWithFormat:#"%d", _ammoCount]];
}
- (IBAction)reload {
_ammoCount = 12;
[ammoField setText: [NSString stringWithFormat:#"%d", _ammoCount]];
fireButton.enabled = YES;
}
Oh, and don't forget to call reload at some point early on to ensure _ammoCount and ammoField get initialised.
Set Instance Integer
int x;
set value of it
x = 12;
do change in method
- (IBAction)fire {
[ammoField setText:[NSString stringWithFormat:#"%i",x]];
x--;
}
set the value of count in viewdidload with an int variable
fire method decrease the count by 1
and reload method to return value to 12
log or use values accordingly
Try this:-
int i;
-(void)ViewDidLoad
{
i=12;
}
- (IBAction)fire
{
[ammoField setText:[NSString stringWithFormat:#"%d",i]];
i--;
}
- (IBAction)reload {
i = 12;
[ammoField setText: [NSString stringWithFormat:#"%d", i]];
}
Hope it will work for you. Thanks :)

how to use the UISlider and how to set the slider on a particular values?

i am using an UIslider first time.
first i want to know how to gat value of slider positon if the range of value is 0 to 10:
second i want my slider just set at 5 different values .
like 1, 2, 3, 4, 5
slider should not set between the labeled value
first u set textfiled and add this function into code
-(IBAction)changeSlider:(id)sender
{
text_field .text= [[NSString alloc] initWithFormat:#" Value %d ", (int)slider.value];
}
I followed this tutorial for mine and it was very helpful there are variables you can set in the code such as max number and how much the slider increases each time. Link: http://www.xprogress.com/post-35-uislider-tutorial-example-how-to-use-slider-in-iphone-sdk-xcode/
In this case I set the slider in XCode to have values of: 0-3. But the slider value is float: 0.000 - 3.000.
// **** Cylinder Volume Slider ****
- (NSInteger) normalizeValueCylinderVolumeSlider:(float) value
{
NSInteger normalizedValue = 0;
if (value>1.5)
{
if (value>2.5)
normalizedValue = 3;
else
normalizedValue = 2;
}
else if (value>0.5)
normalizedValue = 1;
return normalizedValue;
}
- (IBAction)valueChangedCylinderVolumeSlider:(UISlider *)sender
{
float value = [sender value];
NSInteger normalizedValue;
// Step 1:
normalizedValue = [self normalizeValueCylinderVolumeSlider:value];
// Step 2:
if (normalizedValue>value)
{
if ((normalizedValue-value)<0.3)
sender.value = normalizedValue;
}
else if ((value-normalizedValue)<0.3)
sender.value = normalizedValue;
}
- (IBAction)touchUpInsideCylinderVolumeSlider:(UISlider *)sender
{
float normalizedValue = 0;
normalizedValue = [self normalizeValueCylinderVolumeSlider:[sender value]];
sender.value = normalizedValue;
}
- (IBAction)touchUpOutsideCylinderVolumeSlider:(UISlider *)sender
{
float normalizedValue = 0;
normalizedValue = [self normalizeValueCylinderVolumeSlider:[sender value]];
sender.value = normalizedValue;
}
On valueChanged action, (step 1) I set the value to rigid values: 0, 1, 2, 3. And (step 2) I stick the slider thumb to the rigid values if it get close by 0.3 from the rigid value.
On touchUpInside & touchUpOutside I repeat 'step 1' code from valueChanged action to fix the slider value for the case that the drag action end outside the stick range ('step 2').
The best is to put all this code in a sub-class of Slider. But this is my only first week / attempt on iOS development.

Animating sequence of images in cocos2d

i have this code to show animation of a image
-(void) blink:(ccTime) delta {
animateblink ++; //adds 1 every frame
if (animateblink <= 6 ) { //if we included frames to show for breaking and the current frame is less than the max number of frames to play
if (animateblink < 6) {
[sprite setTexture:[[CCSprite spriteWithFile:[NSString stringWithFormat:#"%#_blinkk00%i.png", baseImageName,animateblink]] texture]];
[self unschedule:_cmd];
[self schedule:#selector(openEyes:) interval:0.1f];
[self schedule:#selector(moveSprite:) interval:0.1f];
}
}
}
i have 6 images of animating like
dragonimage_blinkk001,dragonimage_blinkk002,dragonimage_blinkk003,dragonimage_blinkk004,dragonimage_blinkk005,dragonimage_blinkk006 like that
i put two methods,
1: for animation time
2: for movement of the image
the code is
-(void) openEyes:(ccTime) delta {
[sprite setTexture:[[CCSprite spriteWithFile:[NSString stringWithFormat:#"%#.png", baseImageName]] texture]];
[self unschedule:_cmd];
int blinkInterval = (arc4random() % 6) + 1; // range 3 to 8
[self schedule:#selector(blink:) interval:blinkInterval];
}
-(void)moveSprite:(ccTime)delta
{
movementCounter ++;
if (movementCounter == 1000) {
[self unschedule:_cmd];
}
else
{
spriteimagename.position = ccp(spriteimagename.position.x+10,spriteimagename.position.y);
}
}
but on the first method the animation time is not correct,there is a lot of delay of animation,i just want to show animation of the images randomly and fast,its a dragon flying animation.
my sec on method is not at all working,i didn't get any movement of that image.
i hope you understand my issue.how to solve the above two method issues.
Thanks in advance.
Quick solution is to add frameIndex member in cocos2d CCSpriteFrame class. i don't know is that allowed to change. But it works fine.
#interface CCSpriteFrame : NSObject <NSCopying>
{
int frameIndex;
....
}
//Here in code initialize frames with unique index
CCAnimation* animation;
NSMutableArray *animFrames2 = [NSMutableArray array];
for( int i=1;i<=15;i++)
{
CCSpriteFrame *frame = [cache spriteFrameByName:[NSString stringWithFormat:#"ActerSmash_%d.png",i]];
frame.frameIndex = (int)i;
[animFrames2 addObject:frame];
}
animation = [CCAnimation animationWithFrames:animFrames2];
CCAnimate *action = [CCAnimate actionWithDuration:ACTER_SMASH_SPEED animation:animation restoreOriginalFrame:YES];
action.tag = kTagAnimationSmashAnim ;
mActer.AnimSmash = action;
//Checking frame Index
CCAnimate *anim = mActer.AnimSmash ;
for(CCSpriteFrame *frame in anim.animation.frames)
{
if([mActer isFrameDisplayed:frame] ) )
{
if(frame.frameIndex == 5 )
{
//Do something..
}
}
}

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