CCMoveTo doesn't get the updated player postition.....(iphone,cocos2d) - iphone

I'm adding an enemy like this:
-(void)addEnemy {
if ([spawnedEnemies count] < 25) {
CCSprite* sprite = [CCSprite spriteWithFile:#"white.png"];
float randomX = arc4random() % 480;
float randomY = arc4random() % 320;
sprite.position = ccp(randomX,randomY);
[spawnedEnemies addObject:sprite];
[self addChild:sprite];
[sprite runAction:[CCMoveTo actionWithDuration:5 position:player.position]];
} }
but if my player moves the sprite still moves to the last player position...
because of that i tried this in my tick:
-(void)tick:(ccTime)delta {
for (CCSprite *sp in spawnedEnemies) {
[sp stopAllActions];
[sp runAction:[CCMoveTo actionWithDuration:5
position:player.position]];
} }
but the enemies will only move if i stop moving (there just moving reallllllllyyyyyyyyy slow because every time i move it calls [sp stopAllActions]
What should I do now?
EDIT:*EDIT:*EDIT:*EDIT:*EDIT:*EDIT:*EDIT:*EDIT:*EDIT:
Now I'm doing this and the enemies are moving to the player even if the player is moving
but there's a problem: the nearer the enemy (is to the player) the slower they are moving...
How to solve this?
//function to apply a velocity to a position with delta
static CGPoint applyVelocity(CGPoint velocity, CGPoint position, float delta){
return CGPointMake(position.x + velocity.x * delta, position.y + velocity.y * delta);
}
-(void)tick:(ccTime)delta {
for (CCSprite *sp in spawnedEnemies) {
CGPoint m = ccpSub(player.position, sp.position);
sp.position = applyVelocity(m, sp.position, 1.0/60.0f);
}
}

I have four ideas:
Schedule a new update selector with a lower frequency and move the enemies in that method: [self schedule:#selector(moveEnemies) interval:0.1];
Only move the enemies when the player.position changes, maybe in your ccTouchesMoved-method.
Instead of using CCActions, set the position of the sprite directly, you need to do some vector-computations.
Use a physics-engine like Box2D (included in Cocos2D SDK). Then you can simply apply a force to each enemy to the direction of the player in each step.
EDIT:
In order to move the enemies with constant velocity, normalize the velocity vector m:
m = ccpMult(ccpNormalize(m), kSpeed);
kSpeed is a constant float value to adjust the speed.
Hope that helps...

Related

Using SpriteKit how can you move sprite nodes to a point with a random but consistent speed

I'm currently making my first sprite game and one of the things i have implemented into my game is objects coming in from the side, move all the way across the screen, and then be removed from the parent. Here's what that looks like.
MyScene.m
-(void)createObstacle0 {
CGPoint startPoint = CGPointMake(-20, 100);
SKSpriteNode *obstacle = [SKSpriteNode spriteNodeWithImageNamed:#"obstacle"];
obstacle.position = CGPointMake(startPoint.x, startPoint.y);
obstacle.name = #"obstacle0";
[self addChild:obstacle];
float randomNum = arc4random_uniform(2) + 1.92;
[self performSelector:#selector(createObstacle0) withObject:nil afterDelay:randomNum];
}
excerpt from update method
[self enumerateChildNodesWithName:#"obstacle0" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.x > 360) {
[node removeFromParent];
} else {
node.position = CGPointMake(node.position.x + 5.2, node.position.y);
}
}];
At the moment, my objects only move across the screen at one speed. I tried using arc4random inside the currentTime method code, but because thats evaluated every frame, my object would not stay at one speed. It would speed up, slow down, and look very erratic. How can i change my code in CurrentTime to allow my objects crossing the screen to be set a random speed as soon as its made and to keep it until it is destroyed?
Second question:
int yMin = 90;
int yMax = 110;
CGPoint startPoint = CGPointMake(-20, yMin + arc4random_uniform(yMax - yMin));
I would suggest that instead of manually updating the child nodes position to move it from one side to another you create your obstacle and then call runAction: on it using an SKAction created with the moveTo:duration: method. You specify the final point you want your obstacle to end up at as well as how long you want this move to take. Pass in a random number with in the minimum and maximum time you want it to take to duration.
This should allow you to create consistent but randomised object movement.
int MAX_TIME = 20;
int MIN_TIME = 10;
[obstacle runAction:[SKAction moveTo:CGPointMake( 10, 100 ) duration:MIN_TIME + arc4random_uniform( MAX_TIME - MIN_TIME )]];

Moving a sprite with touches began, casting and parameters in obj - c?

I've been reading a book on the cocos2d framework for ios5 for a few days and have developed a small game that the book walks you through. To control the sprite in this game you use the accelerometer:
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.4f;
float sensitivity = 6.0f;
float maxVelocity = 100;
// adjust velocity based on current accelerometer acceleration
playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity;
// we must limit the maximum velocity of the player sprite, in both directions (positive & negative values)
if (playerVelocity.x > maxVelocity)
{
playerVelocity.x = maxVelocity;
}
else if (playerVelocity.x < -maxVelocity)
{
playerVelocity.x = -maxVelocity;
}
// Alternatively, the above if/else if block can be rewritten using fminf and fmaxf more neatly like so:
// playerVelocity.x = fmaxf(fminf(playerVelocity.x, maxVelocity), -maxVelocity);
}
Now I'm wondering if I can change this code to allow the sprite to still accelerate/decelerate along the x axis, but to use touch input rather than the accelerometer, and to go faster the longer the touch is held down for? So a touch to the right would move the sprite to that spot slowly, if the touch is released, it stops moving to that spot. The longer a touch is held down, the faster the sprite moves.
is there anything in the framework to allow me to implement a rotation mechanism that allows my sprite to rotate to the position that the touch was in, so it looks like its facing the point thats been touched?
Well, afaik theres no method that will determine the angle to the touch and then rotate the sprite accordingly, but if you have the x and y coordinates of the sprite and the touch you can calculate it yourself fairly easily.
CGPoint spriteCenter; // this should represent the center position of the sprite
CGPoint touchPoint; //location of touch
float distanceX = touchPoint.x - spriteCenter.x;
float distanceY = touchPoint.y - spriteCenter.y;
float angle = atan2f(distanceY,distanceX); // returns angle in radians
// do whatever you need to with the angle
Once you have the angle you can set the rotation of the sprite.

How to give effect like throwing a ball in a Bucket?

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.

Move object into screen without gravity into box2d in iPhone

i use following code to move my Box2D object into screen, but because gravity of my world or something else i dont know why my objects is forced to move down, i am new to box2d.
i want to move my object in entire world without gravity.
-(void) tick:(NSTimer *)timer {
int32 velocityIterations = 8;
int32 positionIterations = 1;
world->Step(1.0f/60.0f, velocityIterations, positionIterations);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
UIView *oneView = (UIView *)b->GetUserData();
CGPoint newCenter = CGPointMake(b->GetPosition().x * PTM_RATIO,self.view.bounds.size.height - b->GetPosition().y * PTM_RATIO);
oneView.center = newCenter;
CGAffineTransform transform = CGAffineTransformMakeRotation(- b->GetAngle());
oneView.transform = transform;
}
}
}
my accelerometer code is as follow.
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
b2Vec2 gravity;
gravity.Set( acceleration.x * 1.81, acceleration.y * 1.81 );
world->SetGravity(gravity);
}
pleas if any one work around.
Thanks.
As i understand you want to move your object setting it's position. It's a bad idea because it will provide non-physical behavior of the bodies colliding with your object. That's because if you will only change the position of your body it's velocity for physics engine will be still zero and collision will be processed according to zero speed of your object.
A better solution is to use b2_kinematicBody type for your object. Then you will be able to control it's motion specifying it's velocity vector and physics will behave as expected. Also the gravity (and no other forces) will not be applied to your object because of it's type.
EDIT
//creation
b2BodyDef bDef;
bDef.type = b2_kinematicBody;
bDef.position.Set(5, 6);
b2Body *body = physWorld->CreateBody(&bDef);
//control
body->SetLinearVelocity(b2Vec2(3, 4));

Destroying Sprites in and around the Collided Sprite

I need help in destroying the sprites which are in and around the collided sprites ie in a radius of 2.5 cms all sprites should be destroyed. Idea here is i will be shooting a projectile from bottom to the objects falling from the top. Once collision happens all the sprites around that radius also should be destroyed. Like a Bomb Effect. I have used box2d for collision ie contact listener. How to go about doing that?
Please Suggest:-)
Regards,
Karthik
Hold an array of your sprites, or if you are using a batchNode you can do that.
When the collision happens, go through your sprites. Check the distance with their position and the explosion center and kill them if they are in range.
e.g.
CCSprite *sprite;
for (sprite in [batchNode descendants]) {
if ([sprite isInRangeOf:[explosionSprite position]]) {
[sprite yourRemovalMethod];
}
}
the method 'isInRangeOf:' would be within your sprite subclass
Something like..
-(BOOL) isInRangeOf:(CGPoint)explosionCenter {
//Use pythagoras theorem to work out the distance between [sprite position] and [explosionCenter]
CGFloat dx = explosionCenter.x - [self position].x;
CGFloat dy = explosionCenter.y - [self position].y;
float distance = sqrt(dx*dx + dy*dy );
// If your distance is less than or equal to your 'death radius' return YES, else No.
if (distance <= 25) {
return TRUE;
} else {
return FALSE;
}
}
Hope that helps.