i have used cocos2d for game development.but when i use a sprite in CCLayer(inherited) to move through ccTime.but it moves very slowly.i have set in appgelegate CCDirector setAnimationInterval for (1.0/60) The code is as following:
-(id) init
{
if ((self = [super init]))
{
danceSprite = [CCSprite spriteWithFile:#"images.png"];
[self addChild:danceSprite];
// position the sprite in the center of the screen
CGSize s = [[CCDirector sharedDirector] winSize];
danceSprite.position = ccp(s.width/2,s.height/2); //CCSprite
bg_pos.x = danceSprite.position.x;
bg_pos.y = danceSprite.position.y;
[self scheduleUpdate];
}
return self;
}
-(void) update:(ccTime)delta
{
CGPoint pos = danceSprite.position;
bgX = pos.x;
//bgX -= 30.0;
int newX;
newX = bgX + 1.0 * GAME_SPEED_ADJUSTMENT;
pos.x = bgX;
}
GAME_SPEED_ADJUSTMENT
variable/constant
to multiply with delta to get a faster movement. My start setting is always a
minimum of 10
, in your case it's 1, so I would expect it to move rather slowly.
So it looks like
newX = oldX + delta *
GAME_SPEED_ADJUSTMENT
Try this first - one might also use this to increase the difficulty of the game and globally move things faster.
If this doesn't work, just come back....
Related
I am trying to learn how to implement radial gravity to specific objects and I was using the tutorial on (http://www.vellios.com/2010/06/11/radial-gravity-w-box2d-source/), but this tutorial is written an older version of Cocos2d. I have tried to fixed it as much as I could. If someone can point me in the right direction, i would really appreciate. Here is what I have so far. I commented the places that I am having problems with. Thank you.
HelloWorldLayer.h
#import <GameKit/GameKit.h>
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "Box2D.h"
#import "GLES-Render.h"
#define PTM_RATIO 32
// HelloWorldLayer
#interface HelloWorldLayer : CCLayer <GKAchievementViewControllerDelegate, GKLeaderboardViewControllerDelegate>
{
b2World* world; // strong ref
GLESDebugDraw *m_debugDraw; // strong ref
}
// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;
#end
HelloWorldLayer.mm
// Import the interfaces
#import "HelloWorldLayer.h"
// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#define PTM_RATIO 32
#define kRADIAL_GRAVITY_FORCE 250.0f
enum {
kTagParentNode = 1,
kTagTileMap = 1,
kTagSpriteSheet = 1,
kTagAnimation1 = 1,
};
#pragma mark - HelloWorldLayer
#interface HelloWorldLayer()
-(void) initPhysics;
-(void) addNewSpriteAtPosition:(CGPoint)p;
-(void) createMenu;
#end
#implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
if( (self=[super init])) {
// enable events
self.isTouchEnabled = YES;
self.isAccelerometerEnabled = YES;
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCLOG(#"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
// This will speed up the physics simulation
bool doSleep = true;
// Construct a world object, which will hold and simulate the rigid bodies.
world = new b2World(gravity);
world->SetAllowSleeping(doSleep);
world->SetContinuousPhysics(true);
//Set up sprite
CCSprite *sheet = [CCSprite spriteWithFile:#"blocks.png"];
[self addChild:sheet z:0 tag:kTagSpriteSheet];
[self addNewSpriteAtPosition:ccp(screenSize.width/2, screenSize.height/2)];
//ERROR Use of undeclared identifier 'CCLabel'
//ERROR Use of undeclared identifier 'label'
CCLabel *label = [CCLabel labelWithString:#"Tap Screen" fontName:#"Marker Felt" fontSize:32];
// ERROR Use of undeclared identifier 'label'
[self addChild:label z:0];
//ERROR Use of undeclared identifier 'label'
[label setColor:ccc3(0,0,255)];
//ERROR Use of undeclared identifier 'label'
label.position = ccp( screenSize.width/2, screenSize.height-50);
// Create our static "Planet" - Nick
b2CircleShape shape;
shape.m_radius = 1.0f;
shape.m_p.Set(8.0f, 8.0f);
b2FixtureDef fd;
fd.shape = &shape;
//ERROR Use of undeclared identifier 'planet'
planet = groundBody->CreateFixture(&fd);
// End Create Planet - Nick
[self schedule: #selector(tick:)];
// init physics
[self initPhysics];
[self scheduleUpdate];
}
return self;
}
-(void) dealloc
{
delete world;
world = NULL;
delete m_debugDraw;
m_debugDraw = NULL;
[super dealloc];
}
-(void) createMenu
{
}
-(void) initPhysics
{
CGSize s = [[CCDirector sharedDirector] winSize];
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
world = new b2World(gravity);
// Do we want to let bodies sleep?
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);
// Debug Draw functions
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
// flags += b2Draw::e_jointBit;
// flags += b2Draw::e_aabbBit;
// flags += b2Draw::e_pairBit;
// flags += b2Draw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);
// Define the ground box shape.
b2EdgeShape groundBox;
// bottom
groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
}
-(void) draw
{
//
// IMPORTANT:
// This is only for debug purposes
// It is recommend to disable it
//
[super draw];
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
glDisable(GL_TEXTURE_2D);
glDisable(GL_COLOR_BUFFER_BIT);
world->DrawDebugData();
}
-(void) addNewSpriteAtPosition:(CGPoint)p
{
CCLOG(#"Add sprite %0.2f x %02.f",p.x,p.y);
CCSprite *sheet = (CCSprite*) [self getChildByTag:kTagSpriteSheet];
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
//ERROR Cannot initialize a parameter of type 'CCTexture2D *' with an lvalue of type 'CCSprite *'
CCSprite *sprite = [CCSprite spriteWithTexture:sheet rect:CGRectMake(32 * idx,32 * idy,32,32)];
[sheet addChild:sprite];
sprite.position = ccp( p.x, p.y);
// Define the dynamic body.
//Set up a 1m squared box in the physics world
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
bodyDef.userData = sprite;
b2Body *body = world->CreateBody(&bodyDef);
// Define another box shape for our dynamic body.
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
}
-(void) update: (ccTime) dt
{
//It is recommended that a fixed time step is used with Box2D for stability
//of the simulation, however, we are using a variable time step here.
//You need to make an informed choice, the following URL is useful
//http://gafferongames.com/game-physics/fix-your-timestep/
int32 velocityIterations = 8;
int32 positionIterations = 1;
// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
world->Step(dt, velocityIterations, positionIterations);
//Iterate over the bodies in the physics world
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
b2Body* ground = planet->GetBody();
b2CircleShape* circle = (b2CircleShape*)planet->GetShape();
// Get position of our "Planet" - Nick
b2Vec2 center = ground->GetWorldPoint(circle->m_p);
// Get position of our current body in the iteration - Nick
b2Vec2 position = b->GetPosition();
// Get the distance between the two objects. - Nick
b2Vec2 d = center - position;
// The further away the objects are, the weaker the gravitational force is - Nick
float force = kRADIAL_GRAVITY_FORCE / d.LengthSquared(); // 150 can be changed to adjust the amount of force - Nick
d.Normalize();
b2Vec2 F = force * d;
// Finally apply a force on the body in the direction of the "Planet" - Nick
b->ApplyForce(F, position);
if (b->GetUserData() != NULL) {
//Synchronize the AtlasSprites position and rotation with the corresponding body
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//Add a new body/atlas sprite at the touched location
for( UITouch *touch in touches ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
[self addNewSpriteAtPosition:location];
}
}
- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
static float prevX=0, prevY=0;
//#define kFilterFactor 0.05f
#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;
// accelerometer values are in "Portrait" mode. Change them to Landscape left
// multiply the gravity by 10
b2Vec2 gravity( -accelY * 10, accelX * 10);
world->SetGravity( gravity );
}
#pragma mark GameKit delegate
-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
[[app navController] dismissModalViewControllerAnimated:YES];
}
#end
Here is my movement method:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
location = [touch locationInView: [touch view]];
CGPoint location_ = [[CCDirector sharedDirector] convertToGL:location];
NSLog(#"Click Position = (%f,%f)",location_.x,location_.y);
float moveSpeed = 40.0;
float moveDist = sqrt(pow(abs(location_.x - sprite.position.x),2) + pow(abs(location_.y - sprite.position.y),2));
float moveTime = (moveDist / moveSpeed);
[sprite runAction:[CCMoveTo actionWithDuration:moveTime position:location_]];
}
And here's my init method.
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
self.isTouchEnabled = YES;
// create and initialize a Label
[self scheduleUpdate]; // available since v0.99.3
[self schedule: #selector(update:) interval:0.5];
CGSize size = [[CCDirector sharedDirector] winSize];
bg = [CCSprite spriteWithFile:#"testBG.png"];
bg.position = ccp( size.width /2 , size.height/2 );
[self addChild: bg];
sprite = [CCSprite spriteWithFile:#"testSprite.png"];
sprite.position = ccp( size.width /2 , size.height/2 );
[self addChild: sprite];
[self runAction:[CCFollow actionWithTarget:sprite]];
}
return self;
}
My window follows the sprite around, but like I said, the sprite will go to a different point than touched after the first touch. Can anyone tell me what's going on?
edit: I'm thinking that it may have to do with the co-ordinate system itself, or maybe it's to do with
[touches anyObject];? My searches have turned up little.
edit2: I've found that if I return my sprite back to the middle of the bg sprite again, it'll behave normally again from there, until it's too far off.
I believe the problem is with [self runAction:[CCFollow actionWithTarget:sprite]];.
selfis your Scene that you don't want to move around.
The pattern for doing this would be to add a CCNodethat you would call a your _contentNodeto your sceneand add everything you would like to move as a child.
Then you would call [_contentNode runAction:[CCFollow actionWithTarget:sprite]];
IN this I'll suggest you a simple thing... Before adding a new action, stop the previous action on the sprite...
In your ccTouchesBegan method
[sprite stopAllActions];
[sprite runAction:[CCMoveTo actionWithDuration:moveTime position:location_]];
I think this will help as you sprite will stop once you touch..
In current case its undergoing an action.. Suppose its duration is 2 sec. and on next touch you run action of 1 sec. Then it will go to wrong point as previous action is still not completed.
Hope this helps.. :)
I am new to Cocos2d and hence not aware of most of the classes and also the functions. In my application, I want to implement a module like touching and dragging the ball in a direction of a barrel will pass the ball and will put the ball in the barrel. I am able to pass the ball in the direction but then it just would go out of the screen following the coordinates(x.y).
- (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];
// Determine offset of location to projectile
int offX = location.x - ball.position.x;
int offY = location.y - ball.position.y;
// Bail out if we are shooting down or backwards
if (offX <= 0)
return;
// Determine where we wish to shoot the projectile to
int realX = winSize.width + (ball.contentSize.height/2);
float ratio = (float) offY / (float) offX;
int realY = (realX * ratio) + ball.position.y;
CGPoint realDest = ccp(realX, realY);
if(realX>=320)
realX = 320;
if(realY>=480)
realY = 480;
CGPoint realDest = ccp(realX, realY);
int good = goodBarrel.position.x;
int bad = badBarrel.position.x;
int destY = realDest.x;
if(destY<=good)
destY = good;
if(destY>=bad)
destY = bad;
realDest.x = destY+10;
// Determine the length of how far we're shooting
int offRealX = realX - ball.position.x;
int offRealY = realY - ball.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
// Move projectile to actual endpoint
[ball runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:realMoveDuration position:realDest],
[CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)],
nil]];
}
I need to do something like it will get the idea of barrels position and finding the top of the barrel and will put the ball in the center of the barrel and also while moving the ball,the size of the ball gets reduced to give effect of throwing the ball to a distant place. GoodBarrel and BadBarrel are the two barrels I have put in the opposite of ball to put the ball in the same. Is there any function or method I can work on?
Immediately after the [ball runAction: .... ]; line, you can run another action on the same object, simultaneously. Add a
[ball runAction:[CCScaleTo actionWithDuration:realMoveDuration scale:0.4f];
both actions will complete at the same time, providing the 'illusion' of distance you are seeking to create.
You can use collision detection, or in other words check to see if the CGRect of ball and barrel intersect
- (void)collisionDetection:(ccTime)dt{
CGRect ballRect = CGRectMake(
ball.position.x,
ball.position.y,
10,
10);
CGRect barrelRect = CGRectMake(
barrel.position.x,
barrel.position.y,
50,
10);
if (CGRectIntersectsRect(ballRect, barrelRect))
{
// Run Animation of Ball Dropping in the Barrel
[self removeChild:ball cleanup: YES];
}
}
hope this is what you need.
I've created a simple cocos2d iPhone game that has a CCParticleSystemQuad emitter that emits particles across the scene that are shaped like leaves, to give the illusion of wind.
Right now, the wind (gravity) is blowing across the scene from right to left. I am currently stuck trying to figure out how to update the emitter.gravity to switch from (-500, 80) to (500, 80), hopefully without removing the particles that have already been drawn.
In this example, I'd like the switch to occur on a touch event that happens anywhere on the screen.
What should my touch event look like?
How do I detect a touch that happens any where on the screen?
I've also never implemented a scheduled update loop. Is this the direction I should be thinking? And I suppose a more basic question is, am I going about this the right way?
Here's the code I've got so far:
My init:
-(id) init
{
if( (self=[super init])) {
CCSprite * sky = [CCSprite spriteWithFile:#"sky.png"];
[self addChild:sky z:0 tag:1];
windDirection = -200;
[self leaveEmitters];
}
return self;
}
My leaveEmiiters function
-(void) leaveEmitters{
NSLog(#"The wind is :%i", windDirection);
CCParticleSystemQuad * emitter;
emitter = [[CCParticleSystemQuad alloc] initWithTotalParticles:100];
emitter.texture = [[CCTextureCache sharedTextureCache] addImage: #"particlesLeaves.png"];
emitter.emitterMode = kCCParticleModeGravity;
emitter.duration = -1;
emitter.gravity = ccp(windDirection, -80);
emitter.angle = 0;
emitter.angleVar = 360;
emitter.speed = 10;
emitter.speedVar = 100;
emitter.radialAccelVar = 0;
emitter.tangentialAccel = 0;
emitter.tangentialAccelVar = 0;
emitter.life = 10;
emitter.lifeVar = 0;
emitter.startSpin = 0;
emitter.startSpinVar = 360;
emitter.endSpin = 0;
emitter.endSpinVar = 720;
ccColor4F startColorVar = {255, 100, 0, 0};
ccColor4F startColor = {0, 240,0, 255};
emitter.startColor = startColor;
emitter.startColorVar = startColorVar;
emitter.endSize = emitter.startSize;
emitter.startSize = 60.0f;
emitter.emissionRate = 3;
emitter.blendAdditive = NO;
emitter.position = ccp(500,250);
[self addChild: emitter z:10];
emitter.autoRemoveOnFinish = YES;
CCParticleSystemQuad * emitter2;
emitter2 = [[CCParticleSystemQuad alloc] initWithTotalParticles:100];
emitter2.texture = [[CCTextureCache sharedTextureCache] addImage: #"particlesLeaves.png"];
emitter2.emitterMode = kCCParticleModeGravity;
emitter2.duration = -1;
emitter2.gravity = ccp(windDirection, 0);
emitter2.angle = 0;
emitter2.angleVar = 360;
emitter2.speed = 10;
emitter2.speedVar = 100;
emitter2.radialAccelVar = 0;
emitter2.tangentialAccel = 0;
emitter2.tangentialAccelVar = 0;
emitter2.life = 10;
emitter2.lifeVar = 0;
emitter2.startSpin = 0;
emitter2.startSpinVar = 360;
emitter2.endSpin = 0;
emitter2.endSpinVar = 720;
emitter2.startColor = startColor;
emitter2.endSize = emitter.startSize;
emitter2.startSize = 60.0f;
emitter2.emissionRate = 3;
emitter2.blendAdditive = NO;
emitter2.position = ccp(-500,250);
[self addChild: emitter2 z:10];
emitter2.autoRemoveOnFinish = YES;
}
And finally, my ccTouchesBegan function, which isn't working at all. Why?
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
int x = location.x;
int y= location.y;
CCSprite * sky = (CCSprite *) [self getChildByTag:1];
sky.anchorPoint = ccp(0, 0);
CGRect skyHitBox = CGRectMake(sky.position.x, sky.position.y, 500, 500);
if (CGRectContainsPoint(skyHitBox, location)) {
NSLog(#"touch accepted: x: %i y:%i", x, y);
}
}
Any help, feedback, or suggested learning direction would be GREATLY appreciated. Thanks so much!
EDIT: I answered my own questions like 20 seconds after I posted this...
If someone wants to post their own answers, I'll leave this up for 7 more hours.
you just can keep a CCParticleSystemQuad * emitter as private instance member so you can modify emitter.gravity inside the ccTouchesBegan
i didnt get exactly what kind of wind effect you'r trying to achieve. If you want to simply switch from one 500,80 to -500,80 its pretty easy
emitter.gravity = ccp(-emitter.gravity.x, emitter.gravity.y);
If you want to change the wind direction based on witch side of the skybox you hit, with hitting the center equal no wind, and more your touch is far from the center the stronger the wind will get.
I didnt try this but should be a good starting point.
You first need to get get the touched point in skybox coordinates
CGPoint skyTouchedPoint = ccp( x - sky.position.x, y - sky.position.y)
then you can define the center point of you sky box as
CGPoint skyCenterPoint = ccp(sky.size.width/2, sky.size.height/2);
and get a vector pointing to the right side, if you touch the right half side of the skybox and pointing left if you touch the left half side of the skybox
CGPoint windDirection = ccpSub(skyTouchedPoint, skyCenterPoint);
this vector module is higher the more far from the center you touch happened, you should now increase this vector module by a factor that suites for you with
windDirection = ccpMult(windDirection, 10.f); //try different values here
now you can use only the x component of this vector if you want the wind to use always the same y (as you posted the value of 80)
I have a small game that works perfectly when compiling, howevery every second time I
compile it, it gives me the error:
-(void) addHeroCar{
CGSize screenSize = [CCDirector sharedDirector].winSize;
sprite = [CCBodySprite spriteWithFile:#"carNew.png"];
sprite.world = self;
sprite.physicsType = kDynamic;
sprite.collisionType = kBoxCollisionType;
sprite.collidesWithType = kBoxCollisionType | kWallCollisionType;
sprite.position = ccp(screenSize.width / 2, [sprite boundingBox].size.height / 2);
sprite.density = 0.7f;
sprite.friction = 0.3f;
[sprite addBoxWithName:#"box"];
[self addChild:sprite z:1 tag:HERO_TAG];
sprite.fixed = YES;
}
and the debugger shows me the following errors:
-(void) addChild: (CCNode*) child z:(int)z tag:(int) aTag
{
NSAssert( child != nil, #"Argument must be non-nil");
Im using a cocos2d + box2d wrapper from an other developer, just FYI.
Any suggestions?
Regards,
Mirza