how many bullets have been fired? - iphone

I am super frustrated and I know it is just because I don't know what i am doing with cocos2d. I am following Ray Wenderlich tutorials on cocos2d and I am trying to put it all together. When the screen is tapped,one bullet is fired in the direction of the tap. I am using
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self.officer shootToward:touchLocation];
[self.officer shootNow];
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self.officer shootToward:touchLocation];
[self.officer shootNow];
}
which calls these methods in my Officer class
- (void)shootNow {
// 1
CGFloat angle = ccpToAngle(_shootVector);
_gun.rotation = (-1 * CC_RADIANS_TO_DEGREES(angle)) + 90;
// 2
CGSize winSize = [[CCDirector sharedDirector] winSize];
float mapMax = MAX(winSize.width, winSize.height);
CGPoint actualVector = ccpMult(_shootVector, mapMax);
// 3
float POINTS_PER_SECOND = 300;
float duration = mapMax / POINTS_PER_SECOND;
// 5
for(id item in self.children) {
NSString *bulletName = [NSString stringWithFormat:#"bullet.png"];
CCSprite * bullet = [CCSprite spriteWithSpriteFrameName:bulletName];
//bullet.tag = _type;
bullet.position = ccpAdd(self.position, ccpMult(_shootVector, _gun.contentSize.height));
CCMoveBy * move = [CCMoveBy actionWithDuration:duration position:actualVector];
CCCallBlockN * call = [CCCallBlockN actionWithBlock:^(CCNode *node) {
[node removeFromParentAndCleanup:YES];
}];
[bullet runAction:[CCSequence actions:move, call, nil]];
[self.batchNode addChild:bullet];
//[self addChild:bullet];
[_shotsFired addObject:bullet];
}
}
So I figured it would be a simple for loop go through the 5th step x amount of times then call a reload method. Well that didn't work. So I tried to count the touches on the screen, I figured if I got x amount of taps then call the reload method(which is not written yet)? The problem with that was every time you pressed a different area of the screen the count started over from one. Some please help me through this week long process of pulling my hair out? How do I count the amount of times I have fired the gun?

Couldn't you just make a property on your view controller and then every time the shoot now method is called just add 1 to your property, then reset it to 0 when you call the reload method?

Related

intersectsNode not working?

I'm trying to detect when one node overlaps another. I am teaching myself sprite kit and cannot get intersectsNodes to give any output. I've loaded 2 nodes that can be moved around on the screen and then added intersectsNodes in the update section.
-(void)update:(CFTimeInterval)currentTime {
SKSpriteNode* playerShip1;
SKSpriteNode* playerShip2;
if ([playerShip1 intersectsNode: playerShip2]) {
NSLog(#"your ships overlap");
}
Any thoughts on why no intersection is found?
here is the whole m file.
#import "MyScene.h"
#implementation MyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
SKSpriteNode* playerShip1 = [SKSpriteNode spriteNodeWithImageNamed:#"player"];
playerShip1.position = CGPointMake(self.frame.size.width/2, playerShip1.frame.size.height);
playerShip1.name = #"PLAYER_SHIP_1";
[self addChild:playerShip1];
SKSpriteNode* playerShip2 = [SKSpriteNode spriteNodeWithImageNamed:#"player"];
playerShip2.position = CGPointMake(self.frame.size.width/2, self.frame.size.height-playerShip2.frame.size.height);
playerShip2.name = #"PLAYER_SHIP_2";
[self addChild:playerShip2];
SKSpriteNode* playerShip3 = [SKSpriteNode spriteNodeWithImageNamed:#"player"];
playerShip3.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
playerShip3.name = #"PLAYER_SHIP_3";
[self addChild:playerShip3];
activeDragNode = nil;
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// Identify where this touch is on the scene
CGPoint scenePosition = [touch locationInNode:self];
// Find the child node that contains this touch
SKNode* checkNode = [self nodeAtPoint:scenePosition];
// Make sure it is a player ship and not another node like the parent SKScene
if (checkNode && [checkNode.name hasPrefix:#"PLAYER_SHIP"]) {
activeDragNode = (SKSpriteNode*)checkNode;
SKAction *zoomAction = [SKAction scaleTo:1.5 duration:.2];
[checkNode runAction:zoomAction];
//NSLog(#"your ship has been hit!");
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Remove reference to which object we are dragging
activeDragNode=nil;
UITouch *touch = [touches anyObject];
CGPoint scenePosition = [touch locationInNode:self];
SKNode* checkNode = [self nodeAtPoint:scenePosition];
SKAction *shrinkAction = [SKAction scaleTo:1.0 duration:.2];
[checkNode runAction:shrinkAction];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// Be sure we have a reference to an object to drag
if (activeDragNode==nil) return;
UITouch *touch = [touches anyObject];
CGPoint scenePosition = [touch locationInNode:self];
CGPoint lastPosition = [touch previousLocationInNode:self];
// Calculate the new location of the dragged node
CGPoint newLoc = CGPointMake(activeDragNode.position.x + (scenePosition.x - lastPosition.x), activeDragNode.position.y + (scenePosition.y - lastPosition.y));
// Update this location
activeDragNode.position = newLoc;
}
-(void)update:(CFTimeInterval)currentTime {
SKSpriteNode* playerShip1;
SKSpriteNode* playerShip2;
if ([playerShip1 intersectsNode: playerShip2]) {
NSLog(#"your ships overlap");
}
/* Called before each frame is rendered */
}
#end
First you need to set a position for each node:
playerShip1.position = CGPointMake(0,0);
Second you need to add each node to the view:
[self addChild:playerShip1];
Also, you are adding the nodes in your update method which is the wrong place. As your code is now, you will continuously add each node 60 times a second.
I see you adding additional code. You are creating 3 SKSpriteNodes in your init method which is fine and works. However, you are not keeping a reference to these 3 nodes. This means once they are created, you have no way to access them again. To resolve this, you should create 3 SKSpriteNode class properties or add all 3 nodes into an array (class property for the array). If you don't know what I mean, that's ok, it just means you have a ways to learn.
I suggest you do a couple of tutorials as this will teach some additional fundamentals and prevent a ton of "why isn't this working" frustration in the future.

Dpad for sprite kit

I an interested in trying to create a few games, namely in the new sprite kit. However, for the game that I have in mind I would rather use a directional pad vs a joy stick. Since I shall be moving over from Cocos, my old program no longer works (so neither will that dpad). Sadly, I have not come accross any tutorial that may help with implementing one in the new sprite kit (only joy sticks). I was wondering and hoping if anyone came across a simple dpad class from github or something or a helpful link that they would like to share. Thanks
Here's one way:
//Joystick node
- (SKSpriteNode *)controlPadNode
{
SKSpriteNode *controlPadNode = [SKSpriteNode spriteNodeWithImageNamed:#"game-controller-front"];
controlPadNode.position = CGPointMake(controlPadX,controlPadY);
controlPadNode.name = #"controlPadNode";
controlPadNode.zPosition = 1.0;
return controlPadNode;
}
//handle touch events
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
touchX = location.x;
touchY = location.y;
controlButtonDown = true;
}
}
//when touch moves
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
touchX = location.x;
touchY = location.y;
controlButtonDown = true;
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//if control pad touched
if ([node.name isEqualToString:#"controlPadNode"]) {
controlButtonDown = false;
}
}
//update method
-(void)update:(NSTimeInterval)currentTime {
if (controlButtonDown) {
//the control pad
SKNode *controlNode = [self childNodeWithName:#"controlPadNode"];
//the node you want to move
SKNode *node = [self childNodeWithName:#"spaceShipNode"];
//compute the angle between parameters pad and the horizontal
float angle = atan2f (touchY - controlPadY, touchX - controlPadX) ;
//move the control pad for the player to have a sense of movement
SKAction *moveControlPad = [SKAction moveTo:CGPointMake(touchX, touchY) duration:0.00001];
double distance = sqrt(pow((touchX - controlPadX), 2.0) + pow((touchY - controlPadY), 2.0));
//make sure the control pad only moves 40 pixels
if( distance < 40 ){
[controlNode runAction:moveControlPad];
}
//move the ship
SKAction *moveShip = [SKAction moveByX: 6*cosf(angle) y:6*sinf(angle) duration:0.005];
[node runAction: moveShip];
}
}
EDIT:
Also can use this to move the control pad back when touch ends:
if (!controlButtonDown) {
SKNode *controlNode = [self childNodeWithName:#"controlPadNode"];
SKAction *moveControlPad = [SKAction moveTo:CGPointMake(controlPadX, controlPadY) duration:0.00001];
[controlNode runAction:moveControlPad];
}
I've built a small UIKit based game engine before the introduction of SpriteKit. My engine loads cocos2d compatible maps from Tiled, sprites from TexturePacker, and it comes with a joystick that I ported from cocos2d to UIKit. (Mine is based on sneaky-joystick.)
You can grab the whole library on GitHub and pull out the parts you need. It's fairly modular.

UIImageView how to track clockwise or counterclockwise user motion

I have successfully implemented rotating a uiimageview using this code from this post
iPhone - Wheel tracking finger jumps to same starting position?
My question to fellow developers is that the user on touch can rotate the image both clockwise and counterclockwise. Is there a way I can detect in which direction is the user moving the view?
Its important to me because I am making a clock app. I let users move the min hand form 0 min all the way to 60 min. When it reaches there I move the hour hand one up. But the user can spin the min hand counter clockwise in which case I need to move the hour hand one down. Any ideas?
you can set a member variable named "lastPoint" to record the point last time you moved
the you can calc the direction next time
CGPoint lastPoint;
- (void) touchedBegin:(NSSet *)touches withEvent:(UIEvent *)event {
lastPoint = [touch locationInView:self.view];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
//you can save the point , then used in next time you want
int tInput = [allTouches count]-1;
UITouch *touch =[[allTouches allObjects] objectAtIndex:tInput];
CGPoint location = [touch locationInView:self.view];
float theAngle = atan2( location.y-imageX.center.y, location.x-imageX.center.x );
float theLastAngle = atan2( lastPoint.y-imageX.center.y, lastPoint.x-imageX.center.x );
lastPoint = location;
// compare theAngle & theLastAngle , so you can know it is clockwise or counterclockwise.
}

drag UIView like apps in the home screen iPhone

I have a view control and inside I plan to place some controls like buttons textbox etc... I can drag my view along the x axis like:
1)
2)
with the following code:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if( [touch view] == ViewMain)
{
CGPoint location = [touch locationInView:self.view];
displaceX = location.x - ViewMain.center.x;
displaceY = ViewMain.center.y;
startPosX = location.x - displaceX;
}
CurrentTime = [[NSDate date] timeIntervalSince1970];
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
if( [touch view] == ViewMain)
{
CGPoint location = [touch locationInView:self.view];
location.x =location.x - displaceX;
location.y = displaceY;
ViewMain.center = location;
}
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
double time = [[NSDate date] timeIntervalSince1970]-CurrentTime;
UITouch *touch = [[event allTouches] anyObject];
if( [touch view] == ViewMain)
{
CGPoint location = [touch locationInView:self.view];
location.x =location.x - displaceX;
location.y = displaceY;
ViewMain.center = location;
double speed = (ViewMain.center.x-startPosX)/(time*2);
NSLog(#"speed: %f", speed);
}
}
not that I have to add the global variables:
float displaceX = 0;
float displaceY = 0;
float startPosX = 0;
float startPosY = 0;
double CurrentTime;
the reason why I created those variables is so that when I start dragging the view the view moves from the point where I touch it instead of from the middle.
Anyways if I touch a button or image the view will not drag even though the images have transparency on the background. I want to be able to still be able to drag the view regardless if there is an image on top of the view. I where thinking that maybe I need to place a large transparent view on top of everything but I need to have buttons, images etc. I want to be able to drag a view just like you can with:
note that I was able to drag the view regardless of wither I first touched an app/image or text. How could I do that?
I think your problem is that if you touch a UIButton or a UIImageView with interaction enabled, it doesn't pass the touch along.
For the images, uncheck the User Interaction Enabledproperty in IB.
For the buttons that are causing touchesBegan:withEvent:, etc. to not get called, then look at the following link: Is there a way to pass touches through on the iPhone?.
You may want to consider a different approach to this problem. Rather than trying to manually manage the content scrolling yourself you would probably be better off using a UIScrollView with the pagingEnabled property set to YES. This is the method Apple recommends (and it's probably the method used by Springboard.app in your last screenshot). If you are a member of the iOS developer program check out the WWDC 2010 session on UIScrollView for an example of this. I think they may have also posted sample code on developer.apple.com.

How can i rotate body when user touch the screen in cocos2d

I am facing one problem. I have done some coding to rotate cpSegmentShapeNew but its not working . Have a look on the following code,
//**creating shape
testBody = cpBodyNew(INFINITY, INFINITY);
cpShape* testShape = cpSegmentShapeNew(testBody, cpv(230, 82), cpv(193, 46), 0.0f);
testShape->e = 0.0;
testShape->u = 0.0;
testShape->data = flipper;
testShape->collision_type = 2;
cpSpaceAddStaticShape(space, testShape);
//Body moving when user touch
-(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//event that starts when a finger touchs the screen
UITouch *touch = [touches anyObject];
CGPoint tmpLoc = [touch locationInView: [touch view]];
CGPoint location = [[Director sharedDirector] convertCoordinate:tmpLoc];
ball.position = location;
ballBody->p = location;
[flipper runAction:[RotateTo actionWithDuration:0.1f angle:60]];
cpBodySetAngle(testBody, 60);
cpvrotate(testBody->rot, cpv(100000,0));
return kEventHandled;
}
Please anyone tell me that where i am wrong.
Thanks.
Greetings,
The problem is that you are rotating both objects (sprite + body) through code.
What you need is rotate one, and let the other object know it's happened so it can do it too.
For example, if you move the body, then the method that updates the sprites should look like that:
void updateShapes(void* ptr, void* unused)
{
cpShape* shape = (cpShape*)ptr;
Sprite* sprite = shape->data;
if(sprite)
{
cpBody* body = shape->body;
[sprite setPosition:cpv(body->p.x, body->p.y)];
[sprite setRotation: (float) CC_RADIANS_TO_DEGREES( -body->a )];
}
}
The last line of code updates the rotation. That's the line you are missing.
I hope that helps you or someone else in the future.
Good luck cocos2d mate !
Yohann T.