Projectiles/Bullets direction Cocos2d - iphone

i am following a tutorial on a simple cocos2d game.
however on that tutorial the bullets that the user fires is only on one direction
what can i do to make it fire on all directions not just one sided?
here is the code of the direction.
int offX = location.x - projectile.position.x;
int offY = location.y - projectile.position.y;
[self addChild:projectile];
int realX = winSize.width + (projectile.contentSize.width/2);
float ratio = (float) offY / (float) offX;
int realY = (realX *ratio) + projectile.position.y;
CGPoint realDest = ccp(realX, realY);
int offRealX = realX - projectile.position.x;
int offRealY = realY - projectile.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1;
float realMoveDuration = length/velocity;
[projectile runAction:[Sequence actions:[MoveTo actionWithDuration:realMoveDuration position:realDest],
[CallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)], nil]];
all help will be greatly appreciated. Thanks

Assuming you are creating the projectile at the location of your character, you just need to figure out the direction before calculating the end point.
After adding the projectile:
[self addChild:projectile];
Add a scalar float:
float scalarX = 1.0f;
And make it negative if the touch is left of the character:
if (offX < 0.0f) scalar = -1.0f;
Then just multiply the realX by this scalar to make it point the correct way
int realX = scalar * (winSize.width + (projectile.contentSize.width/2));

Related

Objective-C random position on screen not working properly ( SpriteKit )

Well I made a randomNumber Class, (for practice and) for calculating a random position on my screen for an object and it works properly, except for it sometimes puts the sprite out of the screen.The x and y coordinates are smaller the screen height and width. but it doesn't show it on the screen.
The whole program is just basically randomly placing instances of an object inside the screen.
randomNumber.h
#import <Foundation/Foundation.h>
#import <SpriteKit/SpriteKit.h>
#interface randomNumber : NSObject
-(int)randNumX:(int) max :(SKSpriteNode *) sprite;
-(int)randNumY:(int) max :(SKSpriteNode *) sprite;
#end
randomNumber.m
#import "randomNumber.h"
#implementation randomNumber
-(int)randNumX:(int) max :(SKSpriteNode *) sprite {
int _spriteW = sprite.frame.size.width;
int _random = (arc4random() % (max - _spriteW));
NSLog(#"The x value is %d", _random);
return _random;
}
-(int)randNumY:(int) max :(SKSpriteNode *) sprite {
int _spriteH = sprite.frame.size.height;
int _random = (arc4random() % (max - _spriteH));
NSLog(#"The y value is %d", _random);
return _random;
}
#end
MyScene.m ( only the initilazeMole method )
-(void) initilazeMole {
int x = [self.rndNum randNumX:(self.scene.size.width):(self.mole)];
int y = [self.rndNum randNumY:(self.scene.size.height):(self.mole)]
self.mole = [SKSpriteNode spriteNodeWithImageNamed:#"spaceship"];
self.mole.anchorPoint = CGPointMake(0,0);
self.mole.position = CGPointMake(x,y);
SKAction *pulseRed = [SKAction sequence:#[
[SKAction colorizeWithColor:[SKColor redColor] colorBlendFactor:1.0 duration:0.5],
[SKAction waitForDuration:0.1],
[SKAction colorizeWithColorBlendFactor:0.0 duration:1.0]]];
[self.mole runAction: pulseRed];
NSLog(#"mole x position: %f", self.mole.position.x);
NSLog(#"mole y position: %f", self.mole.position.y);
[self addChild:self.mole];
}
I don't really understand why does it place it off the screen, hence I generate a random number that can maximally be ( the screen width - sprite width ) and ( the screen height - sprite height )
My project settings are set up for an iphone 3.5 inch in landscape mode.
Any idea where did my code go wrong ?
Try this:
- (CGPoint) randomPointWithinContainerSize:(CGSize)containerSize forViewSize:(CGSize)size {
NSLog(#"move");
CGFloat xRange = containerSize.width - size.width;
CGFloat yRange = containerSize.height - size.height;
CGFloat minX = (containerSize.width - xRange) / 2;
CGFloat minY = (containerSize.height - yRange) / 2;
int randomX = (arc4random() % (int)floorf(xRange)) + minX;
int randomY = (arc4random() % (int)floorf(yRange)) + minY;
return CGPointMake(randomX, randomY);
}
Then replace:
int x = [self.rndNum randNumX:(self.scene.size.width):(self.mole)];
int y = [self.rndNum randNumY:(self.scene.size.height):(self.mole)]
self.mole = [SKSpriteNode spriteNodeWithImageNamed:#"spaceship"];
self.mole.anchorPoint = CGPointMake(0,0);
self.mole.position = CGPointMake(x,y);
With:
self.mole.position = [self randomPointWithinContainerSize:self.scene.size forViewSize:self.mole.bounds.size];

Having a path that follows another one

I have an array of coordinates (geographic coordinates, but that shouldn't matter) and I need to have a path that "follows" the path that we already have.
We need something like on the following image. You can see that the path is not exactly the same (not a simple offset) and we don't want it to scale either.
Is there some library that we could use to do that or some pointers on how to implement this?
After spending way too much time trying to find a working solution I ended up coding my own:
CGContextBeginPath(context);
CGMutablePathRef path = CGPathCreateMutable();
MKMapPoint *mapPoints = itineraryPath.points;
CGPoint previousEdgeNormal = CGPointZero;
CGPoint previousDrawnPoint = CGPointZero;
float offsetDistance = self.pathWidth*2.5;
for(int i = 0; i < itineraryPath.pointCount; i++) {
if(i < itineraryPath.pointCount-1) {
MKMapPoint mapPoint = mapPoints[i];
CGPoint point = [self pointForMapPoint:mapPoint];
MKMapPoint secondMapPoint = mapPoints[i+1];
CGPoint secondPoint = [self pointForMapPoint:secondMapPoint];
float xDelta = point.x-secondPoint.x;
float yDelta = point.y-secondPoint.y;
float factor = xDelta > 0 ? -1 : 1;
float segmentLength = sqrt(pow(xDelta, 2.0)+pow(yDelta, 2.0));
float yDeltaAngle = asin(sin(M_PI/2*factor)*yDelta/segmentLength);
float opposedAngle = M_PI/2-yDeltaAngle;
float remainingAngle = M_PI/2-opposedAngle;
float yOffset = sin(opposedAngle)*offsetDistance/sin(M_PI/2)*factor;
float xOffset = sin(remainingAngle)*offsetDistance/sin(M_PI/2)*factor;
CGPoint offsetFirstPoint = CGPointMake(point.x+xOffset, point.y+yOffset);
CGPoint offsetSecondPoint = CGPointMake(secondPoint.x+xOffset, secondPoint.y+yOffset);
if(i == mapPointIndex) {
CGPathMoveToPoint(path, NULL, offsetFirstPoint.x, offsetFirstPoint.y);
previousDrawnPoint = offsetFirstPoint;
}
else {
float xNormalDifference = previousEdgeNormal.x-offsetFirstPoint.x;
float yNormalDifference = previousEdgeNormal.y-offsetFirstPoint.y;
float xAverage = (xNormalDifference)/2;
float yAverage = (yNormalDifference)/2;
CGPoint normalAveragePoint = CGPointMake(offsetFirstPoint.x+xAverage, offsetFirstPoint.y+yAverage);
CGPathAddLineToPoint(path, NULL, normalAveragePoint.x, normalAveragePoint.y);
previousDrawnPoint = normalAveragePoint;
}
previousEdgeNormal = offsetSecondPoint;
}
else
CGPathAddLineToPoint(path, NULL, previousEdgeNormal.x, previousEdgeNormal.y);
}
Only caveat is that it doesn't handle acute angles very well yet.
But otherwise gives something pretty neat (right is original path, left is offset)
What you want is called a parallel curve: http://en.wikipedia.org/wiki/Parallel_curve
One way to generate that is to compute the normal of your original curve at each point, and then offset those points using that normal. This is quite simple if you only have straight line segments. For arcs and bezier curves, you also need to figure out how to modify the control points.

How do I use tile coordinates instead of the regular coordinates in cocos2d

I am still new to cocos2d and I have this problem that when I am using the ccp coordinates it stays at same position even when I move to the next screen. I came to the conclusion it must be that I am not using the tiles coordinates. So I need some help converting.
- (CGPoint)tileCoordForPosition:(CGPoint)position {
float x = floor(position.x / map.tileSize.width);
float levelHeightInPixels = map.mapSize.height * map.tileSize.height;
float y = floor((levelHeightInPixels - position.y) / map.tileSize.height);
return ccp(x, y);
}
-(CGRect)tileRectFromTileCoords:(CGPoint)tileCoords {
float levelHeightInPixels = map.mapSize.height * map.tileSize.height;
CGPoint origin = ccp(tileCoords.x * map.tileSize.width, levelHeightInPixels - ((tileCoords.y + 1) * map.tileSize.height));
return CGRectMake(origin.x, origin.y, map.tileSize.width, map.tileSize.height);
}
that is what i use to translate regular coordinates into tile map coordinates.
now I am trying to spawn an enemy at a certain position specifically (0,0)
-(void)addsaw{
CCSprite *saw = [CCSprite spriteWithFile:#"saw.png"];
// Determine where to spawn the target along the Y axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minY =saw.contentSize.height/2;
int maxY = winSize.height - saw.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = ( rangeY) + minY;
//THIS IS THE PROBLEM RIGHT HERE
saw.position = ccp(0,0);
[self addChild:saw];
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(-saw.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(spriteMoveFinished2:)];
[saw runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
saw.tag = 1;
[_saws addObject:saw];
}
How do I change the ccp of my addsaw so I can have it spawn at the tile (0,0) rather than the cocos2d regular (0,0)
you should add your sprite to your cctmxtiledmap instead of the layer!

Rotate sprite image according to user touch location?

I m start learning game development. As a beginner i create one demo game in which one cannon hit bullets to the enemies (coming toward cannon from different direction).
Now i stuck on cannon sprite image rotation anywhere user touch on the screen or enemies. How i do that, My initial code as following,
void HelloWorld:: ccTouchesBegan(CCSet *touches, CCEvent * event)
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCTouch* touch = (CCTouch*)( touches->anyObject() );
CCPoint location = touch->locationInView(touch->view());
location = CCDirector::sharedDirector()->convertToGL(location);
//Rotate cannon direction toward touch point
CCPoint diffPoint = ccpSub(_cannonImage->getPosition(), location);
float angleRadians = atanf((float)diffPoint.y/(float)diffPoint.x);
float angleOffset = CC_DEGREES_TO_RADIANS(180);
if(diffPoint.x < 0){
angleRadians += angleOffset;
}else{
angleRadians -= angleOffset;
}
CCLog("angle to be rotate = %f", angleRadians);
_cannonImage->runAction(CCRotateBy::actionWithDuration(0.1, angleRadians));
}
The code is written in cocos2d-x . I also accepting answer by someone who written in plain cocos2d.
Thanks
iHungry
The perfect answer as follows,
float HelloWorld::changingAngleAccordingToCoordinateSystem(CCPoint imageCenter, CCPoint touchLocation, float calculatedAngle){
//Consideration :- all Angles is in Degree
if((calculatedAngle >= 0 && calculatedAngle <= 90) || (calculatedAngle >= 90 && calculatedAngle <= 180)){
//Ist quardant
calculatedAngle = calculatedAngle;
}
else if(calculatedAngle < 0 && calculatedAngle >= -90){
//IInd quardant
calculatedAngle = 270 + (90 + calculatedAngle);
}
else if(calculatedAngle < -90 && calculatedAngle >= -180){
calculatedAngle = 180 + (180 + calculatedAngle);
}
return calculatedAngle;
}
//Rotate cannon direction toward touch point
float diff_X = touchLocation.x - myImage->getPosition().x;
float diff_Y = touchLocation.y - myImage->getPosition().y;
CCPoint diffPoint = CCPoint(diff_X, diff_Y);
float angleRadians = atan2f(diffPoint.y,diffPoint.x);
angleRadians = CC_RADIANS_TO_DEGREES(angleRadians);
angleRadians = HelloWorld::changingAngleAccordingToCoordinateSystem(myImage->getPosition(), touchLocation, angleRadians);
myImage->setRotation(-angleRadians);
i used this code to rotate my sprite. i Was moving the sprite according to my accelerometer reading.
float angleRadians =-accelX;
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
objGlider->sprite_Glider.rotation = cocosAngle;
Check it. The reason of slow may be that you may be using CClog or NSLog in the code.
Here goes the complete code.
if(!boolPlayerDied)
{
static float prevX=0, prevY=0;
#define kFilterFactor 1.0f// don't use filter. the code is here just as an example
float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
prevX = accelX;
prevY = accelY;
accelX = accelX-0.5;// Angle check fot tgfor the player to play
float angleRadians =-accelX;
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
if(accelX>0)
{
cocosAngle = 1.1 * angleDegrees;
}
else
{
if(accelX<-0.5)
accelX=-0.5;
cocosAngle = 1.1 * angleDegrees;
}
objGlider->sprite_Glider.rotation = cocosAngle;
}
objGlider is the object of the class which creates glider sprite and sprite_Glider is the sprite used in glider class.
you can use rotation property with your sprite to be rotated. In cocos2Dx it might be setRotation.
First of all, replace
float angleRadians = atanf((float)diffPoint.y/(float)diffPoint.x);
float angleOffset = CC_DEGREES_TO_RADIANS(180);
if(diffPoint.x < 0){
angleRadians += angleOffset;
}else{
angleRadians -= angleOffset;
}
by
float angleRadians = atan2f(diffPoint.y, diffPoint.x);
Then it would be better to set rotation immediately (without actions) to process multiple frequent touches.
_cannonImage->setRotation(angleRadians);
Maybe you will need to adjust rotation like setRotation(-angleRadians) or setRotation(angleRadians+90) - it depends on your coordinate system.

iphone toRadians toDegrees compiler problem

I am trying to convert a double to radians using the Objective c function toRadians like this:
double oldLat = toRadians(oldLocation.coordinate.latitude);
but I keep getting a compiler warning and error or implicit declaration of toRadians and toDegrees
I included #import <math.h> but that didn't solve the problem for some reason.
any help would be greatly appreciated.
There is no toRadians in the Foundation classes. You can just convert it manually
degrees * M_PI / 180.0
Foundation imports math.h so you'll have M_PI otherwise you'll have to
#include <math.h>
try this coding:- ( radian to degree)
location = [[CCDirector sharedDirector] convertToGL:location];
// Determine offset of location to projectile
int offX = location.x - PROJECTILE_POSITION_X;
int offY = location.y - PROJECTILE_POSITION_Y;
int realX = winSize.width + (PROJECTILE_WIDTH/2);
float ratio = (float) offY / (float) offX;
int realY = (realX * ratio) + PROJECTILE_POSITION_Y;
int offRealX = realX - PROJECTILE_POSITION_X;
int offRealY = realY - PROJECTILE_POSITION_Y;
// Determine angle to face
float angleRadians = atanf((float)offRealY / (float)offRealX);
float angleDegrees = (__angleRadians__)/((__angleRadians__) * 57.29577951f);