Jump to content
  • Advertisement
Sign in to follow this  
LeftyGuitar

SDL2 and Box2D Nothing Shows Up

This topic is 642 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

 

So I got the code up and running. It runs and compiles, however it only shows a blank window. Nothing shows up on the screen. I can't figure out why nothing is showing up on the screen. It should at least show a basic rectangle show up.

EDIT: OK I managed to get a blue sky as the background and a green square to show up in the top left corner. However, it doesn't do anything, it just sits there idle. It should be doing something, since physics is being applied to it. I've posted the updated code.

 

EDIT 2: OK I got it to work. However, the square falls down the screen very slowly. I assume I'll have to adjust the values to change the speed. Any reccomendations is still welcomed to the code.

 

EDIT 3: OK I got it to speed up, however when it reaches the bottom of the screen, it keeps going, it doesn't bounce or stop. It disappears from the screen once it reaches the bottom.

 

EDIT 4: Ok I forgot to draw the ground, now the ground is showing up, but the square doesn't interact with the ground, it still falls through, I'm not sure why this is. Any help would be appericated.

#include <stdlib.h>
#include <stdio.h>

#include <iostream>

#include "Box2D\Box2D.h"
#include "SDL.h"

using namespace std;

#define PTM_RATIO 32.0

SDL_Window* GameWin;
SDL_Renderer* GameRen;
SDL_Event event;

int Width = 1280, Height = 720;
bool GameRunning = true;

SDL_Rect box;
SDL_Rect ground;

int box_x, box_y, box_w, box_h;
int ground_x, ground_y, ground_w, ground_h;

int main(int argc, char* argv[])
{
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        exit(0);
    }

    GameWin = SDL_CreateWindow("SDL Physics", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Width, Height, SDL_WINDOW_SHOWN);
    GameRen = SDL_CreateRenderer(GameWin, -1, SDL_RENDERER_PRESENTVSYNC);

    box_x = 0, box_y = 0;
    box_w = 50, box_h = 50;

    box.x = box_x, box.y = box_y;
    box.w = box_w, box.h = box_h;

    ground_x = 0, ground_y = 540;
    ground_w = 800, ground_h = 560;

    ground.x = ground_x, ground.y = ground_y;
    ground.w = ground_w, ground.h = ground_h;

    b2Vec2 gravity(0, 98.8f);
    bool doSleep = true;

    b2World* World;
    World = new b2World(gravity);
    World->SetGravity(gravity);

    b2Body* groundBody;
    b2BodyDef groundBodyDef;
    groundBodyDef.type = b2_staticBody;
    groundBodyDef.position.Set((float)ground_x, (float)ground_y);
    groundBody = World->CreateBody(&groundBodyDef);

    b2Body* Body;
    b2BodyDef ballBodyDef;
    ballBodyDef.type = b2_dynamicBody;
    b2Vec2 ballVector;
    ballVector.Set(10, 10);
    ballBodyDef.angularVelocity = 0.0f;
    ballBodyDef.linearVelocity = ballVector;

    ballBodyDef.position.Set(0, 0);
    ballBodyDef.awake = true;
    Body = World->CreateBody(&ballBodyDef);

    b2PolygonShape groundBox;
    b2FixtureDef boxShapeDef;
    boxShapeDef.shape = &groundBox;
    boxShapeDef.density = 2.0f;
    boxShapeDef.restitution = 0.5f;
    groundBox.SetAsBox(0, (float)ground_w);

    groundBody->CreateFixture(&groundBox, 0);

    b2PolygonShape dynamicBox;

    dynamicBox.SetAsBox(10.0f, 10.0f);

    b2FixtureDef fixtureDef;

    fixtureDef.shape = &dynamicBox;

    fixtureDef.density = 2.0f;
    fixtureDef.friction = 1.0f;
    fixtureDef.restitution = 0.5f;

    Body->CreateFixture(&fixtureDef); //this line

    float timeStep = 1.0f / 300.0f;

    int velIter = 1.0;
    int posIter = 1.0;
    World->Step(timeStep, velIter, posIter);

    b2Vec2 pos = Body->GetPosition();
    float an = Body->GetAngle();

    cout << "X:" << pos.x << endl;
    cout << "Y:" << pos.y << endl;

    while (GameRunning)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
            {
                GameRunning = false;
            }

            if (event.type == SDL_KEYDOWN)
            {
                if (event.key.keysym.sym == SDLK_ESCAPE)
                {
                    GameRunning = false;
                }
            }
        }

        //SDL_RendererFlip flip = SDL_FLIP_NONE;

        World->Step(timeStep, velIter, posIter);

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

        box.x = pos.x;
        box.y = pos.y;

        SDL_SetRenderDrawColor(GameRen,0, 255, 255, 0);

        SDL_RenderClear(GameRen);

        SDL_SetRenderDrawColor(GameRen, 0, 255, 0, 0);
        SDL_RenderFillRect(GameRen, &box);
        SDL_SetRenderDrawColor(GameRen, 255, 0, 0, 0);
        SDL_RenderFillRect(GameRen, &ground);

        //SDL_RenderCopyEx(GameRen, NULL, NULL, &box, angle, NULL, flip);

        SDL_RenderPresent(GameRen);
    }

    SDL_DestroyWindow(GameWin);
    SDL_DestroyRenderer(GameRen);

    SDL_Quit();

    return 0;
}
Edited by LeftyGuitar

Share this post


Link to post
Share on other sites
Advertisement

Maybe your should start with SDL and get some basic movement working before using a physics engine. Using a physics engine require lots of understanding in order to integrate the game logic in a fluent way so trying to make your own physics first will give you a better understanding of what the engine does by stepping in a debugger or even calculating examples on paper. Reading about euler forward and midpoint is a good start.

I do not see any code for either dynamic timestep nor interpolated fixed timesteps. You can make a button that slows everything down with a delay or heavy calculation to see what happens when your game scales up or someone plays it on a slower computer. The easy way is to run the physics 300 steps per second and run as many as required for the time spent rendering one frame and save the remainder time accumulated for the next frame. All physics and game logic can then run the same way independent of rendering speed. Everything that is just visual and can be directly derived from the world state (animations, GUI,...) should be updated as needed before rendering to avoid getting more fixed amount of workload than the computer can handle.

Share this post


Link to post
Share on other sites

Well I've used SDL a lot. So I know how it works. Its mostly getting Box2D to work with it. I am trying things. Also, this is more of a quick test to get SDL and Box2D working together.

Share this post


Link to post
Share on other sites

OK, I made some changes to the code and added an image. However it is still falling past the bottom of the screen. It is not interacting or bouncing off the ground as it should be. Here is the updated code.

#include <stdlib.h>
#include <stdio.h>

#include <iostream>

#include "Box2D\Box2D.h"
#include "SDL.h"

using namespace std;

#define PTM_RATIO 32.0

SDL_Window* GameWin;
SDL_Renderer* GameRen;
SDL_Event event;

int Width = 800, Height = 600;
bool GameRunning = true;

SDL_Rect box;
SDL_Rect ground;
SDL_Surface* Ball;
SDL_Texture* Tex;
SDL_Point center;

int box_x, box_y, box_w, box_h;
int ground_x, ground_y, ground_w, ground_h;

int main(int argc, char* argv[])
{
	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		exit(0);
	}

	GameWin = SDL_CreateWindow("SDL Physics", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Width, Height, SDL_WINDOW_SHOWN);
	GameRen = SDL_CreateRenderer(GameWin, -1, SDL_RENDERER_PRESENTVSYNC);

	box_x = 0, box_y = 0;
	box_w = 10, box_h = 10;

	box.x = box_x, box.y = box_y;
	box.w = box_w, box.h = box_h;

	ground_x = 0, ground_y = 540;
	ground_w = 800, ground_h = 560;

	ground.x = ground_x, ground.y = ground_y;
	ground.w = ground_w, ground.h = ground_h;

	Ball = SDL_LoadBMP("ball.bmp");
	Tex = SDL_CreateTextureFromSurface(GameRen, Ball);

	center.x = box.w * 0.5f;
	center.y = box.h - (box.w * 0.5);

	b2Vec2 gravity(0, 9.8f);
	bool doSleep = true;

	b2World* World;
	World = new b2World(gravity);
	World->SetGravity(gravity);

	b2Body* groundBody;
	b2BodyDef groundBodyDef;
	groundBodyDef.type = b2_staticBody;
	groundBodyDef.position.Set((float)ground_x, (float)ground_y);
	groundBody = World->CreateBody(&groundBodyDef);

	b2Body* Body;
	b2BodyDef ballBodyDef;
	ballBodyDef.type = b2_dynamicBody;
	b2Vec2 ballVector;
	ballVector.Set(10, 10);
	ballBodyDef.angularVelocity = 0.0f;
	ballBodyDef.linearVelocity = ballVector;

	ballBodyDef.position.Set(0, 0);
	ballBodyDef.awake = true;
	Body = World->CreateBody(&ballBodyDef);

	b2PolygonShape groundBox;
	b2FixtureDef boxShapeDef;
	boxShapeDef.shape = &groundBox;
	boxShapeDef.density = 2.0f;
	boxShapeDef.restitution = 0.5f;
	groundBox.SetAsBox(0,800);

	groundBody->CreateFixture(&groundBox, 0);

	b2PolygonShape dynamicBox;

	dynamicBox.SetAsBox(10.0f, 10.0f);

	b2FixtureDef fixtureDef;

	fixtureDef.shape = &dynamicBox;

	fixtureDef.density = 2.0f;
	fixtureDef.friction = 1.0f;
	fixtureDef.restitution = 0.5f;

	Body->CreateFixture(&fixtureDef); //this line

	float timeStep = 1.0f / 100.0f;

	int velIter = 1.0;
	int posIter = 1.0;
	World->Step(timeStep, velIter, posIter);

	b2Vec2 pos = Body->GetPosition();
	float an = Body->GetAngle();

	cout << "X:" << pos.x << endl;
	cout << "Y:" << pos.y << endl;

	while (GameRunning)
	{
		while (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
			{
				GameRunning = false;
			}

			if (event.type == SDL_KEYDOWN)
			{
				if (event.key.keysym.sym == SDLK_ESCAPE)
				{
					GameRunning = false;
				}

				if (event.key.keysym.sym == SDLK_LEFT)
				{
					Body->SetTransform(b2Vec2(-1, 0), 1);
				}
				else if (event.key.keysym.sym == SDLK_RIGHT)
				{
					Body->SetTransform(b2Vec2(+1, 0), 1);
				}
			}
		}


		World->Step(timeStep, velIter, posIter);

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

		box.x = pos.x;
		box.y = pos.y;

		box.x = angle; // How to rotate the image?
		box.y = angle;

		SDL_SetRenderDrawColor(GameRen,0, 255, 255, 0);

		SDL_RenderClear(GameRen);

		//SDL_SetRenderDrawColor(GameRen, 0, 255, 0, 0);
		//SDL_RenderFillRect(GameRen, &box);

		SDL_RendererFlip Flip = SDL_FLIP_NONE;

		SDL_RenderCopyEx(GameRen, Tex, NULL, &box, angle, &center, Flip);

		SDL_SetRenderDrawColor(GameRen, 255, 0, 0, 0);
		SDL_RenderFillRect(GameRen, &ground);

		SDL_RenderPresent(GameRen);
	}

	SDL_DestroyWindow(GameWin);
	SDL_DestroyRenderer(GameRen);

	SDL_Quit();

	return 0;
}

Share this post


Link to post
Share on other sites
I would try to assert that the ground is where it is expected to be by visualizing and making ray intersections. If you can make primitive line drawing of the physical world for debugging then it can help a lot when figuring these things out. A lot of physics engines provide some kind of line drawing callback to visualize with any graphics engine.

Share this post


Link to post
Share on other sites

OK I figured it out. The problem was rather simple. I had the value in the wrong place.

#include <stdlib.h>
#include <stdio.h>

#include <iostream>

#include "Box2D\Box2D.h"
#include "DebugDraw.h"
#include "SDL.h"

using namespace std;

#define PTM_RATIO 32.0

SDL_Window* GameWin;
SDL_Renderer* GameRen;
SDL_Event event;

int Width = 800, Height = 600;
bool GameRunning = true;

SDL_Rect box;
SDL_Rect ground;
SDL_Surface* Ball;
SDL_Texture* Tex;
SDL_Point center;

int box_x, box_y, box_w, box_h;
int ground_x, ground_y, ground_w, ground_h;

int main(int argc, char* argv[])
{
	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		exit(0);
	}

	GameWin = SDL_CreateWindow("SDL Physics", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Width, Height, SDL_WINDOW_SHOWN);
	GameRen = SDL_CreateRenderer(GameWin, -1, SDL_RENDERER_PRESENTVSYNC);

	box_x = 0, box_y = 0;
	box_w = 10, box_h = 10;

	box.x = box_x, box.y = box_y;
	box.w = box_w, box.h = box_h;

	ground_x = 0, ground_y = 540;
	ground_w = 800, ground_h = 560;

	ground.x = ground_x, ground.y = ground_y;
	ground.w = ground_w, ground.h = ground_h;

	Ball = SDL_LoadBMP("ball.bmp");
	Tex = SDL_CreateTextureFromSurface(GameRen, Ball);

	center.x = box.w * 0.5f;
	center.y = box.h - (box.w * 0.5);

	b2Vec2 gravity(0, 9.8f);
	bool doSleep = true;

	b2World* World;
	World = new b2World(gravity);
	World->SetGravity(gravity);

	b2Body* groundBody;
	b2BodyDef groundBodyDef;
	groundBodyDef.type = b2_staticBody;
	groundBodyDef.position.Set((float)ground_x, (float)ground_y);
	groundBody = World->CreateBody(&groundBodyDef);

	b2Body* Body;
	b2BodyDef ballBodyDef;
	ballBodyDef.type = b2_dynamicBody;
	b2Vec2 ballVector;
	ballVector.Set(10, 10);
	ballBodyDef.angularVelocity = 0.0f;
	ballBodyDef.linearVelocity = ballVector;

	ballBodyDef.position.Set(0, 0);
	ballBodyDef.awake = true;
	Body = World->CreateBody(&ballBodyDef);

	b2PolygonShape groundBox;
	b2FixtureDef boxShapeDef;
	boxShapeDef.shape = &groundBox;
	boxShapeDef.density = 2.0f;
	boxShapeDef.restitution = 0.5f;
	groundBox.SetAsBox(800,0); //This is what I needed to fix. Orignally it was (0,800)

	groundBody->CreateFixture(&groundBox, 0);

	b2PolygonShape dynamicBox;

	dynamicBox.SetAsBox(10.0f, 10.0f);

	b2FixtureDef fixtureDef;

	fixtureDef.shape = &dynamicBox;

	fixtureDef.density = 2.0f;
	fixtureDef.friction = 1.0f;
	fixtureDef.restitution = 0.5f;

	Body->CreateFixture(&fixtureDef); //this line

	float timeStep = 1.0f / 100.0f;

	int velIter = 1.0;
	int posIter = 1.0;
	World->Step(timeStep, velIter, posIter);

	b2Vec2 pos = Body->GetPosition();
	float an = Body->GetAngle();

	cout << "X:" << pos.x << endl;
	cout << "Y:" << pos.y << endl;

	while (GameRunning)
	{
		while (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
			{
				GameRunning = false;
			}

			if (event.type == SDL_KEYDOWN)
			{
				if (event.key.keysym.sym == SDLK_ESCAPE)
				{
					GameRunning = false;
				}

				if (event.key.keysym.sym == SDLK_LEFT)
				{
					Body->SetTransform(b2Vec2(-1, 0), 1);
				}
				else if (event.key.keysym.sym == SDLK_RIGHT)
				{
					Body->SetTransform(b2Vec2(+1, 0), 1);
				}
			}
		}


		World->Step(timeStep, velIter, posIter);

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

		box.x = pos.x;
		box.y = pos.y;

		SDL_SetRenderDrawColor(GameRen,0, 255, 255, 0);

		SDL_RenderClear(GameRen);

		//SDL_SetRenderDrawColor(GameRen, 0, 255, 0, 0);
		//SDL_RenderFillRect(GameRen, &box);

		SDL_RendererFlip Flip = SDL_FLIP_NONE;

		SDL_RenderCopyEx(GameRen, Tex, NULL, &box, angle, &center, Flip);

		SDL_SetRenderDrawColor(GameRen, 255, 0, 0, 0);
		SDL_RenderFillRect(GameRen, &ground);

		SDL_RenderPresent(GameRen);
	}

	SDL_DestroyTexture(Tex);
	SDL_FreeSurface(Ball);

	SDL_DestroyWindow(GameWin);
	SDL_DestroyRenderer(GameRen);

	SDL_Quit();

	return 0;
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!