0
\$\begingroup\$

I already have some expirience using SDL2 so I thought I will add a Physic Engine to my game - I chose Box2D.

I managed to setup everything and to build a small program using SDL2 and Box2D. But now I have come along on two problems I am not able solve:

Firstly, somehow I am not able to convert my pixels to the MKS unit - I always get nearly no output or the collision detection doesn't work anymore. I have commented out the parts where I would normally use the translation to MKS, maybe someone has a clue why it is'nt working.

Secondly, my collision detection doesn't work proberly if an object collides in an angle (e.g. spinned to 45 degrees):

This is how the Box collides without any angle - this works.

normal collision without angle

But as said if I rotate the box, it doesn't collide properly e.g. it keeps "standing" like this and sometimes even "glitches" forward a little bit:

false collision

I guess this isn't normal? Shouldn't the box "stand up"? I think this is due the fact I am not able to convert to MKS? Also I set my gravity to 100.81 since with 9.81 everything is so slow.

Thanks for any help! Here is my code:

#include "GameLoop.h"
#include "Assets.h"
#include "EventHandler.h"

#include <iostream>
#include <iomanip>
#include <Box2D/Box2D.h>

#define FAILED_TO_CREATE_TEXTURE 0x05

using namespace std;

const float P2M = 30;
const float M2P = 1 / P2M;

b2World* world;

int gameLoop(SDL_Window *window, SDL_Renderer *renderer)
{    
    SDL_Surface* tmp_sprites;
    tmp_sprites = IMG_Load("assets/box.png");
    if(!tmp_sprites)
        return FAILED_TO_CREATE_TEXTURE;

    SDL_Texture* texture_box = SDL_CreateTextureFromSurface(renderer, tmp_sprites);
    SDL_FreeSurface(tmp_sprites);

    bool close_game = false;
    SDL_Event event;

    // parameters of the ground platform rectangle (in pixels)
    float x_pos_rect = 0.0f; 
    float y_pos_rect = 219.9f;
    float width_rect = 320;
    float height_rect = 5;

    // parameters of the falling box (in pixels)
    float x_pos_box = 0;
    float y_pos_box = 0;
    float width_box = 10
    float height_box = 10;

    // Rect to draw platform
    SDL_Rect ground;
    ground.x = x_pos_rect;
    ground.y = y_pos_rect;
    ground.w = width_rect;
    ground.h = height_rect;

    // Rect for a small box to spawn
    SDL_Rect box;
    SDL_Point center; 
    box.x = x_pos_box;
    box.y = y_pos_box;
    box.w = width_box;
    box.h = height_box;
    center.x = (box.w * 0.5f);// P2M * (box.w * 0.5f);
    center.y = (box.h - (box.w * 0.5)); // P2M * (box.h - (box.w * 0.5));

    world = new b2World(b2Vec2(0.0f, 9.81f));
    world->SetAllowSleeping(false);

    b2Body *groundBody;

    b2BodyDef groundBodyDef;
    groundBodyDef.type = b2_staticBody;
    groundBodyDef.position.Set(x_pos_rect, y_pos_rect);// groundBodyDef.position.Set(x_pos_rect * P2M, y_pos_rect * P2M);
    groundBodyDef.angle = 0;
    groundBody = world->CreateBody(&groundBodyDef);

    b2PolygonShape groundBox;
    groundBox.SetAsBox(width_rect, 5); // groundBox.SetAsBox(P2M * (width_rect / 2), P2M * (height_rect / 2)); 

    b2FixtureDef boxShapeDef;
    boxShapeDef.shape = &groundBox; 
    boxShapeDef.density = 0.0f;
    groundBody->CreateFixture(&groundBox, 0);

    b2Body* Body;

    b2BodyDef ballBodyDef;
    ballBodyDef.type = b2_dynamicBody;
    ballBodyDef.angle = 0.0f;
    ballBodyDef.position.Set(200, 40); // ballBodyDef.position.Set(200 * P2M, 40 * P2M);

    Body = world->CreateBody(&ballBodyDef);


    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox((width_box / 2), (height_box / 2));// dynamicBox.SetAsBox((width_box / 2) * P2M, (height_box / 2) * P2M);

    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicBox; 
    fixtureDef.density = 1; 
    fixtureDef.friction = 0.3f; 
    fixtureDef.restitution = 0.5f; 
    Body->CreateFixture(&fixtureDef);

    while(close_game != true)
    {
        keyboardEventHandler(character, close_game, event, Body);

        b2Vec2 pos = Body->GetPosition(); // Body = Body from box
        float angle = Body->GetAngle();

        box.x = pos.x; // * M2P;
        box.y = pos.y; // * M2P;
        //box.w *= M2P;
        //box.h *= M2P;

        //ground.x *= M2P;
        //ground.y *= M2P;
        //ground.w *= M2P;
        //ground.h *= M2P;

        //center.x *= M2P;
        //center.y *= M2P;

        SDL_RenderClear(renderer);

        // Draws our little box                             rotate
        //                                                    |
        SDL_RenderCopyEx(renderer, texture_box, NULL, &box, angle, &center, SDL_FLIP_NONE);

        // Draws ground platform
        SDL_SetRenderDrawColor(renderer, 255, 255, 0, 0);
        SDL_RenderFillRect(renderer, &ground);

        // Show everything
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
        SDL_RenderPresent(renderer);

        world->Step(1.0f / 60.0f, 6, 2.0f); // update

    }

    delete world;

    return 1;
}

I googled a lot but I couldn't find any useful information. I was going through the tutorial by iforce2d and read the documentation but I couldn't figure it out..

\$\endgroup\$
  • \$\begingroup\$ Your question may need a bit of work. But, as a general guideline, I would suggest getting the Box2D test bed to run on your machine. Have a look at the code there. I also find that implementing a Debug Drawer to be most helpful in these kind of situations. \$\endgroup\$ – Willem Sep 17 at 14:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.