IPHONE SDK, How to put Void function into my BOOL??? PLEASE! - iphone

I am using the IPhone's Accelerometer to make a object move. I want to be able to make this function work and not work depending on different states.
I have my code for my Accelerometer function and i want to put it into a BOOL so i can call on it when i need it, but i am having problems. Can anyone Help me put this code into a BOOL named:
-(BOOL) accelerometerWorks
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
valueX = acceleration.x*25.5;
int newX = (int)(ball.center.x +valueX);
if (newX > 320-BALL_RADIUS)
newX = 320-BALL_RADIUS;
if (newX < 0+BALL_RADIUS)
newX = 0+BALL_RADIUS;
int XA = (int)(balloonbit1.center.x +valueX);
if (XA > 320-BALL_RADIUS)
XA = 320-BALL_RADIUS;
if (XA < 0+BALL_RADIUS)
XA = 0+BALL_RADIUS;
int XB = (int)(balloonbit2.center.x +valueX);
if (XB > 320-BALL_RADIUS)
XB = 320-BALL_RADIUS;
if (XB < 0+BALL_RADIUS)
XB = 0+BALL_RADIUS;
int XE = (int)(balloonbit5.center.x +valueX);
if (XE > 320-BALL_RADIUS)
XE = 320-BALL_RADIUS;
if (XE < 0+BALL_RADIUS)
XE = 0+BALL_RADIUS;
int XF = (int)(balloonbit6.center.x +valueX);
if (XF > 320-BALL_RADIUS)
XF = 320-BALL_RADIUS;
if (XF < 0+BALL_RADIUS)
XF = 0+BALL_RADIUS;
int XH = (int)(balloonbit8.center.x +valueX);
if (XH > 320-BALL_RADIUS)
XH = 320-BALL_RADIUS;
if (XH < 0+BALL_RADIUS)
XH = 0+BALL_RADIUS;
ball.center = CGPointMake (newX, 415);
balloonbit1.center = CGPointMake (XA, 408);
balloonbit2.center = CGPointMake (XB, 395);
balloonbit5.center = CGPointMake (XE, 388);
balloonbit6.center = CGPointMake (XF, 413);
balloonbit8.center = CGPointMake (XH, 426);
}
Please help. i have been trying for ages with no success. Thanks.
Harry.

Here's my best guess about what you're after, with nothing to verify it on.
If all you want to do is declare a BOOL value in your code, put
BOOL accelerometerWorks;
in your .h file.
Otherwise, if you want a function to check the state of the game as needed, do something like this:
-(BOOL) accelerometerWorks{
//check conditions, return YES or NO...
return time == 0;
}
and this:
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
if(![self accelerometerWorks]) return;
valueX = acceleration.x*25.5;
int newX = (int)(ball.center.x +valueX);
if (newX > 320-BALL_RADIUS)
newX = 320-BALL_RADIUS;
if (newX < 0+BALL_RADIUS)
newX = 0+BALL_RADIUS;
//etc.
}
You can't mess around with the declaration of accelerometer:didAccelerate or you'll just stop receiving the messages, but you CAN check for an invalid state inside of it.

Harry - you also might want to make the 320 a constant, like you did with BALL_RADIUS (you're going to want this to be able to work on an iPad, right? maybe?) and you might also consider factoring out the code you repeat five times into its own method. aehilrs's code should do exactly what you want for the accelerometer.
-(int) limitTravel:(position) {
if (position > MAX_POSITION-BALL_RADIUS)
return MAX_POSITION-BALL_RADIUS;
if (position < BALL_RADIUS)
return BALL_RADIUS;
}
If you decide to change how the limiting code works, you'll only have to change it one place. Your CGPoint magic numbers would be better as constants too for the same reason as the 320.

Related

SpriteKit Block positioning

I am trying to make a jump game in Xcode 5 with SpriteKit.
First I want to spawn Blocks in a random position, but reachable for the 'human' in the game that is jumping.
I got a 1. Block, that spawn at a set position. From this position, there should spawn a 2. Block, that can be + or - 80 higher or lower, and < 80 away. Now here is the problem, I don`t know how to code it in Xcode. My code so far :
SKTexture * BlockTexture1 = [SKTexture textureWithImageNamed:#"Block"];
BlockTexture1.filteringMode = SKTextureFilteringNearest;
SKTexture * BlockTexture2 = [SKTexture textureWithImageNamed:#"Block"];
BlockTexture2.filteringMode = SKTextureFilteringNearest;
SKSpriteNode * Block1 = [SKSpriteNode spriteNodeWithTexture:BlockTexture1];
[Block1 setScale:1];
Block1.position = CGPointMake( 100 , 150 );
Block1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Block1.size];
Block1.physicsBody.dynamic = NO;
Block1.physicsBody.usesPreciseCollisionDetection = YES;
Block1.zPosition = 3;
[self addChild:Block1];
SKSpriteNode * Block2 = [SKSpriteNode spriteNodeWithTexture:BlockTexture2];
[Block2 setScale:1];
Block2.position = CGPointMake( **Block1 + or - 80, Block 1 < 80** );
Block2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Block2.size];
Block2.physicsBody.dynamic = NO;
Block2.physicsBody.usesPreciseCollisionDetection = YES;
Block2.zPosition = 3;
[self addChild:Block2];
To get your started, something like this perhaps:
int block1x = 100;
int block1y = 150;
Block1.position = CGPointMake(block1x, block1y);
int block2x = 0;
int block2y = 0;
int r1 = arc4random() % 2; // produces random numbers between 0 and 1
if(r1 == 0)
block2x = block1x + 80;
if(r1 == 1)
block2x = block1x - 80;
int r2 = arc4random() % 2;
if(r2 == 0)
block2y = block1y + 80;
if(r2 == 1)
block2y = block1y - 80;
Block2.position = CGPointMake(block2x, block2y);

cut a sprite sheet on cocos2d for animation

I want to cut a sprite in 6 equivalent parts just with one image, a .png file which I found on the web, no with texturepacker, (the image below by example)
I can take other way, but I want to know if I can do that. any one haves idea?
I'll revise my answer if this isn't what you were asking about, but I think you are asking how to 'manually run an animation' using a spritesheet without a plist.
Here's one way. It would be better if you encapsulated this into it's own class, but this can push you in the right direction I think:
ManualAnimationTest.h
#interface ManualAnimationTest : CCLayer
{
CCSprite *animatedSprite;
int x,y;
float animatedSpriteWidth, animatedSpriteHeight;
int animatedSpriteColumns, animatedSpriteRows;
}
#end
ManualAnimationTest.m
#import "ManualAnimationTest.h"
#implementation ManualAnimationTest
-(id) init
{
if( (self=[super init]))
{
CGSize s = [CCDirector sharedDirector].winSize;
x = 0;
y = 0;
animatedSpriteColumns = 3;
animatedSpriteRows = 2;
animatedSpriteWidth = 95.0f;
animatedSpriteHeight = 125.0f;
animatedSprite = [CCSprite spriteWithFile:#"animal_animation.png" rect:CGRectMake(x * animatedSpriteWidth,y * animatedSpriteHeight,animatedSpriteWidth,animatedSpriteHeight)];
[self addChild:animatedSprite];
[animatedSprite setPosition:ccp(s.width / 2.0f, s.height / 2.0f)];
[self schedule:#selector(animateAnimatedSprite) interval:0.5f];
}
return self;
}
-(void) animateAnimatedSprite
{
[animatedSprite setTextureRect:CGRectMake(x * animatedSpriteWidth, y * animatedSpriteHeight, animatedSpriteWidth, animatedSpriteHeight)];
x +=1;
if(x > (animatedSpriteColumns - 1))
{
x = 0;
y +=1;
}
if(y > (animatedSpriteRows - 1))
{
y = 0;
}
}
#end

How to use global / static variables OBJ-C

I'm looking to save a variable that is used for one method, and then call it in another method for an App. Does this have something to do with global/extern/static variables? If so, I was wondering how it would be set up. I've tried to use global and static with no success.
I'm trying to hold the information of newX and newY
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
...
int newX = (int)(Button.center.x + valueX);
int newY = (int)(Button.center.y + valueY);
...
}
and then call it in
-(IBAction)clicked:(id)sender
{
randX = arc4random() % 320;
randY = arc4random() % 548;
CGPoint randNewPlace = CGPointMake(randX, randY);
Rand.center = randNewPlace;
if (newX == randX || newY == randY)
{
[Rand sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
thanks.
Just do as below
Declare properties
#property(nonatomic,weak) int newX;
#property(nonatomic,weak) int newY;
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
...
self.newX = (int)(Button.center.x + valueX);
self.newY = (int)(Button.center.y + valueY);
...
}
-(IBAction)clicked:(id)sender
{
randX = arc4random() % 320;
randY = arc4random() % 548;
CGPoint randNewPlace = CGPointMake(randX, randY);
Rand.center = randNewPlace;
if (self.newX == randX || self.newY == randY)
{
[Rand sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
If you want to define an unchanging constant variable define it in your .h and .m
For example, if i want to define the color black as a hexadecimal string in my .h I put above the #interface.
// Default Black
extern NSString * const Black;
Then in my .m above the #implementation
// Default Black
NSString * const Black = #"0xFF000000";
Any time I call the variable Black, out comes 0xFF000000
Of course you could define any type of variable, it doesn't have to be an NSString. extern simply exposes your variables to the rest of your application.
Hope that helps!
#property (nonatomic) int newX,newY;
To access them just instantiate the class then use dot notation. Class.newX

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.

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