box2d falling while moving - c++

Hey my player isn't falling while I'm pressing any of movement inputs while I'm falling. Just stands still and moves right or left.
Just watch the video; Video
My movement code;
if (right == true) {
p_pBody.body->SetLinearVelocity(b2Vec2(5, 0));
}
else
{
p_pBody.rect.setPosition(p_xPos * s_METPX, p_yPos * s_METPX); // Set The SFML Graphics
}
if (left == true) {
p_pBody.body->SetLinearVelocity(b2Vec2(-5, 0));
}
else
{
p_pBody.rect.setPosition(p_xPos * s_METPX, p_yPos * s_METPX); // Set The SFML Graphics
}

You're setting the vertical velocity to 0 when you're pressing right or left. That's the second coordinate of b2Vec2. If you want to have gravity, replace that zero with the vertical velocity the block has when the buttons are not being pressed.

Related

Set linear velocity of a moving box2d object ( own velocity + player velocity )

I'm just trying to program a game with Box2D/ SDL2 & C++. Unfortunately, I am not really getting on with a problem. In the game there are boxes (b2_dynamicBody) that are generated at the click of a mouse. These then fall down. The character is in the middle and when it is moved I create speed X and Y with
m_pCamera->SetLinearVelocity(b2Vec2(z.B. x = 0.0f, y = 10.0f));
I then add within the game loop to any speed of my own box the speed of the character.
ObjectIterator>SetLinearVelocity(ObjectIterator->GetLinearVelocity() + m_pCamera->GetLinearVelocity());
Unfortunately, there are always funny results and I don't know exactly where I need to look.
When I move the player the falling boxes velocity is slowing down!
Here is a source code excerpt :
for (boxit = m_pBoxList.begin(); boxit != m_pBoxList.end(); boxit++) {
if ((*boxit)->getBody()->GetType() == b2_kinematicBody) {
(*boxit)->getBody()->SetLinearVelocity(b2Vec2(0,0));
}
if((*boxit)->getBody()->GetType() == b2_dynamicBody && m_pCamera->getBody()->GetLinearVelocity().x != 0.0f) {
(*boxit)->getBody()->SetLinearVelocity(m_pCamera->getBody()->GetLinearVelocity());
}
else {
(*boxit)->getBody()->SetLinearVelocity(b2Vec2((*boxit)->getBody()->GetLinearVelocity().x + m_pCamera->getBody()->GetLinearVelocity().x, (*boxit)->getBody()->GetLinearVelocity().y + m_pCamera->getBody()->GetLinearVelocity().y));
}
(*boxit)->Update();
(*boxit)->Render();
(*boxit)->RenderOutline();
if ((*boxit)->getBody()->GetLinearVelocity().y == 0.0f) {
(*boxit)->getBody()->SetType(b2_kinematicBody);
}
}
Screenshot:
screenshot / error description

Moving sprites in a vector

I move sprites stored in a formationvector by holding the mousebutton. Problem is: Whenever i move the sprite onto another one, i move both sprites at the same time.
What i want: Moving the sprite1 over the other sprites2 without changing the position of sprite 2 or with other words:
-Testing in a loop if a sprite of a vector is clicked on
-If sprite is clicked on:
Move this sprite around while button is pressed but somehow stop this move while this movement in order to avoid moving more than this one sprite.
Here is my try so far:
while (App.pollEvent(Event))
{
// Window closed
if (Event.type == sf::Event::Closed)
{
return (-1);
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
for (size_t k = 0; k < formation.size(); k++)
{
if (isMouseOver(formation[k], App) == true)
{
Mouseposition = sf::Vector2f(sf::Mouse::getPosition(App));
Mouseposition.x = Mouseposition.x - formation[k].getLocalBounds().width / 2;
Mouseposition.y = Mouseposition.y - formation[k].getLocalBounds().height / 2;
formation[k].setPosition(sf::Vector2f(Mouseposition));
Formation_playernames.clear();
Formation_playerinformation.clear();
Formation_Playernames(Font, Formation_playernames, formation, playerlist);
Formation_Playerinformation(Font, Formation_playerinformation, formation, playerlist);
}
}
}
}
The Formation-functions store the correct new positions of the sprites and their colors based on the positions into the formation vector
The problem is the for-loop, i could do it without but that would lead to a much longer code. How could i do it ?
Instead of simply checking whether or not the mouse button is pressed, you should structure your code so you can check exactly when the button is pressed, and when it is released. You can then structure your code such that different presses of the button are distinguished from each other. semi-pseudocode follows
bool button_is_pressed = false;
Sprite* currently_selected_sprite = nullptr;
// main application loop
while (...)
{
...
// other application logic
...
if (!button_is_pressed)
{
if (CheckIfButtonIsPressed())
{
button_is_pressed = true;
// Button was just pressed.
// Select the appropriate sprite by checking
// the mouse coordinates against the positions
// of the sprites.
}
else
{
// Button not being pressed.
// Likely no logic needed here.
}
}
else // button_is_pressed == true
{
if (CheckIfButtonIsPressed())
{
// Button is being held down.
// Implement dragging logic using the
// pointer to the selected sprite.
}
else
{
button_is_pressed = false;
// Button was just released.
// Deselect the sprite.
currently_selected_sprite = nullptr;
}
}
}
Alternatively, you could handle mouse events, which will take care of much of this logic for you. http://sfml-dev.org/documentation/2.0/classsf_1_1Event.php
In a more English like pseudo code, this is what your function is doing:
if the mouse button is currently pressed
move all the sprites which are under the mouse to be centered on the mouse cursor
else
do nothing
This is what I'm suggesting
at the moment the mouse button is pressed down
select the sprite which is under the mouse cursor
at the moment the mouse button is released
deselect the selected sprite
if the mouse button is currently pressed, and a sprite is selected
move the selected sprite to the position of the mouse cursor

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.

Game jump logic

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;

Flipping Sprite In The Update Loop

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.