cocos-2d: Randomly Falling Blocks - iphone

so I want to randomly create falling blocks. The blocks can be GRects or Sprites, I just have no clue how to go about it.
I need to both randomly choose a time to call the createBlock function. Then I need it to create a block at the top of the screen that falls to the bottom off the screen. The end result should be an endless flow of blocks falling off the screen. I'm less concerned with the random interval part and more concerned with getting as many blocks as I need to fall.
Thanks in advance!

Well, assuming you have a basic understanding of how cocos2d operates (layers, scenes, children, etc), this is how you might go about it.
CGSize winSize = [[CCDirector shareDirector] winSize];
CCSprite *block = [CCSprite spriteWithFile:#"block.png"];
// Generate a random x position
CGFloat x = arc4random() % winSize.width;
// Position the block at a random x, just above the top of the screen
block.position = ccp(x, winSize.height + block.contentSize.height/2);
// Tell the block to fall down to the bottom of the screen over 2 seconds
CCMoveTo *fall = [CCMoveTo actionWithDuration:2 position:ccp(block.position.x, 0 - block.contentSize.height/2)];
[block runAction:fall];
If you wanted this to occur in a constant stream of blocks, you can setup a callback function to call your "createBlock" function every so often. It's not very efficient to constantly recreate blocks, but it's more simple than maintaining a list of off-screen blocks and moving them up to the top to fall again when necessary.
CCSequence *rainBlocks = [CCSequence actions: [CCCallBlock actionWithBlock:^{
[self createBlock];
}],
[CCDelayTime actionWithDuration:3],
nil]];
[self runAction:[CCRepeatForever actionWithAction:rainBlocks]];
I'm not 100% on the syntax there, but that's the general idea.

Related

How to implement camera flyby in Cocos2d

Let's say the width of a level in my game is three times the screen width, and my player starts at the left most edge. How should I go about implementing a camera flyby starting from the right edge at the beginning of this level to scroll through the entire world so the player knows what to expect ahead?
I came across this post here http://www.cocos2d-iphone.org/forum/topic/9568 that seems to be useful, borrowed the block of code in it and put it in my GameWorldLayer, but it didn't work. I'm essentially only seeing a black screen. What's wrong? And what would be a better way of implementing this?
-(void)visit {
CGSize screenDims = [[CCDirector sharedDirector] winSizeInPixels];
CGPoint camPos = gameCamera.position;
float camZoom = gameCamera.zoom;
[[CCDirector sharedDirector] setProjection:kCCDirectorProjectionCustom];
//now set your projection
kmGLMatrixMode(KM_GL_PROJECTION);
//save current projection state
kmGLPushMatrix();
kmGLLoadIdentity();
kmMat4 orthoMat;
kmMat4OrthographicProjection(&orthoMat,
camPos.x -screenDims.width/(2*camZoom),
camPos.x +screenDims.width/(2*camZoom),
camPos.y +screenDims.height/(2*camZoom),
camPos.y -screenDims.height/(2*camZoom),
-1000,
1000);
kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLLoadIdentity();
[super visit];
//put it back
kmGLMatrixMode(KM_GL_PROJECTION);
kmGLPopMatrix();
kmGLMatrixMode(KM_GL_MODELVIEW);
kmGLLoadIdentity();
}
All that is way to complicated for what you want. Position the layer at the end of the level at the beginning and then simply move it to the beginning i.e.
[layer runAction:[CCMoveTo actionWithDuration:10 position:ccp(starty, startx)]];
Where 20 is the time you want it to take for the "flyby" and the position is the start position

How to move the PhysicsSprite in box2d

I am having a physicsSprite of kinematics body type and I want to move the body and sprite bit down and back to its position. I tried it like this Inside update method:
for (NSValue *bodyValue in [self getGoalPostBodiesList])
{
b2Body *gPBody = (b2Body *)[bodyValue pointerValue];
PhysicsSprite *pSprite =(PhysicsSprite *) gPBody->GetUserData();
NSLog(#"\n tag value of Sprite = %d",pSprite.tag);
if(pSprite == goal1)
{
pSprite.position = CGPointMake((gPBody->GetPosition().x)*32.0,(gPBody->GetPosition().y)*32.0);
float angle = gPBody->GetAngle();
pSprite.rotation = -(CC_RADIANS_TO_DEGREES(angle));
id moveDownAction = [CCMoveTo actionWithDuration:0.5 position:CGPointMake(pSprite.position.x,(pSprite.position.y )- 40)];
id moveUpAction = [CCMoveTo actionWithDuration:0.5 position:CGPointMake(pSprite.position.x,(pSprite.position.y )+ 40)];
CCSequence *seqAction = [CCSequence actions:moveDownAction,moveUpAction, nil];
[pSprite runAction:seqAction];
b2Vec2 pos = b2Vec2(pSprite.position.x/32.0, pSprite.position.y/32.0);
gPBody->SetTransform(pos, CC_DEGREES_TO_RADIANS(pSprite.rotation));
gPBody->SetLinearVelocity(b2Vec2(0.0f, 0.0f));
gPBody->SetAngularVelocity(0.0f);
}
}
Still the sprite is not changing its position.
Anyone's help will be deeply appreciated.
Thanks all,
MONISH
To summarize your code, you update the position of your sprite to reflect that of the body, start an animation, and then update the position of the body to correspond to the position of the sprite. So naturally, nothing should move here, since your CCMoveTo actions have not exerted any effect on your sprite yet.
Second, your update method may be called very often, like dozens of times per second, so the animation gets reset continously and will not make any visible progress.
To follow a consistent pattern, how about you set the velocity of your kinematic bodies. Also, update the position of your sprites to correspond to these bodies as you would do for dynamic bodies, but don't set the transformation of your bodies to correspond to their sprites.

CCMenuItemImages positioning?

I am new to cocos2d and I'm trying to build a simple word game. I am stuck with some doubts.
I have arranged the letter's images at bottom of the screen. I've used CCMenuItemImage as buttons and arranged them. No way when I click the images individually, the letters should move to first position and second, and so on. For example:
if there is some letters like b, u, t, x, y, z and if I click on any letters then it should move to some location like (200, 300) (first position) and then second position. Then third... so on.
How should I do it?? I'm a noob so explain properly. Please help!!
Thanks in advance!!
You would want to make your CCMenuItemImage have a selector to target a helper function to help move your CCMenuItemImage. Within the helper function you'd have your CCMenuItemImage moving code.
To move your CCMenuItemImage you can study/copy the cocos2d-iphone project example's ActionsTest.
You can use CCMoveTo or CCMoveBy to move your CCMenuItemImage.
The actions are defined with a duration and a target position. There are some differences between CCMoveTo and CCMoveBy. The significant one is CCMoveBy can be 'reversed' to get a reversed action for your action. Example below moves grossini to ccp(80,80) and the reverse actionByBack moves it back to it's original position. The following code can be found in the ActionsTest.m file of your cocos2d-iphone project. It defines the movement of 3 sprites, tamara, grossini and kathia.
CGSize s = [[CCDirector sharedDirector] winSize];
id actionTo = [CCMoveTo actionWithDuration: 2 position:ccp(s.width-40, s.height-40)];
id actionBy = [CCMoveBy actionWithDuration:2 position: ccp(80,80)];
id actionByBack = [actionBy reverse];
[tamara runAction: actionTo];
[grossini runAction: [CCSequence actions:actionBy, actionByBack, nil]];
[kathia runAction:[ CCMoveTo actionWithDuration:1 position:ccp(40,40)]];
So in your case, if your CCMenuItem is called _alphabet1 you can use the actionBy action definition example to do the following
[_alphabet1 runAction: [CCSequence actions:actionBy, actionByBack, nil]];
That will send your _alphabet1 CCMenuItemImage to ccp(80,80) within 2 seconds and reverse back to the origin in 2 seconds.
If you just want to move your CCMenuItem to a position and not reverse, just use CCMoveTo.

Cocos2D CCNode position in absolute screen coordinates

I've been looking around for a while, and I have not been able to find an answer to this for some reason. It seems simple enough, but maybe I just can't find the right function in the library.
I have a scene with a layer that contains a bunch of CCNodes with each one CCSprite in them.
During the application, I move around the position of the main layer, so that I "pan" around a camera in a way. (i.e. I translate the entire layer so that the viewport changes).
Now I want to determine the absolute position of a CCNode in screen coordinates. The position property return the position relative to the parent node, but I really would like this transformed to its actual position on screen.
Also, as an added bonus, it would be awesome if I could express this position as coordinate system where 0,0 maps to the upper left of the screen, and 1,1 maps to the lower right of the screen. (So I stay compatible with all devices)
Edit: Note that the solution should work for any hierarchy of CCNodes preferably.
Every CCNode, and descendants thereof, has a method named convertToWorldSpace:(CGPoint)p
This returns the coordinates relative to your scene.
When you have this coordinate, flip your Y-axis, as you want 0,0 to be in the top left.
CCNode * myNode = [[CCNode alloc] init];
myNode.position = CGPointMake(150.0f, 100.0f);
CCSprite * mySprite = [[CCSprite alloc] init]; // CCSprite is a descendant of CCNode
[myNode addChild: mySprite];
mySprite.position = CGPointMake(-50.0f, 50.0f);
// we now have a node with a sprite in in. On this sprite (well, maybe
// it you should attack the node to a scene) you can call convertToWorldSpace:
CGPoint worldCoord = [mySprite convertToWorldSpace: mySprite.position];
// to convert it to Y0 = top we should take the Y of the screen, and subtract the worldCoord Y
worldCoord = CGPointMake(worldCoord.x, ((CGSize)[[CCDirector sharedDirector] displaySizeInPixels]).height - worldCoord.y);
// This is dry coded so may contain an error here or there.
// Let me know if this doesn't work.
[mySprite release];
[myNode release];

CCSprite following a sequence of CGPoints

I'm developing a line drawing game, similar to Flight Control, Harbor Master, and others in the appstore, using Cocos2D.
For this game, I need a CCSprite to follow a line that the user has drawn. I'm storing a sequence of CGPoint structs in an NSArray, based on the points I get in the touchesBegin and touchesMoved messages. I now have the problem of how to make my sprite follow them.
I have a tick method, that is called at the framerate speed. In that tick method, based on the speed and current position of the sprite, I need to calculate its next position. Is there any standard way to achieve this?
My current approach is calculate the line between the last "reference point" and the next one, and calculate the next point in that line. The problem I have is when the sprite "turns" (moves from one segment of the line to another).
Any hint will be greatly appreciated.
Why do you code your own tick method? Why don't you just use the built-in CCMoveTo method?
(void) gotoNextWayPoint {
// You would need to code these functions:
CGPoint point1 = [self popCurrentWayPoint];
CGPoint point2 = [self getCurrentWayPoint];
// Calculate distance from last way point to next way point
CGFloat dx = point2.x - point1.x;
CGFloat dy = point2.y - point1.y;
float distance = sqrt( dx*dx + dy*dy );
// Calculate angle of segment
float angle = atan2(dy, dx);
// Rotate sprite to angle of next segment
// You could also do this as part of the sequence (or CCSpawn actually) below
// gradually as it approaches the next way point, but you would need the
// angle of the line between the next and next next way point
[mySprite setRotation: angle];
CCTime segmentDuration = distance/speed;
// Animate this segment, and afterward, call this function again
CCAction *myAction = [CCSequence actions:
[CCMoveTo actionWithDuration: segmentDuration position: nextWayPoint],
[CCCallFunc actionWithTarget: self selector: #selector(gotoNextWayPoint)],
nil];
[mySprite runAction: myAction];
}