Cocos2d problem/question - iphone

I am making a game in Cocos2d. I want enemies to spawn on the right and left sides of the screen, and move to a random point on the screen, then repeat. Despite my efforts, I cannot figure it out. This should be relatively easy to answer, it should look like something out of one of Ray Wenderlich's tutorials. Some code would be nice. Thanks!

This is the code from ray Wanderlich tutorial..
[self schedule:#selector(addTarget) interval:2.0];
-(void)addTarget {
CCSprite *target = [CCSprite spriteWithFile:#"Target.jpg"
rect:CGRectMake(0, 0, 27, 40)]; //Creating Sprite and setting rect
// Determine where to spawn the target along the Y axis
CGSize winSize = [[CCDirector sharedDirector] winSize]; //Get the screensize
int minY = target.contentSize.height/2;
int maxY = winSize.height - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
target.position = ccp(winSize.width + (target.contentSize.width/2), actualY);
[self addChild:target];
// Determine speed of the target
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(-target.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:#selector(spriteMoveFinished:)];
[target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
}
minY-->position at the bottom of the screen
maxY--->position at the top of the screen.
rangeY ---> the height of the screen.
actualY--->calculate the random point between bottom of the screen and top of the screen.
target.position --> setting random position for the sprite to move.
actualDuration --> getting random duration.so that the sprite moves in various time delay.
actionMove --> creating Move action.
actionMoveDone ---> After completing move action,calling spriteMoveFinished to remove sprites.

Related

Can't position SKShapeNode (rectangle) in grid precisely

Being new to the obj-c language and Sprite kit I'm having difficulties positioning a rectangle in a grid...
There's an offset in the rectangles I create - if I manage to get the code to position a rectangle in a chosen field another rectangle will be offset...
I have tried several different approches and I can get it to work using JavaFX. What am I doing wrong?
The photo below shows my problem clearly.
My code is rather simple and can be seen here:
#import "MyScene.h"
#implementation MyScene
const int ROWS = 10;
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.backgroundColor = [SKColor darkGrayColor];
[self createBoardWithRows:ROWS];
[self createBoxPositionX:1 positionY:1];
[self createBoxPositionX:3 positionY:3];
[self createBoxPositionX:5 positionY:5];
}
return self;
}
-(void) createBoardWithRows: (int) rows{
for (int i = 1; i < rows; i++){
//Horisontal lines
int yPos = self.size.height/rows * i;
SKShapeNode *lineH = [SKShapeNode node];
CGMutablePathRef pathToDraw = CGPathCreateMutable();
CGPathMoveToPoint(pathToDraw, NULL, 0, yPos);
CGPathAddLineToPoint(pathToDraw, NULL, self.size.width, yPos);
lineH.path = pathToDraw;
lineH.lineWidth = 1.0;
[lineH setStrokeColor:[UIColor blackColor]];
//Vertical Lines
int xPos = self.size.width/rows * i;
SKShapeNode *lineV = [SKShapeNode node];
CGPathMoveToPoint(pathToDraw, NULL, xPos, 0);
CGPathAddLineToPoint(pathToDraw, NULL, xPos, self.size.height);
lineV.path = pathToDraw;
lineV.lineWidth = 1.0;
[lineV setStrokeColor:[UIColor blackColor]];
//Add lines
[self addChild:lineH];
[self addChild:lineV];
}
}
-(void) createBoxPositionX:(int) fieldIndexX positionY:(int) fieldIndexY{
int width = self.size.width/ROWS;
int height = self.size.height/ROWS;
int x = (width * fieldIndexX);
int y = (height * fieldIndexY);
CGRect box = CGRectMake(x, y, width, height);
SKShapeNode *shapeNode = [[SKShapeNode alloc] init];
shapeNode.path = [UIBezierPath bezierPathWithRect:box].CGPath;
shapeNode.fillColor = SKColor.yellowColor;
//Stroke settings
shapeNode.strokeColor = [SKColor clearColor];
shapeNode.lineWidth = 0;
[self addChild:shapeNode];
//Alternative rectangle
//SKSpriteNode spriteNodeWithColor:CGSize:
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
}
#end
It almost seems like you're not taking into account the line width of the border in each box - so when you create the yellow boxes they are displaced by the number of points equivalent to the number of "borders".
To fix this, change these two lines:
int x = (width * fieldIndexX);
int y = (height * fieldIndexY);
to:
int x = (width * fieldIndexX) + fieldIndexX;
int y = (height * fieldIndexY) + fieldIndexY;
If you are getting 1 pixel shifts into any direction it might be anchor point issue.
By default it is 0.5,0.5 - at center of the sprite.
So if your sprite has even length for example 4, the middle can fall on either 2 or 3 and you will get 1 pixel off positioning.
The fix for this is clear, set the anchor point of node to 0,0, like so:
node.anchorPoint = CGPointMake(0,0);
What this does is that the sprite is pinned to it parent with lower left corner instead of center. Since the lower left corner always starts at 0,0 pixel you will have correct positions regardless of pixel count of your nodes.
But you will have to adjust the nodes position to accomodate this change.
Hope this helps.

how to change image of moving ccsprite using timer

I have around 10 sprite of same image and these are moving, i want to change the image(2 images) of all sprite alternatively by using timer.
I am using following code but its not working for me
CCSprite *target = [CCSprite spriteWithFile:#"images1.png" rect:CGRectMake(0, 0, 120, 140)];
// Determine where to spawn the target along the Y axis
winSize = [[CCDirector sharedDirector] winSize];
int minY = target.contentSize.height/2;
int maxY = (winSize.height/2) - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) ;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
target.position = ccp(winSize.width + (target.contentSize.width/2), actualY);
[self addChild:target];
// Determine speed of the target
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
id delayTime1 = [CCDelayTime actionWithDuration:1.0f];
id calFun1 = [CCCallBlock actionWithBlock:^{
//HERE SET BLUE TEXTURE..
[target setTexture:[[CCSprite spriteWithFile:#"image1.png"]texture]];
}];
id delayTime2 = [CCDelayTime actionWithDuration:1.0f];
id calFun2 = [CCCallBlock actionWithBlock:^{
//HERE SET RED TEXTURE..
[target setTexture:[[CCSprite spriteWithFile:#"image2.png"]texture]];
}];
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration*2.5 position:ccp(-target.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
id sequece = [CCSequence actions:delayTime1, calFun1, delayTime2, calFun2,actionMove, actionMoveDone, nil];
id repeate = [CCRepeatForever actionWithAction:sequece];
[target runAction:repeate];
But by using this code only one image is continuously showing on sprite. The image is not changing.
Try this
-(CCSpriteFrame *)getImageWithName:(NSString *)image{
CCSprite *sprite=[CCSprite spriteWithFile:image];
CCSpriteFrame *frame=[CCSpriteFrame frameWithTexture:sprite.texture rect:CGRectMake(0, 0, sprite.contentSize.width, sprite.contentSize.height)];
return frame;
}
Then
[target setDisplayFrame:[self getImageWithName:#"image1"]];
[target setDisplayFrame:[self getImageWithName:#"image2"]];

How to draw polygons in cocoa touch using UIBezierPath

I want to draw polygon of different sides (4-12). What is the logic for drawing a polygon. For e.g. if user selects 6 side, it should draw a hexagon, if user enters 8 sides it should draw a octagon. I have found the following code but i also want to resize the UIView in which i am drawing a polygon so that the shape inside of the view also grows along with the view. Any body can help me please. Following is the code i am using currently but it is not positioned at the center also when i resize the view that shape moves to another position in the view.
int radius = MINIMUM(widht, height)*0.4 ;
for (int i = 0; i < _numberOFsides; i++){
CGPoint point = CGPointMake(widht/2+radius *cosf(i*2*M_PI/_numberOFsides), widht/2+radius*sinf(i*2*M_PI/_numberOFsides));
if (i==0) {
[_shapePath moveToPoint:point];
}
else{
[_shapePath addLineToPoint:point];
[_shapePath stroke];
}
}
now to resize ur UIBazierPath you can add below code,
CGRect bazierRect = CGPathGetBoundingBox(bezierpath.CGPath)
CGFloat scaleX = view.frame.size.width / bazierRect.frame.size.width;
CGFloat scaleY = view.frame.size.height / bazierRect.frame.size.height;
CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY);
CGPathRef newPath = CGPathCreateCopyByTransformingPath(bezierpath.CGPath, &transform);
bezierPath.CGPath = newPath;
CFRelease(newPath);
If you want to make a regular polygon with any number of sides the following code will give you the vertices of each edge and it is easy to rescale in size and number of sides:
int n = 10; //number of edges
float j = 20; //length of each edge
float x = 130;
float y = 250;//the point 130,250 will be at the bottom of the figure
float angle = 2*M_PI;
for (int i = 0; i < n; i++) {
CGRect frame = CGRectMake(x, y, 2, 2);//put a dot on x,y
NSLog(#"%f | %f, %f", angle, x, y);
x = x + j*cosf(angle);
y = y + j*sinf(angle); //move to the next point
angle = angle - 2*M_PI/n; //update the angle
//display the dot
UIView *rect = [[UIView alloc] initWithFrame:frame];
rect.backgroundColor = [UIColor blueColor];
[self.view addSubview:rect];
}
Hope this helps. If you have any questions feel free to ask and have a great day!
~Deadly Porcupine

3D perspective view in iphone game using cocos2d

I am developing 'Paper Toss' for iphone using cocos2d & I would like to know that how to implement 3D perspective view into this,because while we are throwing the paper ball to the bin,we have to get the 3D feel.I'am attaching the code which i have done,using this i have got a straight line motion.Please help me..
*- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Choose one of the touches to work with
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
// Set up initial location of projectile
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *projectile = [CCSprite spriteWithFile:#"ball.png"
rect:CGRectMake(0, 0, 40, 40)];
projectile.position = ccp(winSize.width/2,20);
// Determine offset of location to projectile
int offX = location.x - projectile.position.x;
int offY = location.y - projectile.position.y;
// Bail out if we are shooting down or backwards
if (offY <= 0) return;
// Ok to add now - we've double checked position
[self addChild:projectile];
// Determine where we wish to shoot the projectile to
int realY = winSize.height + (projectile.contentSize.width/2);
float ratio = (float) offX / (float) offY;
int realX = (realY * ratio) + projectile.position.x;
CGPoint realDest = ccp(realX, realY);
// Determine the length of how far we're shooting
int offRealX = realX + projectile.position.x;
int offRealY = realY + projectile.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
// Move projectile to actual endpoint
[projectile runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:realMoveDuration position:realDest],
[CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)],
nil]];
//add to the projectiles array
projectile.tag = 2;
[_projectiles addObject:projectile];
}*
Finally I have completed paper toss using cocos2d.I implemented bezier curve and here it is,
// Bezier curve control points
bezier.controlPoint_1 = ccp(location.x-CONTROL_POINT1_X, CONTROL_POINT1_Y);
bezier.controlPoint_2 = ccp(location.x-CONTROL_POINT2_X, CONTROL_POINT2_Y);
bezier.endPosition = ccp(location.x-CONTROL_POINT1_X,distance);
// Motion along bezier curve and finally call a function
[projectile runAction:[CCSequence actions:
[CCAutoBezier actionWithDuration:DEFAULT_ACTION_DURATION bezier:bezier],
[CCCallFuncN actionWithTarget:self selector:#selector(collisionCheck:)], nil]];
Just scale your sprite image so it gets smaller the "further away" it is.
Hey you can use bezier curve for 3d perspective view in cocos2d.
bezier.controlPoint_1 = ccp(location.x-CONTROL_POINT1_X, CONTROL_POINT1_Y);
bezier.controlPoint_2 = ccp(location.x-CONTROL_POINT2_X, CONTROL_POINT2_Y);

i want my falling sprites to dissapear half way down the screen

im new to programming, i have been experimenting with cocos2d, heres the problem, i have made a simple game, device in portrait, it has falling sprites, and i want the sprite to disappear when the position of the top of the sprite < screen.height/2 how can this be done?
heres some code you may be interested in:
this is the falling sprite, it falls from the top of the screen to the bottom
-(void)addRock {
CCSprite *rock = [CCSprite spriteWithFile:#"rock.png"
rect:CGRectMake(0, 0, 27, 40)];
// Determine where to spawn the target along the X axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minX = rock.contentSize.width/2;
int maxX = winSize.width - rock.contentSize.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
// Create the target slightly off-screen along the right edge,
// and along a random position along the X axis as calculated above
rock.position = ccp(actualX, 500);
[self addChild:rock];
// Determine speed of the target
int actualDuration = spriteDuration;//speed of sprite
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(actualX,-winSize.height+ rock.contentSize.height)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
[rock runAction:[CCSequence actions:actionMove, nil]];
}
when the sprite move has finished
-(void)spriteMoveFinished:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
}
To fade your sprite out halfway of the Animation you can use CCSpawn to combine the falling animation with the fadeOut. But as you want it to fade out after a given time, you need to create a Sequence of CCDelayTime and CCFadeOut.
double fadeStart = 0.5;
id wait = [CCDelayTime actionWithDuration: actualDuration * fadeStart];
id fadeOut = [CCFadeOut actionWithDuration: actualDuration * (1.0 - fadeStart)];
id waitThenFade = [CCSequence actions: wait, fadeOut, nil];
id actionMove = ...;
id fullAnimation = [CCSpawn actions:actionMove, waitThenFade, nil];
[rock runAction:[CCSequence actions:fullAnimation, actionMoveDone, nil]];
In case you want the fading to start earlier or later you simply have to move the fadeStart value. 0 will start immediately, 1 will actually not fade, so better pick a value in between.
Maybe something like this?
CGSize size = [[CCDirector sharedDirector] winSize];
CCSprite* img = [[CCSprite alloc] initWithFile:#"yourSprite.png"];
img.position = ccp(size.width/2,size.height + img.boundingBox.size.height/2);
[img runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:3 position:ccp(img.position.x,size.height/2 - img.boundingBox.size.height/2)],
[CCFadeOut actionWithDuration:1],
[CCCallFuncN actionWithTarget:nil selector:#selector(spriteMoveFinished:)],
nil]];