Hi Im making a cocos2d game that has a sprite flying and falling, Im trying to have a first tap touch event for example when the user touches the screen for the first time it'll start the game animation and start the physics engine. Whats happening is that when the user starts the game the sprite falls down right away, can anyone give me a hand with this?
right now Im using something like this but Im not sure how to get the physics engine to wait until the user touches the screen for the first time.
CCSprite *_pixie
CCNode *_start;
BOOL *_firstTap;
CCPhysicsNode *_physicsNode;
-(void)didLoadFromCCB{
_physicsNode.collisionDelegate = self;
_firstTap = True;
}
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
if(_firstTap == TRUE){
_start.visible = FALSE;
_firstTap = False;
}
//flying sounds & so on
if (!_gameOver) {
[[OALSimpleAudio sharedInstance] playEffect:MAGIC volume:0.4 pitch:1 pan:0 loop:NO];
[_pixie.physicsBody applyImpulse:ccp(0, 420.f)];
[_pixie.physicsBody applyAngularImpulse:11000.f];
_sinceTouch = 0.f;
}
}
- (void)update:(CCTime)delta {
if(_firstTap == FALSE){
float yVelocity = clampf(_pixie.physicsBody.velocity.y, -1 * MAXFLOAT, 200.f);
if ((_sinceTouch > .5f)) {
[_pixie.physicsBody applyAngularImpulse:-40000.f*delta];
}
}
}
Change
BOOL *_firstTap;
to
BOOL _firstTap; //No asterisk
And also make sure that you set _firsttap = YES in viewDidLoad functions
- (void)viewDidLoad
{
[super viewDidLoad];
_firstTap = YES;
}
Looks to me like the first touch Boolean value may not be defined until after the update code is called. You are also mixing BOOL values with bool values.
Objective-C : BOOL vs bool
Related
This might be a stupid question, but in my app there will be a need to pass a bool variable to a method.
Let's say I have 10 BOOL variables declared as b1,b2.....b10.
I can send BOOL value as a parameter by simply with the following code:
[self sendBoolValue:YES];
- (void)sendBoolValue:(BOOL)value
{
b1 = value;
// now b1 will be YES.
}
Now what I need is something which does this:
[self sendBoolVariable:b1]; // I tried sending &b1, but it didnt work out.
- (void)sendBoolVariable:(BOOL)value
{
value = YES; // trying to set b1 to YES.
// b1 is still NO.
}
I couldnt get to send the BOOL variable. IS this even possible ?
Why I am doing this?:
I have a UIView which has 9 subviews(I call these as tiles) in a 3x3 grid layout.
I have two BOOL values startTile and endTile. I need to set these values based on the touch!!!
I am using touches-Began/Moved/Ended to detect touches on these views
When the touches started, I need to calculate if the touch is in the tile1 or tile2.....
So the actual code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// calculate touch point and based on it set the bool value
[self sendBoolVariable:startTile];
//startTile is selected, so change its color
// lock other tiles
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
//if touches came to tile 2 region
[self sendBoolVariable:b2]; //b2 is BOOL variable for tile2
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self sendBoolVariable:endTile];
//end tile is selcted too
//at this point both start tile and tile are selected
//now do the animation for the start tile and end tile
//other tiles are still in locked state
}
As you can see, I need to call same method but need to send three different bool variables!!!!
Not 100% sure if this is what you want but you can do:
[self sendBoolVariable:&b1];
- (void)sendBoolVariable:(BOOL *)value {
*value = YES; //b1 is now YES
}
Following your clarifications, how about:
BOOL a = YES;
a = [self modifyBoolValueBasedOnItself:a]; // the method takes the BOOL as a parameter and returns the modified value
An BOOL is just a a signed char.
If you're trying to change the value of a property, try self.variable = YES or _variable = YES
Also kudos to barry wark for the following:
From the definition in objc.h:
typedef signed char BOOL;
// BOOL is explicitly signed so #encode(BOOL) == "c" rather than "C"
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED
#define YES (BOOL)1
#define NO (BOOL)0
When you pass the BOOL b1 to the method:
[self sendBoolVariable:b1];
"value" has a scope limited to the method. So when you set value=YES:
-(void)sendBoolVariable:(BOOL) value{
value=YES;
you are not changing the value of the broader scope ivar "b1".
I am building a Sprite Kit game where the player shoots a particle whenever the screen is pressed. How can I limit the touch inputs (let's say 2 recognized touch inputs per second) so that the player can't just quickly tap the screen to get unlimited shots?
Another solution:
Create a BOOL (I prefer to work with properties myself, so):
#property (nonatomic, assign) BOOL touchEnabled;
Set it to YES in the scene's init. Then it is fairly simple from thereon:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (self.touchEnabled){
self.touchEnabled = NO;
[self shootParticle];
[self performSelector:#selector(enableTouch) withObject:nil afterDelay:2.0];
}
...
- (void)shootParticle{
// whatever...
}
- (void)enableTouch{
self.touchEnabled = YES;
}
One of many possibilities:
#interface YourSceneName (){
int _amountBullets; //increase every time you shot and just shoot when _fireStop = NO
BOOL _fireStop; // init as NO at start
BOOL _needStartTime; // init as YES at start
CFTimeInterval _startTime;
}
#end
-(void)update:(CFTimeInterval)currentTime {
//set starttime
if(_needStartTime){
_startTime = currentTime;
_needStartTime = NO;
}
//timeinterval if 2 seconds, renew everything
if(currentTime - _startTime > 2){
_startTime = currentTime;
_amountBullets = 0
_fireStop = NO;
}
//set firestop to yes, method should be executed
if(_amountBullets = 2){
_fireStop = YES;
}
}
I am new in SpriteKit but this should work. I bet there are better possibilities. Also i havenĀ“t test the code. It shell show you the logic of how you could do it, hope I could help.
Here is a great Tutorial for working with time in SpriteKit.
I am developing a game on Xcode, but I ran into a problem. I'm not able to make my objectGuy
from going beyond a roof and I am unable to make my objectGuy from falling beyond the floor.
This is what I tried coding: I need help making the collision stop the jump and make the objectGuy fall back down and once it collides with the ground, to keep him there.
topGround is referring to the roof / bottomGround is referring to the ground
-(void) collision {
if (CGRectIntersectsRect(guy.frame, topGround.frame)) {
guyJump = 0;
}
if (CGRectIntersectsRect(guy.frame, bottomGround.frame)) {
guy.center = CGPointMake(guy.center.x, 261);
}
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
guyJump = 20;
[self collision];
}
-(void) guyMoving {
guy.center = CGPointMake(guy.center.x, guy.center.y - guyJump);
guyJump = guyJump - 5;
if (guyJump < -3) {
guyJump = -3;
}
}
I have a CCNode that contains multiple CCSprite children.
I would like to receive touch events in my parent CCNode if any of the children have been touched.
This behaviour seems like it should be supported, I may be missing something.
My solution is to setUserInteractionEnabled = YES on all children and bubble the event up to the parent.
I do this by subclassing the CCSprite class overriding their method :
- (void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
[super touchBegan:touch withEvent:event];
}
I am wondering if there is a more elegant, simple and generic way of accomplishing the same behaviour ?
You could override hitTestWithWorldPos: of your 'containing' node, either calling hitTestWithWorldPos on specific children or, iterating through all children as you see fit. Perhaps something like this:
-(BOOL) hitTestWithWorldPos:(CGPoint)pos
{
BOOL hit = NO;
hit = [super hitTestWithWorldPos:pos];
for(CCNode *child in self.children)
{
hit |= [child hitTestWithWorldPos:pos];
}
return hit;
}
edit: just to be clear, then you would only need to setUserInteractionEnabled for the container, and only process the touch using the touch events of the containing node.
edit2:
so, I thought about it for a bit more and here's a quick category you can add that will enable a quick hit test for all children of a node recursively.
CCNode+CCNode_RecursiveTouch.h
#import "CCNode.h"
#interface CCNode (CCNode_RecursiveTouch)
{
}
-(BOOL) hitTestWithWorldPos:(CGPoint)worldPos forNodeTree:(id)parentNode shouldIncludeParentNode:(BOOL)includeParent;
#end
CCNode+CCNode_RecursiveTouch.m
#import "CCNode+CCNode_RecursiveTouch.h"
#implementation CCNode (CCNode_RecursiveTouch)
-(BOOL) hitTestWithWorldPos:(CGPoint)worldPos forNodeTree:(id)parentNode shouldIncludeParentNode:(BOOL)includeParent
{
BOOL hit = NO;
if(includeParent) {hit |= [parentNode hitTestWithWorldPos:worldPos];}
for( CCNode *cnode in [parentNode children] )
{
hit |= [cnode hitTestWithWorldPos:worldPos];
(cnode.children.count)?(hit |= [self hitTestWithWorldPos:worldPos forNodeTree:cnode shouldIncludeParentNode:NO]):NO; // on recurse, don't process parent again
}
return hit;
}
#end
usage would just be .. in the containing class, override hitTestWithWorldPos like this:
-(BOOL) hitTestWithWorldPos:(CGPoint)pos
{
BOOL hit = NO;
hit = [self hitTestWithWorldPos:pos forNodeTree:self shouldIncludeParentNode:NO];
return hit;
}
and of course, don't forget to include the category header.
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
//Do whatever you like...
//Bubble the event up to the next responder...
[[[CCDirector sharedDirector] responderManager] discardCurrentEvent];
}
I am trying to get my head around the touch handling in Kobold2Ds's KKInput class. At the moment I just have some dummy methods that are checking for the three main phases of touch input, began, moving, and ended.
However the code for touches moving never seems to get called.
Here is my code. It is inside a CCNode subclass, that has a CCSprite that it is responsible for rendering and managing.
-(void) update:(ccTime)delta
{
// NSLog(#"Update");
KKInput* input = [KKInput sharedInput];
if ([input isAnyTouchOnNode:tileSprite touchPhase:KKTouchPhaseMoved])
{
NSLog(#"Tile touched moved");
}
if ([input isAnyTouchOnNode:tileSprite touchPhase:KKTouchPhaseBegan])
{
NSLog(#"Tile touched began");
self.frameNumber = #2;
}
if ([input isAnyTouchOnNode:tileSprite touchPhase:KKTouchPhaseEnded])
{
NSLog(#"Tile touched ended");
self.frameNumber = #1;
}
}
The code for KKTouchPhaseBegan and KKTouchPhaseEnded both get called, but the code for KKTouchPhaseMoved never does.
Can anyone clue me in to what i'm doing wrong?