I'm pretty new to iOS and cocos2d and I'm having a problem trying to create what I want the code to do. Let me give you the rundown first then i'll show what I've got.
What I got so far is a giant sprite in the middle and when that is touched, I want to have say 2000 of a different sprite generate from the center position and like a particle system, shoot off in all directions.
First off, I tried coding implementing the velocity code (written in Objective-c) over to Cocos2d and that didn't work. -code-
-(void)ccTouchBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(CGRectContainsPoint([[self getChildByTag:1] boundingBox], location))
{
for( int i = 0; i < 100; i++)
{
CCSprite *ballGuySprite = [CCSprite spriteWithFile:#"ball.png"];
[self addChild:ballGuySprite z:7];
ballGuySprite.position = ccp(((s.width + i *10) /2), (s.height + i *10) /2);
}
}
}
What that does is when I touch the first sprite, 100 of the other sprites are on top of each other leading to the top right corner.
The velocity code that I used when as followed and when I try to apply it to the sprite nothing happens. - Velocity code -
-(void) checkCollisionWithScreenEdges
{
if(ballGuysRect.origin.x <= 0)
{
ballVelocity.x = abs(ballVelocity.x);
}
if(ballGuysRect.origin.x >= VIEW_WIDTH - GUY_SIZE)
{
ballVelocity.x = -1 * abs(ballVelocity.x);
}
if(ballGuysRect.origin.y <= 0)
{
ballVelocity.y = abs(ballVelocity.y);
}
if(ballGuysRect.origin.y >= VIEW_HEIGHT - GUY_SIZE)
{
ballVelocity.y = -1 * abs(ballVelocity.y);
}
}
-(void) updateModelWithTime:(CFTimeInterval)timestamp
{
if(lastTime == 0.0)
{
lastTime = timestamp;
}
else
{
timeDelta = timestamp - lastTime;
lastTime = timestamp;
ballGuysRect.origin.x += ballVelocity.x * timeDelta;
ballGuysRect.origin.y += ballVelocity.y * timeDelta;
[self checkCollisionWithScreenEdges];
}
}
When I attach that code to the sprite, nothing happen.
I also tried adding a CCParticleExplosion which did do what I wanted but I still want to add a touch function to each individual sprite that's generated and they tend to just fade away.
So again, I'm still fairly new to this and if anyone could give any advice that would be great.
Thanks for your patients and time to read this.
Your code looks good to me, but you never seem to update the position of your sprites. Somewhere in updateModelWithTime I would expect you to set ballGuySprite.position = ballGuysRect.origin plus half of its height or width, respectively.
Also, I don't see how updateModelWithTime can control 100 different sprites. I see only one instance of ballGuysRect here. You will need a ballGuysRect for each sprite, e.g. an array.
Finally, I'd say that you don't really need ballGuysRect, ballVelocity, and the sprite. Ball could be a subclass of CCSprite, including a velocity vector. Then all you need to do is keep an array of Balls and manage those.
I am not sure what version of cocos2d you are using but a few things look a bit odd.
Your first problem appears to be that you are just using the same sprite over and over again.
Since you want so many different sprites shooting away, I would recommend that you use a CCSpriteBatchNode, as this should simplify things and speed things up.
The following code should help you get that set up and move them offscreen with CCMoveTo:
//in your header file:
CCSpriteBatchNode *batch;
//in your init method
batch = [CCSpriteBatchNode batchNodeWithFile:#"ball.png"];
//Then in your ccTouches method
for( int i = 0; i < 100; i++)
{
CCSprite *ballGuySprite = [CCSprite spriteWithFile:#"ball.png"];
[batch addChild:ballGuySprite z:7 tag:0];
ballGuySprite.position = ccp(where-ever the center image is located);
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(random off screen location)];
[ballGuySprite runAction:actionMove];
}
Also usually your update method looks something like the following:
-(void)update:(ccTime)delta{
//check for sprites that have moved off screen and disable them.
}
Hope this helps.
Related
I wanted to create a space background so I make a for loop to create the stars. Here is the code:
for (int i = 0; i<100; i++) {
SKShapeNode *star= [SKShapeNode shapeNodeWithPath:Path.CGPath];
star.fillColor = [UIColor whiteColor];
star.physicsBody = nil;
int xposition = arc4random()%960;
int yposition = arc4random()%640;
star.position = CGPointMake(xposition, yposition);
float size = (arc4random()%3 + 1)/10.0;
star.xScale = size;
star.yScale = size;
star.alpha = (arc4random()%10 + 1 )/ 10.0;
star.zPosition = -2;
[self addChild:star];
}
But it takes a lot from my cpu. when the code is activated the cpu at top 78%.(I check the code in the iPhone simulator);
Somebody know how to fix it? thanks.
Your physics bodies continue to calculate even when off of the screen. You will need to remove them once they go out of the frame, otherwise everything will slow to a crawl. (And to echo what others have stated you will eventually need a real device).
From this document: Jumping Into Sprite Kit
You can implement the "Did Simulate Physics" method to get rid of the stars that fell from the bottom of the screen like so:
-(void)didSimulatePhysics
{
[self enumerateChildNodesWithName:#"star" usingBlock:^(SKNode *node, BOOL *stop) {
if (node.position.y < 0)
[node removeFromParent];
}];
}
Note that you will first need to set the name of your star shapes by using the name property like so:
star.name = "star"
So currently right now I am having a frustrating bug with my images.
Lets start with right off the bat, what is the bug?
So the bug is when I add this particular code into my project.
-(void)addfive{
score = score + 1;
scoreString = [NSString stringWithFormat:#"SCORE: %i", score];
scoreLabel.text = scoreString;
}
I put it into one of my voids
-(void)PoopandScore{
if (CGRectIntersectsRect(Poop.frame, toilet.frame)){
[self addfive];
[enemyMovementTimer invalidate];
[self bugpositionenemy];
}
}
so you must be thinking whats the problem? Well when my toilet catches the poop the images all return to there places where they were on the view controller, then go back to where they are supposed to go. If I were to make a professional game I don't want the movement to be glitchy every time you catch a poop. can anyone please help me? I am a bit stuck and find coding very tiring. Thanks!
my position enemy looks like this
-(void)positionEnemy {
// Random enemy position
enemyPosition = arc4random() % 249;
enemyPosition = enemyPosition + 20;
// Set enemy Image location
Poop.center = CGPointMake(enemyPosition, -40);
// Set enemy speed
randomSpeed = speedOfEnemy;
switch (randomSpeed) {
case 0:
speedOfEnemy = 0.005;
break;
case 1:
speedOfEnemy = 0.005;
case 2:
speedOfEnemy = 0.005;
default:
break;
}
if you need me to add any more information don't be afraid to ask me!
Found the answer. Had to turn off auto layout!
I am using SpriteBuilder to make a game. The objective is to destroy some CCSprites. I have 3 sprites on screen and are destroyed by another sprite, so the code must have something to do with when there are no more 'enemy' sprites remaining a next button must show. I have looked on the internet and are inexperienced with Cocos2D coding. Here is the code I have used to get rid of the 'enemy'
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair danald:(CCNode *)nodeA wildcard:(CCNode *)nodeB {
float energy = [pair totalKineticEnergy];
if (energy > 5000.f) {
[self danaldRemoved:nodeA];
}
}
If the object is hit with a certain speed it will call the method below
- (void)danaldRemoved:(CCNode *)Danald {
CCParticleSystem *explosion = (CCParticleSystem *)[CCBReader load:#"Explosion"];
explosion.autoRemoveOnFinish = TRUE;
explosion.position = Danald.position;
[Danald.parent addChild:explosion];
[Danald removeFromParent];
}
Thanks in an advanced, sorry if this question has been asked before but I cannot find it
Well I would suggest this method:
Create a variable where you store the number of sprites left. For example:
int spritesLeft;
And then initialize it to 0:
-(void) didLoadFromCCB{
//REST OF CODE
spritesLeft=3; //3 because you said there are only 3.
}
Now when you call danaldRemoved: method, just subtract 1 to spritesLeft, and check if spritesLeft is equal to 0. If it's true, just call your method to make a button appear:
- (void)danaldRemoved:(CCNode *)Danald {
spritesLeft--; //substract 1
CCParticleSystem *explosion = (CCParticleSystem *)[CCBReader load:#"Explosion"];
explosion.autoRemoveOnFinish = TRUE;
explosion.position = Danald.position;
[Danald.parent addChild:explosion];
[Danald removeFromParent];
//check if game is over.
if (spritesLeft == 0){
[self printButton];
}
}
Now create the method printButton, but before go to SpriteBuilder, create the button and place it where you want. Now uncheck 'Visible' value, and then go to code connections, and select 'Doc root var' (under custom class) and write a name for the button, for example: nextButton. At the selector value write: changeLevel and target: document root
Now declare it at the top of your .m file as you did with any other objects:
CCButton *nextButton;
Method for button (just set visibility ON)
-(void) printButton{
nextButton.visible = YES;
}
And now your method to change level:
-(void) changeLevel{
CCScene *nextLevel = [CCBReader loadAsScene:#"YOUR LEVEL"];
[[CCDirector sharedDirector] replaceScene:nextLevel];
}
Hope this helps!
EDIT: HOW TO DETECT WHEN A SPRITE GOES OFF THE SCREEN
As I said, create any kind of physic object in spritebuilder. For example, I use CCNodeColor. Then make it a rectangle and place it at left of the screen. Now go to physics, enable physics, polygon type and static. Now in connections, select doc root var and call it _leftNode. Now repeat with top,right and bottom and call them _topNode, etc.
Now go to code, declare your new nodes: CCNode *_leftNode; and so...
Now let's make a collision type:
_bottomNode.physicsBody.collisionType = #"_bound";
_leftNode.physicsBody.collisionType = #"_bound";
_rightNode.physicsBody.collisionType = #"_bound";
_topNode.physicsBody.collisionType = #"_bound";
And do the same with your sprite, but I think you have done that before. Let's make an example:
spritename.physicsBody.collisionType = #"_sprite";
So now implement the method:
-(void)ccPhysicsCollisionPostSolve:(CCPhysicsCollisionPair *)pair _sprite:(CCNode *)nodeA _bound:(CCNode *)nodeB {
[_physicsNode removeChild:nodeA cleanup:YES];
}
And that's all.
I'm trying to move all sprites with the same tag some inches to the right.
I have tried 4 different type of expressions in order to do so, but nothing worked. Here is what i ve done so far...
-(void) moveSprites {
NSArray* spritesWithTag = [lh spritesWithTag: BOXES1]
for (LHSprite* spr in spritesWithTag)
(NSLog (#"name is %#", [spr uniqueName]);
CGPoint newposition = ccpSub (ccp(-50,0), [spr position]);
//generating the new position for the elements
[spr transformPosition: newposition];
//first attemp, should work but for some reason it doesn't work
spr.position = newposition;
//2nd attemp
b2Vec2 newpositionVector (newposition.x, newposition.y);
[spr body]->SetTransform(newpositionVector, 0);
//third try
[spr setPosition:newposition];
//last form
}
When i run the app the method call works fine and all sprites with tag BOXES1 appear in the output tab, but its position hasn't changed at all. Any idea over why is it happening. What did I wrong? Is there any other way to move an sprite or are them prevented from moving in some other form i dont know? Those are static sprites, dont know if this affects... thanks!
Hi All
Im just having an issue with particle effects not appearing all the time. Im coding using objective c and cocos2d for the iphone.
Below is the code in question.
CCParticleExplosion *emitter;
emitter = [[CCParticleExplosion alloc] initWithTotalParticles:30];
emitter.texture = [[CCTextureCache sharedTextureCache] addImage:#"particle_bubble.png"];
emitter.position = ccp(MidX,MidY);
emitter.life =0.5;
emitter.duration = 0.5;
emitter.speed = 60;
[self addChild:emitter];
emitter.autoRemoveOnFinish = YES;
////////////////////////////////////////////////////
CCParticleMeteor *emitter2;
emitter2 = [[CCParticleMeteor alloc] initWithTotalParticles:150];
emitter2.texture = [[CCTextureCache sharedTextureCache] addImage:#"fire_particle.png"];
emitter2.position = ccp(MidX,MidY);
emitter2.life = 0.5;
emitter2.duration = 2;
emitter2.speed = 60;
id emitMove = [CCMoveTo actionWithDuration:0.5 position:HUD.moonSprite.position ];
[self addChild:emitter2 z:1];
[emitter2 runAction:[CCSequence actions:emitMove, nil]];
emitter2.autoRemoveOnFinish = YES;
This code is within the same function right after each other as shown.
but sometimes the 2nd particle effect is not created and i cant figure out why. the first particle effect is always created no problems so im sure it is getting into the function correctly but sometimes (almost 50%) the 2nd meteor emitter is not displayed. i have tried messing around with z values to make sure it is not hidden behind an other object and it doesnt appear to be the problem. Anyone have any ideas on why this would be happening?
Thanks
G
I suggest using the 71 squared particle designer. http://particledesigner.71squared.com/
Did the trick for me.
Try this:
Define the emitters in a local variable (.h)
Call this before the code above:
if (emitter.parent == self) {
NSLog(#"em1 released");
[emitter release];
}
if (emitter2.parent == self) {
NSLog(#"em2 released");
[emitter2 release];
}
This checks if the emitter is a child and removes it, so you can remove the emitter.autoRemoveOnFinish so your emitter will show every time