Flipping Sprite In The Update Loop - cocos2d-iphone

I've got a bird sprite that I want to bounce around the screen. So when it reaches the bounds of the screen, the bird will travel back and forth. This is working but I'm not able to flip the sprite each time.It works the first time it moves right and hits the right edge of the screen, and when it comes back and hits the left side, the sprite does not flip. Here's what I'm trying to do
- (void)update:(ccTime)dt
{
if (bird_x > 1550 || bird_x < 0)
{
flip *= -1;
self.bird.flipX = YES;
}
bird_x = bird_x + 10 * flip;
_bird.position = ccp(bird_x, 1000);
}
What am I doing wrong?
Thanks in advance.

It's because the flip is only an on/off state. Replace your self.bird.flipX = YES; line with self.bird.flipX = !self.bird.flipX; and try again.

Related

Slowdown when loading the same SpriteFrame used in an animation in Cocos2dx

I am currently experiencing some heavy slowdowns with my game. I have narrowed it down to something related with texture animations.
In my game there are characters that walk in 1 of 4 possible directions, they will walk up to a point, then change direction and continue walking (sort of like a tower defense game).
First i am loading the sprite frame cache like this
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("characters.plist");
This code is only run once during the life time of my application.
When the characters get loaded to the screen their animation is being set using the following code:
int direction = 0;
int number = 0;
if (this->to_x < 0) // Left
{
direction = 1;
number = 1;
}
else if(this->to_x > 0) // Right
{
direction = 2;
number = 1;
}
if (this->to_y < 0) // Down
{
direction = 0;
number = 0;
}
else if(this->to_y > 0) // Up
{
direction = 3;
number = 2;
}
int s = 0; //skin
// Set the animation
Animation *animation = Animation::create();
for (int i = 0; i < INT16_MAX; i++)
{
string frame_sprite_name = StringUtils::format("%s_%d_%d_%d.png",parameters[name].image_name.c_str(),s,number,i);
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frame_sprite_name);
if (frame) {
animation->addSpriteFrame(frame);
} else {
break;
}
}
// Invert the sprite when they go right
if (direction == 2) {
setFlippedX(true);
}else{
setFlippedX(false);
}
// Set the pace of the animation based on the type
if (name=="runner") {
animation->setDelayPerUnit(0.15f);
} else{
animation->setDelayPerUnit(0.3f);
}
Animate *animate = Animate::create(animation);
this->stopAllActions();
this->runAction(RepeatForever::create(animate));
What this code does is:
Check the direction
Get the sprite frame from the cache based on the direction
Run the action with repeat forever.
However this code is ran every time they change direction to set the new animation of the active characters. Also, at one time I can have around 40-50 of these characters going around.
I've noticed that after a few minutes in the game the slowdown starts to happen as soon as a new "character" is created, (since they are created in rapid succession in waves). And the slowdown also happens when the characters change in direction. So this makes me believe I am using the textures wrong.
If anyone knows how to fix this please let me know.
PD: I was thinking about the possibility of pre-loading all the animations and then just having each of the sprites that represent the characters run the corresponding animation.
You should definitely cache the animation in the AnimationCache with addAnimation and getAnimation methods.

How to set the position of a sprite to the center of the screen

I have some code on a pong game i've been working on:
The code sample shows that when the ball hits the bottom of the window, the ball resets to the middle of the window. What I'm trying to achieve is that I'd like to be able to add some code so that if the ball hits the top of the window, the ball will reset back to the middle.
Can anyone help me with this?
//...
// IF BALL GETS PAST PLAYER PADDLE AND TOUCHES BOTTOM OF SCREEN
if (GetPosition().y - GetHeight()/2 <= 0)
{
_angle = 180 - _angle;
moveByY = -moveByY;
}
if (GetPosition().y + GetHeight()/2 + moveByY >= Game::SCREEN_HEIGHT)
{
// RESET BALL TO MIDDLE OF SCREEN AND RESET TIMER TO 0
GetSprite().SetPosition(Game::SCREEN_WIDTH/2, Game::SCREEN_HEIGHT/2);
_angle = (float)sf::Randomizer::Random(0,360);
_velocity = 220.0f;
_elapsedTimeSinceStart = 0.0f;
}
//...
I figured this out, added some more conditional statements to check the boundary, if the ball hits the top then reset the ball to the middle of the screen.

CCSprite Not Flipping

So in my game I am trying to make the character be able to go left or right depending on the button the player pushes.
I want to flip the sprite so that it faces the right way in whatever direction it is going.
I have a bool as a property of the player class called isGoingLeft and thats how I check when the player is facing left.
The way I flip the player is like this
//IN THE METHOD FOR THE RIGHT BUTTON
if (player.isGoingLeft) {
player.flipX = 180;
NSLog(#"Flip Right");
player.isGoingLeft = FALSE;
}
//IN THE METHOD FOR THE LEFT BUTTON
if (!player.isGoingLeft) {
player.flipX = 180;
player.isGoingLeft = TRUE;
NSLog(#"Flip Left");
}
This works when I start off going right, and then turn left (the sprite flips correctly). But when I try to go right again, the player moves right, it just doesn’t flip again. The NSLog saying that it flipped back to facing right runs and the bool is changed. I have no idea what is going on
flipX is a BOOL type, so any value greater than 0 will make the sprite flipped.
Use this instead:
player.flipX = YES;
player.flipX = NO;

Reverse animation direction when hitting the side of the screen

I am creating a space invaders game for my university assignment. I am breaking the parts down on paper, I thought a good place to start would be to move the sprites across the screen. The issue I have at the moment is this, when the sprite his the right hand side of the screen it would just carry on moving, so I added this code:
if (invadersSprite.getPosition().x > 650)
{
std::cout << "WIDTH_END" << std::endl;
}
I basically used this for debugging for future reference. The output popped up into the console so I knew I was onto something. So, I started moving on from the output to actually moving the sprites back to the left hand side of the screen. I am now having more issues then expected.
I declared some ints for up, left, right and down just for easability when it comes to reading the code.
int spriteWalkSpeed = 50;
int up=-spriteWalkSpeed, down=spriteWalkSpeed, left=-spriteWalkSpeed, right=spriteWalkSpeed;
I've tried using the SFML move commands and also setPosition, but none of them really work as I thought they should.
move:
The issue I have had with this one is it basically stops in the middle of the screen. It still animates the leg movement and such, but it doesn't move left or right.
if (invadersSprite.getPosition().x > 650)
{
invadersSprite.move(left, 00);
}
setPosition:
This is a little closer to what I am after, but still no cigar. The movement pauses for around a second and then pops up at the left hand side of the screen. What I need is to move back down the screen.
if (invadersSprite.getPosition().x > 650)
{
invadersSprite.setPosition(left, 00);
}
I haven't been using SFML for very long so I am a little puzzled by this.
EDIT
At the moment the sprite is moving to the right of the screen, as needed:
if(spriteTimer>delay)
{
invadersSprite.setTextureRect(area);
++count;
invadersSprite.move(right,0);
if(count==SPRITECOLS) //WE HAVE MOVED OFF THE RIGHT OF THE IMAGE
{
area.left=0; //reset texture rect at left
count=0; //reset count
}
else
{
area.left+=spaceWidth; //move texture rect right
}
spriteTimer=0; //we have made one move in the sprite tile - start timing for the next move
}
Your current logic will only move the sprite left once if the x-coord is greater than 650 - but that's not exactly what you want. What you want is for the sprite to continuously move left after reaching the edge.
To do this you'll need to keep track of a current velocity for your sprite. For example, when your sprite starts, it will be moving right:
xVelocity = right;
Then you can have 2 conditions that will switch direction (when hitting edges of screen):
if (invaderSprite.getPosition().x >= screenWidth) {
// hit the right side of screen
xVelocity = left;
} else if (invaderSprite.getPosition().x <= 0) {
// hit the left side of screen
xVelocity = right;
}
Now, on ever game tick, you simply move your sprite according to its current velocity:
invaderSprite.move(xVelocity, yVelocity);
There are some other things that will need to be fixed, like taking the width of the sprite into consideration, changing the y velocity, etc., but this is the main idea.

Make sprite bounce back

I'm playing a little around with DirectX 9.0 and want a object to bounce back when it hits the screen edges (top,bottom,right and left). The sprite is an image that is 128x128 pixels.
I manage to make it bounce back and forth, but this does not happend before the image is either half outside the screen, or too early. This is because the object it self is in the middle of the image, is there anyway to "remove" the background part so the program does not bounce back the sprite before the image part itself collides with the screen edge?
Do I have to modify the image manually? Like cropping it or something=
Here is some of the code I'm working with:
if(this->Textures[i].posision.x >= this->_screenWidth)
{
this->Textures[i].right = false;
}
else if(this->Textures[i].posision.x <= 0)
{
this->Textures[i].right = true;
}
if(!this->Textures[i].right)
this->Textures[i].posision.x -= 0.3f;
else
this->Textures[i].posision.x += 0.3f;
Thanks for any help!
well, if you're travelling with a left-ward vector, a collision would be qualified as:
if(this->Textures[i].posision.x - 128/2 <= 0)
{
this->Textures[i].right = true;
}
if your position.x and position.y refer to the centre of the image, then all you have to do is add/subtract half the image size to get the bounds of your image.
If your sprite isn't filling up your image, then you should probably crop some of it out.