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;
Related
Does anyone have a better way to constrain a child of a QGraphicsItem to a scene?
I have successfully properly constrained a parent QGraphicsItem to its scene by overriding itemChange, but now I need to do the same for the child QGraphicsItem.
Example Use-case:
This code works... for the most part. The only problem is the QGraphicsItem's velocity when hitting either side will affect its endstop position:
QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change,
const QVariant &value)
{
QPointF newPos = value.toPointF();
if (change == ItemPositionChange)
{
if(scene())
{
newPos.setY(pos().y()); // Y-coordinate is constant.
if(scenePos().x() < 0 ) //If child item is off the left side of the scene,
{
if (newPos.x() < pos().x()) // and is trying to move left,
{
newPos.setX(pos().x()); // then hold its position
}
}
else if( scenePos().x() > scene()->sceneRect().right()) //If child item is off the right side of the scene,
{
if (newPos.x() > pos().x()) //and is trying to move right,
{
newPos.setX(pos().x()); // then hold its position
}
}
}
}
return newPos;
}
For the parent item, I used:
newPos.setX(qMin(scRect.right(), qMax(newPos.x(), scRect.left())));
which worked perfectly, but I'm stumped as to how or if I could use that here.
First, to be specific, scenes effectively have no boundaries. What you're trying to do is constrain the item to the scene rectangle that you've set elsewhere.
The problem I see is in your use of scenePos. This is an ItemPositionChange; the item's scenePos hasn't been updated with the new position yet, so when you check for scenePos being out of the scene rect, you're really checking the result of the last position change, not the current one. Because of that, your item ends up just off the edge of the scene rectangle and then sticks there. How far off the edge depends on how fast you were moving the mouse, which dictates how much distance there is between ItemPositionChange notifications.
Instead, you need to compare the new position to the scene rectangle and then restrict the value that gets returned to be within the scene rectangle. You need the new position in scene coordinates to do the comparison, so you need something like:
QPoint new_scene_pos = mapToScene (new_pos);
if (new_scene_pos.x() < scene()->sceneRect().left())
{
new_scene_pos.setX (scene()->sceneRect().left());
new_pos = mapFromScene (new_scene_pos);
}
This isn't complete code, obviously, but these are the conversions and checks you need to do to keep it in on the left side. The right side is very similar, so just use the new_scene_pos for the comparison there.
Note that I didn't assume that the left edge of sceneRecT is at 0. I'm sure that's what you coded where you set the sceneRect, but using the actual left value rather than assuming it's 0 eliminates any problems if you end up later changing the range of scene coordinates you're planning to work with.
I used "left" instead of "x" on the sceneRect call just because it parallels using "right" for the other side. They're exactly the same, but I think it reads slightly better in this case.
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.
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.
I am creating a 2D Mario game.
The following function is intended to update a player's position when a particular key is pressed. The player is allowed to move left and right, and jump in the same place, or jump to the left or to the right (to form like an arc).
bool updatePlayerPosition(Movement* mov){
if (this->keyPressed(SDLK_RIGHT)) {
mov->applyForce(1); // Changes the velocity in X
}
if (this->keyPressed(SDLK_LEFT)) {
mov->applyForce(-1); // Changes the velocity in X
}
if (this->keyPressed(SDLK_SPACE)) {
mov->jump(); // Changes the velocity in Y
}
if (this->keyPressed(SDLK_DOWN)) {
mov->fallDown(); // Changes the velocity in X and Y
}
Point* pos = mov->getPosition();
// Check whether the position is out of bounds
if(Level::allowsMove(pos)){
// If it is not, I update the player's current position
position->x = pos->x;
position->y = pos->y;
return true;
}
// If the movement is not allowed, I don't change the position
else {
mov->setPosition(*position);
return false;
}
}
Here is the bug: when I hit the end of the level (which has a fixed width), and if I try to move right and jump at the same time, the player jumps and stays in the air. Only when I release the space bar does the Player come to the ground.
How can I fix this?
For your game, I think you only want the player to jump whenever space is pressed and when the player is on the floor. You must then check if the player is on the floor to have the desired behavior.
I suggest you device a mechanism like this:
if (this->keyPressed(SDLK_SPACE) && this->isOnTheFloor()) {
^^^^^^^^^^^^^^^^^^^^^^^
mov->jump(); // Changes the velocity in Y
}
Your spacebar handler should only apply force one time - on key down, or up, if you prefer, not every frame. On spacebar down, velocity 'up' should be set to some (likely constant) value. Then every frame, if not on the ground, velocity down should be increase a specified amount, with a maximum speed. So OnSpacebarDown, YVelocity = 10.0; and for each frame if(!bGrounded) YVelocity -= 1.0;
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.