Had time to test your code, and its great! I threw box2d physics in there and the camera lags behind the player. any idea on how to fix this?
I was mainly thinking about this line:
camera.x = (Player.x) - wWidth / 2;
In your code you did this before updating the player coordinates which essentially means the camera will lag one frame behind. In the code that I posted I instead did it afterwards which should fix this issue. Note that we’re just talking about one frame so this should be barely noticeable. If the camera lags behind more then there is probably some other explanation.
Tried that and it does work, but box2d object stutters. any ideas
Actually nvm i figured it out within your code! Turns out i had a object that was not suppose scroll with the camera was the issue!! Cant thank you guys enough!!
For anyone who wants to use box2d within sdl2 within the camera smooth scrolling.
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <box2d/box2d.h>
#undef main
int LEVEL_WIDTH;
int LEVEL_HEIGHT;
int wWidth;
int wHeight;
//float camSpeed; ///Not Needed
//float playerSpeed = 1000; /// Only if Player.x is not attactched to box.x, see below the int main function.
double OldTime = 0.0;
double NewTime = 0.0;
double DeltaTime = 0.0;
double Lifetime = 0.0;
//Input boolean
bool LHeld = false;
bool RHeld = false;
///Attatch this to the box2d object
SDL_Rect box;
/// Create box2d world
b2World* world;
/// Most of this is from eder13 and the github from given source. Had to update to SetTwoSided for box2d 2.4.1
const int MET2PIX = 80; // 640 / 80 = 8
const int WIDTH = 640;
const int HEIGHT = 480;
const int SCALED_WIDTH = WIDTH / MET2PIX; // 4 | 3
const int SCALED_HEIGHT = HEIGHT / MET2PIX;
//1 rad × 180/π = 57,296°
const float RAD2DEG = 180 / M_PI;
using namespace std;
int main()
{
///b2Vec2 force(10.0f, 0.0f); Can be ignored
///Set window values
wWidth = 800;
wHeight = 600;
///Set level values. Changing this will resort in either image wrap or image not scrolling
LEVEL_WIDTH = 2000;
LEVEL_HEIGHT = 1000;
///The camera
SDL_Rect camera{ 0,0,wWidth,wHeight };
///The player size, can be modified
SDL_FPoint PlayerSize = { 40.0f, 100.0f };
///Setting up more values for player and window values
SDL_FRect Player = { wWidth - PlayerSize.x, wHeight - PlayerSize.y, PlayerSize.x, PlayerSize.y };
Player.x = 1;
Player.y = 90;
///Standard SDL2 stuff
if (SDL_Init(SDL_INIT_VIDEO))
{
printf("Error: %s", SDL_GetError());
return -1;
}
SDL_Window* window = SDL_CreateWindow("Spine SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wWidth, wHeight,
0);
if (!window) {
printf("Error: %s", SDL_GetError());
return -1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!renderer) {
printf("Error: %s", SDL_GetError());
return -1;
}
///Setup our textures, can change this, but keep in mind the width and height of these pictures must match
SDL_Texture* texture = IMG_LoadTexture(renderer, "background.png");
SDL_Texture* sample = IMG_LoadTexture(renderer, "sample.png");
///Create our box2d world
world = new b2World(b2Vec2(0.0f, 9.81f)); // new b2World(b2Vec2(0.0f, 9.81f));
///Stole all this from eder13 in favor of me studying sdl2 and box2d together. If you see this eder13, i'm sorry!!!!!!!!!
// cartesian origin
float ground_x = 0.0f;
float ground_y = 0.0f;
// start ground point
b2Vec2 startpoint;
startpoint.x = -3.0f;
startpoint.y = -1.0;
// end ground point
b2Vec2 endpoint;
endpoint.x = 20;
endpoint.y = 7.5; ///Setting this will result in endpoint going either up or down, thus making the box slide either fast or slow
// LineGround
b2BodyDef myGroundDef;
myGroundDef.type = b2_staticBody;
myGroundDef.position.Set(ground_x, ground_y); // set the starting position x and y cartesian
myGroundDef.angle = 0;
b2Body* groundLineBody = world->CreateBody(&myGroundDef);
b2EdgeShape edgeShape;
edgeShape.SetTwoSided(startpoint, endpoint); // length -> coordinate vector from to vector
b2FixtureDef edgeFixtureDef;
edgeFixtureDef.shape = &edgeShape;
groundLineBody->CreateFixture(&edgeFixtureDef);
SDL_Surface* tmp_sprites;
tmp_sprites = IMG_Load("box.bmp");
if (!tmp_sprites)
return EXIT_FAILURE;
SDL_Texture* texture_box = SDL_CreateTextureFromSurface(renderer, tmp_sprites);
SDL_FreeSurface(tmp_sprites);
// cartesian origin box
float x_box = -2.5f;
float y_box = -2.5f;
// size of box
float w_box = 1.76;
float h_box = 1.76;
// angle of the box
float angle_box = 45.0f; //45.0f;
///Create for the body for the box created from SDL_Rect box
b2Body* Body;
///Box2d values
b2BodyDef boxBodyDef;
boxBodyDef.type = b2_dynamicBody;
boxBodyDef.angle = angle_box; // flips the whole thing -> 180 grad drehung
//boxBodyDef.angle = 0;
boxBodyDef.position.Set(x_box, y_box);
///Set velocity to box2d body for box
b2Vec2 vel;
vel.Set(0, 0.2f);
Body = world->CreateBody(&boxBodyDef);
Body->SetLinearVelocity(vel);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox((w_box / 2.0f) - dynamicBox.m_radius, (h_box / 2.0f) - dynamicBox.m_radius); // will be 0.5 x 0.5
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 1;
fixtureDef.friction = 0.3f;
fixtureDef.restitution = 0.5f;
Body->CreateFixture(&fixtureDef);
// box: convert Metres back to Pixels for width and height
box.w = w_box * MET2PIX;
box.h = h_box * MET2PIX;
// cartesian origin of _0019_PLATF.png 89 x 22
float x_plat = -3.6f; // to edge
float y_plat = -0.14f;// to edge
// size of the platform
float w_plat = 89.0f / MET2PIX;
float h_plat = 22.0f / MET2PIX;
// define a Rect for this platform and its body def
SDL_Rect platform;
b2Body* Body_platform;
b2BodyDef platformBoyDef;
platformBoyDef.type = b2_staticBody;
platformBoyDef.position.Set(x_plat, y_plat);
Body_platform = world->CreateBody(&platformBoyDef);
b2PolygonShape platformTile; // subtracting radius fixes the incorrect little gap that can appear when working with really small resolutions
platformTile.SetAsBox((w_plat / 2.0f) - platformTile.m_radius, (h_plat / 2.0f) - platformTile.m_radius); // subtracting the radius kills the gap issue:
b2FixtureDef fixturePlat;
fixturePlat.shape = &platformTile;
fixturePlat.density = 1.0f;
fixturePlat.friction = 0.3f;
fixturePlat.restitution = 0.5f;
Body_platform->CreateFixture(&fixturePlat);
// set the SDL_RECT rendering values
platform.w = w_plat * MET2PIX;
platform.h = h_plat * MET2PIX;
platform.x = ((SCALED_WIDTH / 2.0f) + x_plat) * MET2PIX - platform.w / 2;
platform.y = ((SCALED_HEIGHT / 2.0f) + y_plat) * MET2PIX - platform.h / 2;
bool quit = false;
while (!quit)
{
b2Vec2 pos = Body->GetPosition(); // Body = Body from box
float angle = Body->GetAngle();
// RAD2Degree
angle *= RAD2DEG;
///From daniel1985
NewTime = (double)SDL_GetTicks();
DeltaTime = (NewTime - OldTime) * 0.001;
OldTime = NewTime;
Lifetime += DeltaTime;
///Created this and had some help from the community
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = Player.w;
rect.h = Player.h;
SDL_Event event;
while (SDL_PollEvent(&event) != 0)
{
if (event.type == SDL_QUIT)
{
quit = true;
break;
}
}
///This is for any object you wish to place for the camera not to scroll within any given rect you put your texture in
SDL_Rect dontFollow = { box.x - camera.x, box.y - camera.y,box.w,box.h };
// question box, update x and y destination
box.x = ((SCALED_WIDTH / 2.0f) + pos.x) * MET2PIX - box.w / 2;
box.y = ((SCALED_HEIGHT / 2.0f) + pos.y) * MET2PIX - box.h / 2;
///From daniel1985, setting up input
const Uint8* KeyboardState = SDL_GetKeyboardState(nullptr);
LHeld = (KeyboardState[SDL_SCANCODE_LEFT] == SDL_TRUE);
RHeld = (KeyboardState[SDL_SCANCODE_RIGHT] == SDL_TRUE);
///This is just in case you want to move the blue rectangle around within x axis
/*
if (LHeld && !RHeld)
//Player.x -= playerSpeed * (float)DeltaTime;
else if (RHeld && !LHeld)
//Player.x += playerSpeed * (float)DeltaTime;
//Player.x += playerSpeed * (float)DeltaTime;
*/
/*
if (Player.x < 0.0f)
Player.x = 0.0f;
else if (Player.x > (LEVEL_WIDTH - Player.w))
Player.x = LEVEL_WIDTH - Player.w;
*/ ///Only for moving the player when not focused on box2d
///Attatch camera to box2d object
camera.x = (box.x) - wWidth / 2;
///From LazyFoo scrolling and sources found on youtube for sdl2 screen scrolling/ camera scroll
if (camera.x < 0)
{
camera.x = 0;
}
if (camera.y < 0)
{
camera.y = 0;
}
if (camera.x > LEVEL_WIDTH - camera.w)
{
camera.x = LEVEL_WIDTH - camera.w;
}
if (camera.y > LEVEL_HEIGHT - camera.h)
{
camera.y = LEVEL_HEIGHT - camera.h;
}
///Standard SDL2 stuff
SDL_SetRenderDrawColor(renderer, 94, 93, 96, 255);
SDL_RenderClear(renderer);
///Render the background
SDL_RenderCopy(renderer, texture, &camera, NULL);
///Setting rect values to both the player and camera
rect.x = Player.x - camera.x;
rect.y = Player.y - camera.y;
///Standard SDL2
SDL_RenderCopy(renderer, sample, NULL, &rect);
///Set visibility from line created from startpoint and endpoint(Not fixxed, but in demo, the box slides while the camera scrolls with the box sliding
SDL_RenderDrawLine(renderer, ((SCALED_WIDTH / 2.0f) + edgeShape.m_vertex1.x) * MET2PIX, ((SCALED_HEIGHT / 2.0f) + edgeShape.m_vertex1.y) * MET2PIX, ((SCALED_WIDTH / 2.0f) + edgeShape.m_vertex2.x) * MET2PIX, ((SCALED_HEIGHT / 2.0f) + edgeShape.m_vertex2.y) * MET2PIX);
///Set box.bmp to Body created from above int main, and then have it rotate. Settings can be modified if you like
SDL_RenderCopyEx(renderer, texture_box, NULL, &dontFollow, Body->GetAngle() * RAD2DEG, NULL, SDL_FLIP_NONE);
///Standard SDL2
SDL_RenderPresent(renderer);
///Required for simulating box2d physics. Delete this, NO PHYSICS!!!!!
world->Step(1.0f / 60.0f, 6.0f, 2.0f);
}
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_DestroyTexture(texture);
texture = nullptr;
SDL_Quit();
return 0;
}
The purpose of this code, is to simulate a textured box to slide down the slope created from sdl2
Nice that you got it working.
I just want to note that Box2D uses radians for rotations.
I see for example that you’re setting the angle like this:
// angle of the box
float angle_box = 45.0f; //45.0f;
boxBodyDef.angle = angle_box;
It looks like you want to use degrees in your code base and when you’re passing in 45 as the angle, the physics object will be rotated 45 radians.
If you want to use degrees, you should convert the angle to radians when passing it to Box2D.
Example:
#define DEG_TO_RAD(X) ((X) * (M_PI / 180.0f))
boxBodyDef.angle = DEG_TO_RAD(angle_box);
Later on, when you retrieve the angle from Box2D, you’re doing this:
float angle = Body->GetAngle();
// RAD2Degree
angle *= RAD2DEG;
It can be changed to a one-liner like this:
#define RAD_TO_DEG(X) ((X) * (180.0f / PI))
const float angle = RAD_TO_DEG(Body->GetAngle());
thnx ill take a look