rectangle disappearing with SDL - c++

So I'm simply trying to make a red 10 x 10 box move vertically back and forth. I compile and run my program and the red box appears starts moving down, then just disappears after it hits the edge of the screen. I used some cout << statements that tell me when the functions are being called and they are all being called when they are supposed to. Even when the box can't be seen the functions are properly being called.
My main loop
while(running)
{
myScreen->Clear();
boxes.Move();
boxes.Draw();
myScreen->Flip();
........
My draw() function
SDL_Color red;
red.r = 255;
red.g = 0;
red.b = 0;
if( SDL_FillRect( my_screen->Get_screen(), &start_dest, SDL_MapRGB(
my_screen->Get_pixel_format(), red.r, red.g, red.b ) ) == -1 )`
cout << "Fill rect in Draw(); failed\n";
My Move() function
start_dest.y += y_step;
if ( start_dest.y >= my_screen->Get_height() )
{
cout << "start_dest.y >= screen height\n";
start_dest.y = my_screen->Get_height();
y_step = -y_step;
}
if ( start_dest.y <= 0 )
{
cout << "start_dest.y <= 0\n";
start_dest.y = 0;
y_step = -y_step;
}
I have been trying to find this bug forever. just leave a comment if anyone wants to see more code. Thanks

There isn't enough information to give conclusive answer, but here's a hint.
From my experience with SDL, SDL functions can modify your Rect structure when called, especially when rect is partly off-screen. Make sure you set all its properties (x,y,width,height) before each SDL function that uses the rectangle.

(I'm assuming here that start_dest has a 'height' member, and that the screen coordinates have (0,0) in the top left corner)
I think perhaps the first 'if' statement in Move() should be
if(start_dest.y >= my_screen.Get_height - start_dest.height)
so that the rectangle will bounce when its bottom hits the bottom of the screen rather than waiting until the top of the rectangle gets there. Something to that effect, anyways.

Related

QT collision detection between 2 QGraphicsPixmapItems

Link to project
The interesting parts should be in gameengine.cpp's "launchSplash" -function and splashanimation.cpp
The game creates the bubbles randomly in the acceptable are. The player's job is to shoot the bubbles with water drops. The water drops are launched from the middle bottom part of the game screen. The grids are only used for debugging, and will later on be gone, but it makes visualizing the areas easier.
The bubbles are destroyed by shooting the water drop at them, but the water drop disappears when it hits a bubble or the upper boundary of the game. The water drop shoots to the direction of a mouse click.
I'm trying to create a collision detection for a basic bubble shooter game, but I'm not sure how I can detect the collision in a neat way.
The game board looks something like this game board, the water drops are shot from the middle bottom part of the screen to the direction of the cursor.
Eventually I'll have the water drop ricochet from the walls, but at the moment I'm contempt with figuring out how to detect collisions in the first place.
The game board is 500x600 units (width x height), so the point the water drop is shot at is (250, 600).
When the water drop is shot, I use
void GameEngine::launchSplash(int clickX, int clickY){
// <my long method of calculating the coordinates for the water drop's path>
graphicalGameBoard_.animateSplash(graphicalGameBoard_.width()/2, graphicalGameBoard_.height(), xDestination, yDestination);
}
where xDestination and yDestionation are the place the water drop will end up if it travels unhindered. The water drop will either end up at x=0 / x=500 and/or y=0/y=600, but I don't think that's relevant.
The bubbles are added to the game board with
board_.clear();
for(int y = 0; y < HEIGHT; ++y)
{
std::vector< std::shared_ptr<Bubble> > row;
for(int x = 0; x < WIDTH; ++x)
{
std::shared_ptr<Bubble> newBubble = nullptr;
// There will be bubbles only in the top 3/4 of the board only in the middle
// (i.e. not in the first two and last two columns).
if (y < HEIGHT*3/4 && x > 1 && x < WIDTH-2)
{
// Generate random numbers using the enumearation type defined in
// file bubble.hh. The value COLOR_COUNT is used to represent no bubble.
std::uniform_int_distribution<int> distribution(RED,COLOR_COUNT);
// If you want no empty squares, change the initialization to:
// std::uniform_int_distribution<int> distribution(RED,BLUE);
Color color = static_cast<Color>(distribution(randomEngine_));
if(color != COLOR_COUNT) {
newBubble = std::make_shared<Bubble>(x, y, color);
}
}
row.push_back(newBubble);
}
board_.push_back(row);
}
in the gameengine.cpp which draws the board and the water drop being shot at the bubbles.
The water drops are drawn using
SplashAnimation::SplashAnimation(GameBoard* scene, QPointF startPoint, QPointF endPoint):
QVariantAnimation(0),
scene_(scene),
item_()
{
scene_->addItem(&item_);
// The animation runs for the given duration and moves the splash
// smoothly from startpoint to endpoint.
setDuration(2000);
setKeyValueAt(0, QPointF(startPoint));
setKeyValueAt(1, QPointF(endPoint));
}
I figured there are two ways to do this: either the inbuilt QT Collision detection or doing a separate calculation. I was not able to work with QT Collision and my attempts at detecting the collision manually did not really work out too well.
I already have a function for detecting bubble objects at certain cells, but it's in column/row instead of raw coordinates (500x600).
std::shared_ptr<Bubble> GameEngine::bubbleAt(int x, int y) const
{
if (0 <= x and x < WIDTH and 0 <= y and y < HEIGHT){
return board_.at(y).at(x);
}
else{
return nullptr;
}
}
Edit: Currently I'm trying to work on something like this, but I'm afraid it's going to be a bit heavy for the game since it iterates so much (or not?):
for (int i = 0; i<600;++i)
{
xfract = (xDestination+250.0)/600.0;
yfract = (600.0-yDestination)/600.0;
xStep = xfract*i;
yStep = yfract*i;
if (xStep >= 50){
thisX = xStep/50-5;
}else{
thisX=5;
}
if (yStep >= 50){
thisY = 11-yStep/50 + 1;
}else{
thisY = 11;
}
thisX = abs(thisX);
if (bubbleAt(thisX, thisY)!=nullptr){
endX = xfract*i;
endY = yfract*i;
i = 600;
std::cout << "collision at x: "<<thisX<< " y: "<<thisY<<std::endl;
std::cout << "collision at x: "<<xStep<< " y: "<<yStep<<std::endl;
std::cout << graphicalGameBoard_.width() << " " << graphicalGameBoard_.height()<<std::endl;
removeBubble(thisX, thisY);
graphicalGameBoard_.removeBubble(thisX, thisY);
endY = 600-endY;
}
}
graphicalGameBoard_.animateSplash(graphicalGameBoard_.width()/2, graphicalGameBoard_.height(), endX, endY);
I'm trying to split the steps into small fractions and check if the current step has a bubble in it until the water drop reaches the end or finds a bubble.
This works on my only one of my sides in terms of calculating, but the animation is off the mark and right side (x>250) collision detection doesn't work at all for some reason (it hits seemingly random bubbles at impossible locations on the right side).
Edit^2: Here are things I've tried in order to work with the actual collision detection of QT:
Within splashanimation.cpp, where the water drop is drawn using
SplashAnimation::SplashAnimation(GameBoard* scene, QPointF startPoint, QPointF endPoint):
QVariantAnimation(0),
scene_(scene),
item_()
{
scene_->addItem(&item_);
// The animation runs for the given duration and moves the splash
// smoothly from startpoint to endpoint.
setDuration(2000);
setKeyValueAt(0, QPointF(startPoint));
setKeyValueAt(1, QPointF(endPoint));
}
SplashAnimation::~SplashAnimation()
{
scene_->removeItem(&item_);
}
void SplashAnimation::updateCurrentValue(QVariant const& value)
{
item_.setPos(value.toPointF());
}
where scene is QGraphicsScene, and the parent of this contains the bubbles.
I've tried this on both the gameboard.cpp (which is parent for bubbles and the animation) and splash.cpp (which animates the water drop), but both give me the same compilation errors.
QGraphicsItem::QGraphicsItem();
gives
error: cannot call constructor ?QGraphicsItem::QGraphicsItem? directly [-fpermissive]
QGraphicsItem::QGraphicsItem();
^
QList<QGraphicsItem *> list = collidingItems() ;
gives error: ?collidingItems? was not declared in this scope
QList<QGraphicsItem *> list = collidingItems() ;
^
QList<QGraphicsItem *> list = QGraphicsItem::collidingItems() ;
gives error: cannot call member function ?QList<QGraphicsItem*> QGraphicsItem::collidingItems(Qt::ItemSelectionMode) const? without object
QList<QGraphicsItem *> list = QGraphicsItem::collidingItems() ;
^
I also tried adding arguments, but nothing I had the mind to try worked any better.
In this answer I am going to give you some recommendations that you use to implement the solution:
Avoid using the following instruction, use the signals that is one of the most powerful elements of Qt and that the event loop does the work.
while (animations_.state() == QAbstractAnimation::Running)
{
QCoreApplication::processEvents(QEventLoop::AllEvents);
}
QGraphicsScene works with coordinates that support the floating point, so the coordinates of the scene are handled with QPointF.
Using the above, if you are going to send point information use QPointF instead of int, int in the signals.
Use the methods that Qt provides, for example the following:
if (0 <= clickPosition.x() and clickPosition.x() <= GRID_SIDE*WIDTH and
0 <= clickPosition.y() and clickPosition.y() <= GRID_SIDE*HEIGHT)
It can be reduced to the following:
if(sceneRect().contains(event->scenePos()))
The advantage of that implementation is that it is more readable
I do not understand why you can not implement collidingItems, maybe it's the configuration of your .pro,
Use the following to add the gui module, core and widgets
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
Also to implement the animation use my previous answer
The complete and functional code can be found at the following link.

MFC - How to draw pixel waves inside a rectangle

I am new to MFC trying to learn from the scratch.
I am trying to create a small dialog based application in VS2012 - MFC.
On the dialog window i have drawn a rectangle (in OnPaint event) like this.
CPaintDC dc(this);
CRect background1(10,10,208,92);
dc.Rectangle(10,10,208,92);
Then i filled the bacground with some color. Like this.
CBrush brush1;
brush1.CreateSolidBrush(RGB(2,3,4));
dc.FillRect(background1,&brush1);
Now i wanted to draw waves in form of pixels continuously inside the rectangle.
As of now what i have done is,
bool top = false;
for(i=10,j=92;i<200 && j>10;)
{
pDC->SetPixel(i,j,NewColor);
Sleep(10);
if(!top)
j-=1;
else
j+=1;
if(j%4==0)
{
i+=1;
}
if(j==12)
top=true;
if(j==90)
top = false;
}
I am just drawing the pixels straightaway on the window, but within the dimensions where the rectangle lies. And the waves stop as it reaches the right dimension of the rect. But i feel thats not the right way to do it.
I want to draw the waves inside the rectangle and also continuosly, like when it reacahes the right end it should move left and it should be continuous.
Is there any proper way in MFC to draw something inside a rectangle (technically inside another object)?
Please help me out.
The ScrollWindow function can be used to scroll the existing graph to the left. Then you draw the new data to the right of the scrolled area. The drawing will be much faster if you use the Polyline function instead of DrawPixel: Polyline draws an array of pixels.
I tried your code and just added some condition, so that if it reaches right side it should start moving toward left.
void CMyDlg::OnBnClickedOk()
{
CWnd *cWnd = FromHandle(m_hWnd);
CDC *pDC = cWnd->GetDC();
bool top = false;
bool right = false;
int i,j;
for(i=10,j=92;i<=200 && j>10;)
{
pDC->SetPixel(i,j,RGB(255,255,255));
Sleep(10);
if(!top)
j-=1;
else
j+=1;
if(j%4==0)
{
if(!right)
i++; // if reaches right side i--;
else{
i--;
}
}
if(j==12)
top=true;
else if(j==90)
top = false;
if(i == 200)// make right = true if reaches right side
right = true;
else if(i == 10)// make false it reaches left side
right = false;
}
}
I am getting output something like this
NOTE: this will cause infinite loop, you need to check condition where you have to stop printing pixels.
You are NOT looping with Sleep(10) in your WM_PAINT handler, are you?
MFC or not, you should separate your data processing from presentation.
It appears you are trying to do an animation; the simplest way to do it is to have an off-screen (memory) DC and drawing your pixels on it. At certain times (frame rate?), you would call parent's InvalidateRect()/UpdateWindow() pair. Then in ON_PAINT, you would BitBlt() your prepared DC onto your preferred location in the dialog.

Mouse cursor position deviations when scrolling

I'm trying to write little project for programming class. It's simple graphic library using only ascii characters, working on Windows console (I use win7 64bit). The problems occur when i'm trying to add mouse handling. Here's the code
void importantMouseThings()
{
DWORD numEvents = 0;
DWORD numEventsRead = 0;
GetNumberOfConsoleInputEvents( cgWindow::inputHandle, &numEvents);
if (numEvents != 0)
{
INPUT_RECORD *eventBuffer = new INPUT_RECORD[numEvents];
ReadConsoleInput(cgWindow::inputHandle, eventBuffer, numEvents, &numEventsRead);
for (DWORD i = 0; i < numEventsRead; i++)
{
if (eventBuffer[i].EventType == MOUSE_EVENT)
{
int mousex = eventBuffer[i].Event.MouseEvent.dwMousePosition.X;
int mousey = eventBuffer[i].Event.MouseEvent.dwMousePosition.Y;
std::cout << mousex << " " << mousey << std::endl;
}
}
delete[] eventBuffer;
}
}
The problem is when I move cursor to upper-left corner of console window, cout writes "0 0", but when I use scroll wheel (I mean when i scroll down or up) valuses change to something like "20 14". When I call another mouse event, simply by moving cursor a bit, values come back to return state "0 0".
Maybe I just don't get what dwMousePosition is, maybe it's something with console window (both, window and buffer sizes are set to 80x80, so there's no visible scrollbars).
EDIT:
Okey, I just realized, that value changes depends on window position. So if the window is on the left side of screen, the X divergence is very small and grows as I move window to the right. Any ideas, what is wrong?

How do I perform image clipping efficiently within a parent RECT?

So,
I'm playing around with the DIRECTX API in C++ and designing a sprite interface that does clipping within parent RECT's, like a UI window or another sprite or what have you.
This is because, later on, I'm going to make a scrolling function for a UI window.
I think an image would be appropriate to demonstrate what I am trying to achieve.
In order to do clipping calculations, at least four variables/structs are required (from what I can discern):
Parent RECT: the "clipping" bounds
D3DXIMAGE_INFO: containing the image information, such as width and height
Sprite position
Draw RECT: for the LPD3DXSPRITE->Draw() function. Basically, what part of the image should be drawn. This is where the "clipping" is done.
Now, I think it would be confusing if I showed you my entire interface and its inner workings and how it handles the variables.
So, instead,
this piece of code demonstrates how I'm currently calculating the clipping.
void ClippingCalculation(){
RECT parent_bounds, draw_rect;
D3DXVECTOR2 sprite_position; //Relative to parent rect
D3DXIMAGE_INFO img_info;
//Fill image info
D3DXGetImageInfoFromFile("image.png", &img_info); //Image is 100x100px
//Define the rects
SetRect(&parent_bounds, 0, 0, 200, 200);
SetRect(&draw_rect, 0, 0, img_info.Width, img_info.Height); //Draw the entire image by default
//Give it a position that makes a portion go out of parent bounds
sprite_position = D3DXVECTOR2(150, 150); // 3/4 of the entire image is out of bounds
//Check if completely within bounds
bool min_x = (sprite_position.x > parent_bounds.left),
min_y = (sprite_position.y > parent_bounds.top),
max_x = (sprite_position.x+img_info.Width < parent_bounds.right),
max_y = (sprite_position.y+img_info.Height < parent_bounds.bottom);
if(min_x && min_y && max_x && max_y)
return; //No clipping needs to be done
float delta_top = parent_bounds.top - sprite_position.y,
delta_left = parent_bounds.left - sprite_position.x,
delta_bottom = parent_bounds.bottom - sprite_position.y,
delta_right = parent_bounds.right - sprite_position.x;
//Check if completely outside bounds
bool out_left = (delta_left >= img_info.Width),
out_top = (delta_top >= img_info.Height),
out_bottom = (delta_bottom >= img_info.Height),
out_right = (delta_right >= img_info.Width);
if(out_left || out_top || out_bottom || out_right){
//No drawing needs to be done, it's not even visible
return; //No clipping
}
if(!min_x) draw_rect.left = delta_left;
if(!min_x) draw_rect.top = delta_top;
if(!max_x) draw_rect.right = delta_right;
if(!max_y) draw_rect.bottom = delta_bottom;
return;
}
My questions are:
Do you see anything immediately wrong with the code?
Is it efficient or inefficient?
The clipping is done every time the sprite is repositioned, loaded or when a parent is added.
Is the math solid? Should I approach it differently?
Could it be done in a better way and could you provide examples?
Clipping a RECT is a lot easier than this:
clipped_rect.left= MAX(rect_a.left, rect_b.left);
clipped_rect.right= MIN(rect_a.right, rect_b.right);
clipped_rect.top= MIN(rect_a.top, rect_b.top);
clipped_rect.bottom= MAX(rect_a.bottom, rect_b.bottom);
bool completely_clipped=
clipped_rect.left>=clipped_rect.right ||
clipped_rect.bottom>=clipped_rect.top
This assumes Y increases as you go up. It should be pretty easy to find a platform specific version of MIN and MAX that are performant.

2D Platformer Collision Handling

I am trying to create a 2D platformer (Mario-type) game and I am some having some issues with handling collisions properly. I am writing this game in C++, using SDL for input, image loading, font loading, etcetera. I am also using OpenGL via the FreeGLUT library in conjunction with SDL to display graphics.
My method of collision detection is AABB (Axis-Aligned Bounding Box), which is really all I need to start with. What I need is an easy way to both detect which side the collision occurred on and handle the collisions properly. So, basically, if the player collides with the top of the platform, reposition him to the top; if there is a collision to the sides, reposition the player back to the side of the object; if there is a collision to the bottom, reposition the player under the platform.
I have tried many different ways of doing this, such as trying to find the penetration depth and repositioning the player backwards by the penetration depth. Sadly, nothing I've tried seems to work correctly. Player movement ends up being very glitchy and repositions the player when I don't want it to. Part of the reason is probably because I feel like this is something so simple but I'm over-thinking it.
If anyone thinks they can help, please take a look at the code below and help me try to improve on this if you can. I would like to refrain from using a library to handle this (as I want to learn on my own) or the something like the SAT (Separating Axis Theorem) if at all possible. Thank you in advance for your help!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ballPrev.coords[1] < block[i].coords[3] && block[i].coords[3] < ballPrev.coords[3])
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
To explain what some of this code means:
The blocks variable is basically an integer that is storing the amount of blocks, or platforms. I am checking all of the blocks using a for loop, and the number that the loop is currently on is represented by integer i.
The coordinate system might seem a little weird, so that's worth explaining.
coords[0] represents the x position (left) of the object (where it starts on the x axis).
coords[1] represents the y position (top) of the object (where it starts on the y axis).
coords[2] represents the width of the object plus coords[0] (right).
coords[3] represents the height of the object plus coords[1] (bottom).
de2dCheckCollision performs an AABB collision detection.
Up is negative y and down is positive y, as it is in most games.
Hopefully I have provided enough information for someone to help me successfully. If there is something I left out that might be crucial, let me know and I'll provide the necessary information. Finally, for anyone who can help, providing code would be very helpful and much appreciated.
Thank you again for your help!
Edit 2: I have updated my code with a new algorithm that checks where the ball was previously before collision. Corner cases work on that single platform correctly now, and when I have a wall of objects, I can slide against it correctly now. The only remaining problem is that there is a small jittering effect that happens when I am on the ground, where the ball is constantly going up and down as if it is being pulled by gravity and then the ball falls back into the object again.
Edit: Here is a URL to an image trying to show the kinds of problems I am having:
http://img8.imageshack.us/img8/4603/collisionproblem.png
In case the explanation in the picture doesn't make too much sense, the ball cannot move left past the corner of an object unless I jump over it. However, the ball can move right, but it gets repositioned to the right of the object while moving, which is not needed. This creates a skipping movement essentially, where it appears as the the ball is skipping over half of the object or so when I move right. If this doesn't make sense, please ask me and I'll try to clarify more.
One problem with your code is that you only detect situations like this:
If the circle happens to be fully inside the block, you don't reposition at all. And that's a problem.
You're trying to think about your simulation as if it were continuous, but keep in mind it's discrete. In general, if you only look at the current state of the ball, you really cannot know which side it collided with. Look at these two possibilities:
The first solution that comes to mind is to look at the last position of the ball as well; more precisely, look at the delta vector. See if the delta vector intersects a wall. If it does, reposition in an axis-aligned direction towards the wall intersected by the delta vector.
Edit: When I said "delta vector", I forgot that you're moving a square and not a single point. So, if you just look at the delta vector of the top-left corner, that's not going to be enough because it may not detect that part of the ball entered a block. Instead, you can look at the delta vectors of all 4 corners.