I have written a programme to bounce around a rectangle. I use SDL_RenderFillRect to draw a rectangle and SDL_RenderPresent to present that rectangle after which SDL_RenderClear clears the renderer to do it all over again. I use SDL_GetTicks and SDL_Delay to get it to update 60 times a second but somehow the speed of the rectangle is irregular instead of smooth. I have tried different things the past few days but nothing helped. Is there a specific way I should use SDL_RenderPresent to get my window to update regularly?
#include <SDL.h>
#include <math.h>
#include <iostream>
#include <stdio.h>
const int width = 1200;
const int height = 800;
const double PI = 3.141592653589793;
void init();
void quit();
double x = width / 2;
double y = height / 2;
double r = 25;
double vx = 1;
double vy = 1;
double s = 4;
double tickStart = SDL_GetTicks();
double tickEnd = 0;
double tickDelta = 0;
double frameTime = 1001.0 / 60.0;
double delayTime = 0;
int c = 0;
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Event *event;
SDL_Rect rect;
int main(int argc, char* argv[]) {
init();
// main loop
bool running = true;
while (running) {
event = new SDL_Event;
while (SDL_PollEvent(event) != 0) {
if (event->type == SDL_QUIT) {
running = false;
break;
}
}
//renderer
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
// update position
x = x + vx*s;
y = y + vy*s;
// check wall collision
if (x - r <= 0) {
vx = -vx;
x = r;
}
else if (x + r >= width) {
vx = -vx;
x = width - r;
}
if (y - r <= 0) {
vy = -vy;
y = r;
}
else if (y + r >= height) {
vy = -vy;
y = height - r;
}
// rect
rect.h = rect.w = 2 * r;
rect.x = x - r;
rect.y = y - r;
SDL_RenderFillRect(renderer, &rect);
// present everything at the right time
tickEnd = SDL_GetTicks();
tickDelta = tickEnd - tickStart;
delayTime = frameTime - tickDelta;
std::cout << tickDelta << std::endl;
if (delayTime > 0)
SDL_Delay(delayTime);
tickStart = SDL_GetTicks();
SDL_RenderPresent(renderer);
c++;
}
quit();
return 0;
}
void init()
{
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("test", 200, 100, width, height, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
}
void quit()
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_QUIT;
}
Calling SDL_Delay() seems to take about 15ms depending on circumstances. The renderer can be vertically synced by asigning the right flag: renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
Related
I'm currently stuck because the program runs perfectly fine but when I try to eat the food it doesn't work because the food is in a weird position. What I mean by weird position is that when I go over it with the snake it doesn't register.
At first, I thought it was because I was getting a decimal so I tried to put it into an int, but apparently, that did not work.
Snake game, SDL, c++
#include <SDL.h>
#include <SDL_keycode.h>
#include <stdio.h>
#include <iostream>
using namespace std;
struct Food
{
int Height;
int Width;
int x_Pos;
int y_Pos;
void move()
{
int x_Pos = rand() % 400 + 40;//random pos
int y_Pos = rand() % 400 + 40;
}
void draw(SDL_Renderer* renderer)
{
SDL_Rect r{ x_Pos, y_Pos, 20, 20 };
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 0);
SDL_RenderFillRect(renderer, &r);
}
};
struct v2
{
int x, y;
};
v2 operator+ (const v2& a, const v2& b)
{
return v2{ a.x + b.x, a.y + b.y };
}
void operator+= (v2& a, const v2& b)
{
a.x += b.x;
a.y += b.y;
}
struct Snake
{
int Height;
int Width;
v2 pos;
v2 vel;
int vX, vY;
uint32_t accumulator;
void update(uint32_t delta_time, Food& food)
{
accumulator += delta_time;
if (accumulator > 50)// update every 50 ms
{
accumulator = 0;
pos.x += vel.x;
pos.y += vel.y;
if (pos.x == food.x_Pos && pos.y == food.y_Pos)
{
food.move();
}
}
}
void draw(SDL_Renderer* renderer)
{
SDL_Rect r{ pos.x, pos.y, 20, 20 };
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 0);
SDL_RenderFillRect(renderer, &r);
}
};
bool isRunning = true;
//Screen dimension constants
const int SCREEN_WIDTH = 700;
const int SCREEN_HEIGHT = 700;
void setup_Window(int width, int height);
void input(SDL_Renderer* renderer);
void create_Rect(SDL_Renderer* &renderer, int x, int y, int w, int h, int colorRed, int colorGreen, int colorBlue, int colorA);
int main(int argc, char** argv)
{
srand(time(NULL));
int score = 0;
setup_Window(SCREEN_WIDTH, SCREEN_HEIGHT);
return 0;
}
void Calc()
{
}
void setup_Window(int width, int height)
{
if (SDL_Init(SDL_INIT_VIDEO) == 0)
{
std::cout << "Subsystems Initialised!..." << std::endl;
//The window we'll be rendering to
SDL_Window* window = SDL_CreateWindow("Snake Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);
// Setup renderer
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
input(renderer);
}
}
void create_Rect(SDL_Renderer* &renderer, int x, int y, int w, int h, int colorRed, int colorGreen, int colorBlue, int colorA)
{
// Creat a rect at pos ( 50, 50 ) that's 50 pixels wide and 50 pixels high.
SDL_Rect r;
r.x = x;//615
r.y = y;//0
r.w = w;//25
r.h = h;//480
// x = up and down
// y = left and right
// Set render color to blue ( rect will be rendered in this color )
SDL_SetRenderDrawColor(renderer, colorRed, colorGreen, colorBlue, colorA);
// Render rect
SDL_RenderFillRect(renderer, &r);
// Render the rect to the screen
SDL_RenderPresent(renderer);
}
void input(SDL_Renderer* renderer)
{
uint32_t current_Time = 0, previous_Time, delta_Time;
SDL_Event event;
int rando1 = rand() % 400 + 40;
int rando2 = rand() % 400 + 40;
int rando3 = rand() % 400 + 40;
int rando4 = rand() % 400 + 40;
Snake snake_Body = {};// stuct for Snake object
snake_Body.pos.x = rando1;//random pos
snake_Body.pos.y = rando2;
Food food = {}; // stuct for food object
food.move();
food.x_Pos = SCREEN_WIDTH/2;//random pos
food.y_Pos = SCREEN_HEIGHT/2;
while (isRunning)
{
previous_Time = current_Time;
current_Time = SDL_GetTicks();
delta_Time = current_Time - previous_Time;
// Set render color to black ( rect will be rendered in this color )
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
/* Clear the entire screen to our selected color. */
SDL_RenderClear(renderer);
create_Rect(renderer, 670, 0, 30, 700, 0, 255, 255, 255);// right rectangle
create_Rect(renderer, 1, 0, 30, 700, 0, 255, 255, 255);// left rectangle
create_Rect(renderer, 30, 1, 700, 30, 0, 255, 255, 255);// top rectangle
create_Rect(renderer, 1, 670, 700, 30, 0, 255, 255, 255);// Bottom rectangle
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
isRunning = false;
}
if (event.type == SDL_KEYDOWN)
{
switch (event.key.keysym.sym)
{
case SDLK_LEFT:
{
snake_Body.vel.y = 0;
snake_Body.vel.x = -15;
cout << "Crouiser1" << endl;
break;
}
case SDLK_UP:
{
snake_Body.vel.y = -15;
snake_Body.vel.x = 0;
cout << "Crouiser2" << endl;
break;
}
case SDLK_RIGHT:
{
snake_Body.vel.y = 0;
snake_Body.vel.x = 15;
cout << "Crouiser3" << endl;
break;
}
case SDLK_DOWN:
{
snake_Body.vel.y = 15;
snake_Body.vel.x = 0;
cout << "Crouiser4" << endl;
break;
}
case SDLK_ESCAPE:
{
isRunning = false;
break;
}
default:
{
break;
}
}
}
}
snake_Body.update(delta_Time, food);
snake_Body.draw(renderer);
food.draw(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(100);
}
}
The collision-check in your update-function only checks if the upper left pixel of your Snake-rectangle overlaps with the upper left pixel of your Food-Rectangle.
To solve your problem, you need to implement a proper collision-check.
This code works for me:
bool CollisionCheck(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
{
//x-coordinate of square 1 is positioned after x + width of square 2
bool one = x1 > (x2 + w2);
//x-coordinate of square 2 is positioned after x + width of square 1
bool two = (x1 + w1) < x2;
//y-coordinate of square 1 is positioned below y + hight of square 2
bool three = y1 > (y2 + h2);
//y-coordinate of square 2 is positioned below y + hight of square 1
bool four = (y1 + h1) < y2;
if (one || two || three || four)
{
//If one of the above rules apply, there is NO COLLISION
return false;
}
//If none of the above rules apply, there is a collision
return true;
}
I started Learning C++ yesterday And In that time i was rewriting my java "Falling Sand" Sandbox Game code in C++ using SFML (bit simplified since i don't know C++). but Performance in C++ was much worse in than java, what could be the reason for it, I Know this is very unfocused question, but my code is simple, i probably have a newbie mistakes which should be easy to correct.
#include <SFML/Graphics.hpp>
#include <iostream>
sf::Clock sclock;
const int WIDTH = 1440, HEIGHT = 960;
const char Blank = 0, Sand = 1, Water = 2;
const char* title = "Sandbox Simulation";
char map[WIDTH*HEIGHT];
sf::Vector2i mousePos;
int dist(int x1, int x2, int y1, int y2) {
return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
}
int localBrushSize = 48;
short halfBrush = (short)floor(localBrushSize / 2);
char chosen = Sand;
void place() {
int randY = 0;
int randX = 0;
randX = randY = 1;
for (int y = mousePos.y - halfBrush; y <= mousePos.y + halfBrush; y += randY) {
for (int x = mousePos.x - halfBrush; x <= mousePos.x + halfBrush; x += randX) {
int I = x + y * WIDTH;
int distance = dist(mousePos.x, x, mousePos.y, y);
if (distance < halfBrush && I > 0) {
map[I] = chosen;
}
}
}
}
float Delta_Time() {
return sclock.restart().asSeconds();
}
int main() {
map[11111] = 2;
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), title);
sf::Event evnt;
sf::RectangleShape pixel(sf::Vector2f(1.0f, 1.0f));
window.clear();
while (window.isOpen()) {
while (window.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
window.close();
break;
}
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
mousePos = sf::Mouse::getPosition(window);
place();
}
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
int I = x + y * WIDTH;
switch (map[I]) {
case Sand:
pixel.setPosition(x, y);
pixel.setFillColor(sf::Color::Yellow);
window.draw(pixel);
break;
case Water:
pixel.setPosition(x, y);
pixel.setFillColor(sf::Color::Cyan);
window.draw(pixel);
break;
}
}
}
window.display();
}
return 0;
}
You might be able to make a cached / "framebuffer" like this
TOTALLY untested concept code. WIDTH/HEIGHT might be mixed up, endianess is not OK, etc.
sf::Image image;
sf:Image.create(WIDTH, HEIGHT, sf::Color(0, 0, 0));
sf::Sprite sprite;
std::array<sf::Uint8, WIDTH * HEIGHT * 4> pixels; // you can reuse this. The 4 is the size of RGBA
...
for(int y = 0; y < HEIGHT; y++) {
for(int x = 0; x < WIDTH; x++) {
int offset = (x + y * WIDTH) * 4;
pixels[offset] = sf::Color::Yellow.toInteger(); // in case BIG/Litte endian confusion you might have to do the below.
//pixels[offset + 0 ] = 255; // R?
//pixels[offset + 1 ] = 255; // G?
//pixels[offset + 2 ] = 255; // B?
//pixels[offset + 3 ] = 255; // A?
}
}
image.LoadFromPixels(WIDTH, HEIGHT, pixels);
sprite.SetImage(image);
window.Draw(sprite);
window.Display();
I have implemented a depth buffer using a std::vector with size 640 * 480. I can write and read from the buffer fine, but I have noticed the buffer appears to be copied along the left and right edges. The buffer is written row by row, going left to right and then going down one row.
I am quite certain the issue is related to the depth buffer, as disabling read from the buffer fixes the artifacts and shows the buffer is still being written properly.
I am using SDL as the graphics library, but not OpenGL.
This buffer should only show one trapezium down the middle. The extra bits on the left and right should not appear.
What is happening to cause these artifacts? Alternatively, could I know some methods to debug this better.
Minimum code to replicate (as far as I can tell):
#include "SDL.h"
#include <vector>
#include <algorithm>
#include <iostream>
struct vec3d {
float x = 0;
float y = 0;
float z = 0;
};
struct tri3d {
vec3d p1;
vec3d p2;
vec3d p3;
};
struct vector2d {
float x;
float y;
};
float vect_dot_vect(vector2d a, vector2d b) {
return(a.x * b.x + a.y * b.y);
}
int draw_tri(SDL_Renderer* renderer, std::vector<float>& buffer_out, tri3d triangle, int half_x_width, int half_y_width, int depth_test) { // depthmap is a linear array. Buffer out is pointing to the first value
tri3d scaled_tri = triangle;
// Find bounding box of tri
int x = (int)std::min(std::min(floor(scaled_tri.p1.x), floor(scaled_tri.p2.x)), floor(scaled_tri.p3.x));
int y = (int)std::min(std::min(floor(scaled_tri.p1.y), floor(scaled_tri.p2.y)), floor(scaled_tri.p3.y));
int wx = (int)std::max(std::max(ceil(scaled_tri.p1.x), ceil(scaled_tri.p2.x)), ceil(scaled_tri.p3.x)) - x;
int wy = (int)std::max(std::max(ceil(scaled_tri.p1.y), ceil(scaled_tri.p2.y)), ceil(scaled_tri.p3.y)) - y;
// Find edge vectors
vector2d ac;
ac.x = scaled_tri.p3.x - scaled_tri.p1.x;
ac.y = scaled_tri.p3.y - scaled_tri.p1.y;
vector2d ab;
ab.x = scaled_tri.p2.x - scaled_tri.p1.x;
ab.y = scaled_tri.p2.y - scaled_tri.p1.y;
float cc = vect_dot_vect(ac, ac);
float cb = vect_dot_vect(ac, ab);
float cp;
float bb = vect_dot_vect(ab, ab);
float bp;
float invDenom = 1 / (cc * bb - pow(cb, 2));
float u;
float v;
float w;
float x_dif = x - scaled_tri.p1.x;
float y_dif = y - scaled_tri.p1.y;
int full_y_width = half_y_width * 2;
float twoarea = (ab.x * ac.y - ab.y * ac.x);
float barycentric_depth_weights[3] = { scaled_tri.p1.z, scaled_tri.p2.z, scaled_tri.p3.z };
float depth_map_value;
for (size_t i = wy; i != 0; i--) {
for (size_t q = wx; q != 0; q--) {
vector2d ap;
ap.x = q + x_dif;
ap.y = i + y_dif;
cp = vect_dot_vect(ac, ap);
bp = vect_dot_vect(ab, ap);
// Find barycentric coords
u = (bb * cp - cb * bp) * invDenom;
v = (cc * bp - cb * cp) * invDenom;
w = abs(1 - u - v);
depth_map_value = (w * barycentric_depth_weights[0] + v * barycentric_depth_weights[1] + u * barycentric_depth_weights[2]);
// Test if in tri
if (u >= 0 && v >= 0 && u + v < 1) {
// Test depth buffer
if (buffer_out[(y + i) * full_y_width + x + q] < (0.0625 + depth_map_value)) {
buffer_out[(y + i) * full_y_width + x + q] = depth_map_value;
}
}
}
}
return 0;
}
SDL_Window* win_make_window(int display_width, int display_height, SDL_WindowFlags flags) {
// Returns an SDL window given screen size and flags
SDL_Window* window = NULL;
window = SDL_CreateWindow("Minimum code", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, display_width, display_height, flags);
if (window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
return window;
}
int draw_buffer(SDL_Renderer* renderer, std::vector<float>& buffer, int half_screen_x, int half_screen_y) {
// Iterate over every pixel and draw
int depth_map_value;
int screen_y = 2 * half_screen_y;
for (size_t i = 0; i < screen_y; i++) {
for (size_t q = 0; q < half_screen_x * 2; q++) {
depth_map_value = buffer.at(screen_y * i + q) * 100;
SDL_SetRenderDrawColor(renderer, depth_map_value, depth_map_value, depth_map_value, 255);
SDL_RenderDrawPoint(renderer, (int)q, (int)i);
}
}
return 0;
}
int main(int argc, char* argv[]) {
const int half_screen_size[2] = { 320, 240 }; // Half size of screen. Needed it elsewhere
const SDL_WindowFlags flags = SDL_WINDOW_SHOWN;
// SDL startup boilerplate
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Renderer* renderer = NULL;
// The tris, already projected
tri3d tri1;
tri1.p1 = { 577.173828, 453.201538, 1.37657264 };
tri1.p2 = { 108.381744, 399.609772, 1.03054810 };
tri1.p3 = { 547.989380,70.1635742,1.20407486 };
tri3d tri2;
tri2.p1 = { 108.381744, 399.609772, 1.03054810 };
tri2.p2 = { 131.230850, 108.719635, 0.930727124 };
tri2.p3 = { 547.989380, 70.1635742, 1.20407486 };
//Create depth buffer
std::vector<float> depth_buffer = {0};
depth_buffer.resize(4 * static_cast<__int64>(half_screen_size[0]) * static_cast<__int64>(half_screen_size[1]));
// Catch startup errors
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); // Catch startup errors
else {
SDL_Event event_handle;
window = win_make_window(half_screen_size[0] * 2, half_screen_size[1] * 2, flags);
screenSurface = SDL_GetWindowSurface(window);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// Draw tris to screen. No pixels actually drawn for debug purposes, only modifies depth buffer
draw_tri(renderer, depth_buffer, tri1, half_screen_size[0], half_screen_size[1], 1);
draw_tri(renderer, depth_buffer, tri2, half_screen_size[0], half_screen_size[1], 1);
// Draw the buffer to screen
draw_buffer(renderer, depth_buffer, half_screen_size[0], half_screen_size[1]);
SDL_RenderPresent(renderer);
}
// Close everything else
std::cin.get();
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
This is a school project and as such, I am not allowed to use SDL provided features except to draw to screen and for handling windows.
I modified the code to draw the depth buffer as it was being calculated, and noticed that when drawing from left to right, columnwise, the leftmost artifact no longer renderers. By changing the range of the region rendered, it appears that writing to one spot on the depth buffer also writes to another. No idea what to make of this yet.
No idea what's the deal with "half" sizes as you seem to use full size everywhere, but your array indexing is wrong. When iterating rectangle with [width, height], correct indexing code is e.g.:
for(int y = 0; y != height; ++y) {
for(int x = 0; x != width; ++x) {
int pixel = pixel_array[y*width+x]; // not y*height!
}
}
Correct that in both places you index your depth array:
in draw_tri, buffer_out[(y + i) * full_y_width + x + q] - should be full_x_width, which you don't have yet,
in draw_buffer, depth_map_value = buffer.at(screen_y * i + q) * 100; - should be screen_x.
This code is eating up my RAM at 1 to 2 percent a second (6 GB total).
Could anyone tell me what's wrong? Thanks in advance. I'm new to this, so if I sound like a complete idiot, I am. I'd like an answer fast.
#include <windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
/* Globals */
int ScreenX = 0;
int ScreenY = 0;
BYTE* ScreenData = 0;
void ScreenCap()
{
HDC hScreen = GetDC(GetDesktopWindow());
//hScreen2 = hScreen;
if (ScreenX == 0)
{
ScreenX = GetDeviceCaps(hScreen, HORZRES);
ScreenY = GetDeviceCaps(hScreen, VERTRES);
}
HDC hdcMem = CreateCompatibleDC (hScreen);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, ScreenX, ScreenY);
HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hOld);
BITMAPINFOHEADER bmi = {0};
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biPlanes = 1;
bmi.biBitCount = 32;
bmi.biWidth = ScreenX;
bmi.biHeight = -ScreenY;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = 0;// 3 * ScreenX * ScreenY;
if(ScreenData)
free(ScreenData);
ScreenData = (BYTE*)malloc(4 * ScreenX * ScreenY);
GetDIBits(hdcMem, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
ReleaseDC(GetDesktopWindow(),hScreen);
DeleteDC(hdcMem);
}
inline int PosB(int x, int y)
{
return ScreenData[4*((y*ScreenX)+x)];
}
inline int PosG(int x, int y)
{
return ScreenData[4*((y*ScreenX)+x)+1];
}
inline int PosR(int x, int y)
{
return ScreenData[4*((y*ScreenX)+x)+2];
}
bool ButtonPress(int Key)
{
bool button_pressed = false;
while(GetAsyncKeyState(Key))
button_pressed = true;
return button_pressed;
}
int main()
{
while (true)
{
ScreenCap();
/*for (int x = 1; x < ScreenX; x++)
{
for (int y = 1; y < ScreenY; y++)
{
int Red = PosR(x, y);
int Green = PosG(x, y);
int Blue = PosB(x, y);
if (Red == 22 && Green == 58 && Blue == 89)
{
cout << ">:D";
POINT pos;
GetCursorPos(&pos);
int DX = 683 - x;
int DY = 683 - y;
/*COLORREF col = GetPixel(hScreen2, DX - pos.x + 1, pos.y - DY + 1);
int red = GetRValue(col);
int blue = GetBValue(col);
int green = GetGValue(col);
if (red == 22 && green == 58 && blue == 89)
{
break;
}
//SetCursorPos(x + DX, y + DY);
SetCursorPos(DX - pos.x + 1, pos.y - DY + 1);
cout << DX - pos.x << ", " << pos.y - DY + 1 << endl;
break;
}
}
}*/
}
system("PAUSE");
return 0;
}
You keep creating new bitmaps and never delete them.
Even better than freeing them each time would be to reuse the previous bitmap unless the screen size actually changed. Ditto for ScreenData. Reallocating unnecessarily is a performance killer.
You also aren't selecting the original object back in before destroying the DC, which is a problem.
I've created a program using SDL in which a rectangle continuously collides within the walls of the program, but the collision checking is not working properly.
Here is the code:`
int main(int argc, char *argv[]){
//variable Initialization]
width = height = 45;
srcX = srcY = 0;
destY = destX = 0;
vlc = 1;
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
SDL_WM_SetCaption("Bouncing Balls","./ball.jpg");
backg = IMG_Load("./back.png");
ball = IMG_Load("./ball.jpg");
while (checkBounce){
//Increase velocity
destX += vlc;
destY += vlc;
//Collision Checking
if (destX < 0){
destX = 0;
vlc = -vlc;
destX += vlc;
}
if (destY < 0){
destY = 0;
vlc = -vlc;
destY += vlc;
}
if (destY + height > 480){
destY = 480 - height;
vlc = -vlc;
}
if (destX + width > 640){
destX = 640 - width;
vlc = -vlc;
}
if (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT)
checkBounce = false;
}
//Applying Surfaces
applySurface(0, 0, backg, screen);
applyBall(srcX, srcY, destX, destY, width, height, ball, screen);
SDL_Flip(screen);
}
SDL_Quit();
return 0;
}
Here is the gif Image What is happening :Bouncing Rectangle.gif
I'm assuming that the expected result is for the rectangle to bounce off of the walls correctly?
You need to separate your velocity in to x and y components rather than using a single number. This is because velocity is two dimensional.
Your program is causing both the x and y components to become negative whenever a collision is detected. This causes the rectangle to bounce backwards along its path.
Here's an edit:
int main(int argc, char *argv[]){
//variable Initialization]
width = height = 45;
srcX = srcY = 0;
destY = destX = 0;
vlcX = 1;
vlcY = 1;
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
SDL_WM_SetCaption("Bouncing Balls","./ball.jpg");
backg = IMG_Load("./back.png");
ball = IMG_Load("./ball.jpg");
while (checkBounce){
//Increase velocity
destX += vlcX;
destY += vlcY;
//Collision Checking
if (destX < 0){
destX = 0;
vlcX = -vlcX;
destX += vlcX;
}
if (destY < 0){
destY = 0;
vlcY = -vlcY;
destY += vlcY;
}
if (destY + height > 480){
destY = 480 - height;
vlcY = -vlcY;
}
if (destX + width > 640){
destX = 640 - width;
vlcX = -vlcX;
}
if (SDL_PollEvent(&event)){
if (event.type == SDL_QUIT)
checkBounce = false;
}
//Applying Surfaces
applySurface(0, 0, backg, screen);
applyBall(srcX, srcY, destX, destY, width, height, ball, screen);
SDL_Flip(screen);
}
SDL_Quit();
return 0;
}