Is there a way to fill a linear gradient along a diagonal? - c++

I am trying to write code that will fill a rectangular region with a gradient that varies along a diagonal of that region. I had thought that I could play with the direction parameter as follows:
context->GradientFillLinear(
wxrect,
get_wx_colour(gradient.front()),
get_wx_colour(gradient.back()),
wxNORTH | wxEAST);
When I do this, the compiler converts the direction subexpression to an int and fails to compile because of a type mismatch. I suspect that gradients can only be filled horizontally or vertically and this is why the parameter is written expecting an enum value. Can anyone confirm this suspicion?

As of wxWidget-3.0.2, the implementation of GradientFillLinear eventually calls a specific implementation which looks somewhat like:
wxDCImpl::DoGradientFillLinear()
{
...
if ( nDirection == wxEAST || nDirection == wxWEST )
{
...
}
else // nDirection == wxNORTH || nDirection == wxSOUTH
{
...
}
So, your suspicion appears to be correct and even if you did manage to somehow coerce the direction as wxNORTH | wxEAST in the argument of GradientFillLinear, the implementation would not have supported it.

As SleuthEye's answer correctly says, this can't be done directly, but you can always apply a transformation to rotate the horizontal or vertical gradient by 45 degrees.

Related

C++ collision issue

I am testing collision between numerous moving squares in a quadtree.
When two square collides, I invert their velocity, like this:
for (auto pair : collisionPairs)
{
auto& square1 = static_cast<Square&>(*(pair.first));
auto& square2 = static_cast<Square&>(*(pair.second));
square1.setVelocity(-square1.getVelocity());
square2.setVelocity(-square2.getVelocity());
}
The problem is, collision detection is not always during one frame.
Sometimes, they are collision between same squares more than one frame, because the squares have been intersecting to deep.
So squares overlap and they keep reversing their velocity infinitely, which results a 0 velocity ( -velocity + velocity = 0 )
How could I fix this ?
EDIT : I've discovered that the deep intersection issue was caused by my quadtree, I forgot to check collision with the objects of children trees.
Now it STILL happens but very rarely, like 1 in 100 collisions, before it was ~20 from 100 collisions
In addition to the pure collision detection I'd also check, whether the centers of the squares move towards each other or not and only revert their velocity in the first case. For me to provide an example you'd have to provide information about your implementation of the Square class.
Edit: Essentially the logic would look something like this:
if (collision detected) {
if ( (square2.posx-square1.posx)* (square2.vx-square1.vx) < 0) {
// EDIT: exchange velocities of square1 and square2 in x direction
}
if ( (square2.posy-square1.posy)* (square2.vy-square1.vy) < 0) {
// EDIT: exchange velocities of square1 and square2 in y direction
}
}
This is of course far from a realistic collision simulation, but if you just want to see whether your collision detection works correctly it should suffice.
Btw. I'm assuming, that the rectangle edges are all oriented along the x and y axis.
You could give your Square class an additional inCollision() state or so, and check this additionally:
if(!square1.inCollision()) {
square1.setVelocity(-square1.getVelocity());
square1.setInCollision(true);
}
// Analogous code for square2
// Set inCollision state to false, when you build the collisionPairs
// Simplyfied pseudo code:
if(intersect(square1,square2) {
// make_pair blah blah
}
else {
square1.setInCollision(false);
square2.setInCollision(false);
}

SDL Screen Render Position Error Along Top of Window

I am making a top down isometric game using SDL 2.0 and C++ and have come across a glitch.
When a texture is rendered to the screen using the SDL_RenderCopyfunction, the moment the top of the texture hits the top of the screen it gets pushed down by one pixel, thus causing the missing borders seen in the following picture:
Pre-edit with no annotations
Post-edit with with annotations
The following is my render function specific to the world itself, as the world renders differently from everything else in the game, because I am simply copying a "source" texture instead of loading a texture for every single tile in the game, which would be absurdly inefficient.
//-----------------------------------------------------------------------------
// Rendering
DSDataTypes::Sint32 World::Render()
{
//TODO: Change from indexing to using an interator (pointer) for efficiency
for(int index = 0; index < static_cast<int>(mWorldSize.mX * mWorldSize.mY); ++index)
{
const int kTileType = static_cast<int>(mpTilesList[index].GetType());
//Translate the world so that when camera panning occurs the objects in the world will all be in the accurate position
I am also incorporating camera panning as follows (paraphrased with some snippets of code included as my camera panning logic spans multiple files due to the object orientated design of my game):
(code from above immediately continued below)
mpTilesList[index].SetRenderOffset(Window::GetPanOffset());
//position (dstRect)
SDL_Rect position;
position.x = static_cast<int>(mpTilesList[index].GetPositionCurrent().mX + Window::GetPanOffset().mX);
position.y = static_cast<int>(mpTilesList[index].GetPositionCurrent().mY + Window::GetPanOffset().mY);
position.w = static_cast<int>(mpTilesList[index].GetSize().mX);
position.h = static_cast<int>(mpTilesList[index].GetSize().mY);
//clip (frame)
SDL_Rect clip;
clip.x = static_cast<int>(mpSourceList[kTileType].GetFramePos().mX);
clip.y = static_cast<int>(mpSourceList[kTileType].GetFramePos().mY);
clip.w = static_cast<int>(mpSourceList[kTileType].GetFrameSize().mX);
clip.h = static_cast<int>(mpSourceList[kTileType].GetFrameSize().mY);
I am confused as to why this is happening, as regardless of whether I include my simple culling algorithm or not (as shown below), the same result occurs.
(code from above immediately continued below)
//Check to ensure tile is being drawn within the screen size. If so, rendercopy it, else simply skip over and do not render it.
//If the tile's position.x is greather than the left border of the screen
if(position.x > (-mpSourceList[kTileType].GetRenderSize().mX))
{
//If the tile's position.y is greather than the top border of the screen
if(position.y > (-mpSourceList[kTileType].GetRenderSize().mY))
{
//If the tile's position.x is less than the right border of the screen
if(position.x < Window::msWindowSize.w)
{
//If the tile's position.y is less than the bottom border of the screen
if(position.y < Window::msWindowSize.h)
{
SDL_RenderCopy(Window::mspRenderer.get(), mpSourceList[kTileType].GetTexture(), &clip, &position);
}
}
}
}
}
return 0;//TODO
}
You may have a rounding error when you are casting the positions to ints. Perhaps you should round to the nearest integer instead of just taking the floor (which is what you're cast is doing). A tile at position (0.8, 0.8) will be rendered at pixel (0, 0) when it should probably be rendered at position (1, 1).
Or you could ensure that the size of your tiles is always an integer, then errors shouldn't accumulate.
Short version of answer, restated at bottom:
By fixing my data types issue, that allowed me to fix my math library, which removed the issue of rounding parts of pixels, since there is no such thing as less than 1 but greater than 0 pixels on the screen when rendering.
Long Answer:
I believe the issue to have been caused by a rounding error with the offset logic used when rotating a 2D grid to a diagonal isometric perspective, with the rounding error only occurring when dealing with screen coordinates between -1 and +1.
Since I based the conversion from changing an orthogonal grid to a diagonal grid on the y axis (rows), this would explain why the single pixel offset was occurring only at the top border of the screen and not bottom border.
Even though every single row had implicit rounding occurring without any safety checks, only the conversion from world coordinates to screen coordinates dealt with rounding between a positive and negative number.
The reason behind all of this is because my math library which was templatized had an issue a lot of my code being based on type defined user types such as:
typedef unsigned int Uint32;
typedef signed int Sint32;
So I simply used DSMathematics::Vector2<float> instead of the proper implementation of DSMathematics::Vector2<int>.
The reason this is an issue is because there cannot be "half a pixel" on the screen, and thus integers must be used instead of floating point values.
By fixing my data types issue, that allowed me to fix my math library, which removed the issue of rounding parts of pixels, since there is no such thing as less than 1 but greater than 0 pixels on the screen when rendering.

c++ Collision Detection for a turning rectangle

I have some collision detection working when my player hits an object. But this only works when my players x & y co-ordinates hit my marker (which is the centre of my character).
Would making a method returning a vector of all of the coordinates that the players texture cover work and what is the best way to implement this?
This is being done in c++ creating a top down game
There are many ways to do it, most simply is probably(depending on you use of classes etc).
This is the simplest, but no where near the best, or infact very good at all. This way means changing your "marker" to the bottom left of the rectangle.
void collisions()
{
//check if the x-coord is between the furthest left and furthest right x coords
if(rect.Getx() > someObject.Getx() && rect.Getx() < someObject.Getx() + someObject.GetWidth())
{
rect.SetMoveSpeed(0);
}
if(rect.Gety() > someObject.Gety() && rect.Gety() < someObject.Gety() + someObject.GetHeight())
{
rect.setMoveSpeed(0);
}
}
You would then have to set the move speed to normal when it is not colliding. That could be done with an else after each if, setting the move speed again. This is a quick fix and is not recommended for use in a game you plan to distribute anywhere.

C++ Collision Detection doesn't work on last check?

Over the last few days I have been trying to implement simple collision detection of objects drawn using OpenGL.
With the aid of the Pearson, Computer Graphics with OpenGL I have managed to write the following function:
void move(){
if(check_collision(sprite,platform1) || check_collision(sprite,platform2)){ //if colliding...
if (downKeyPressed ){ y_Vel += speed; downKeyPressed = false;} //going down
else if(upKeyPressed ){ y_Vel -= speed; upKeyPressed = false;} //going up
else if(rightKeyPressed){ x_Vel -= speed; rightKeyPressed = false;} //going right
else if(leftKeyPressed ){ x_Vel += speed; leftKeyPressed = false;} //going left
} // always glitches on whatever is last else if above?!?!
else{ glTranslatef(sprite.x+x_Vel, sprite.y+y_Vel, 0.0); }
}
My sprite moves in accordance to keyboard inputs (the arrow keys). If it collides with a stationary object it stops moving and stays in its position.
So far, it works when colliding with the top, left side and bottom of the stationary object. Unfortunately (even though I use the same logic) the right hand side doesn't work and upon a collision the sprite is redrawn at its original x/y coordinates. I'm baffled.
As it turns out, which-ever is the last check in the move() function (the last else-if) is the one that doesn't work... I have swapped the left with the right and sure enough when left is then the last one and the one that plays up :(
Any advice or ideas on how I can improve this and stop it glitching?
Please excuse my naivety and amateur coding. I'm merely a self-taught beginning. Thanks.
You should not use an else if. There is a possibility that it is hitting a side and the top or the bottom in the same frame. Trying changing those to all ifs because you want to check each one. or at the least change it to this.
if( /* check top */)
{
}
else if( /* check bot */)
{
}
if( /* check right */ )
{
}
else if( /* check left */)
{
}
Also, you should avoid declaring global variables like Y_VEL and X_VEL as this creates confusion. You may just be doing this to get your feet wet but I would avoid it. Create a class for each object and then have the velocities as members of that class.
Well, it seems to me that you have an issue when it comes to translating the actual object.
Your move code states
if(there is a collision)
{
//do stuff
}
else
{
glTranslateF( );
}
SO, whenever there is a collision, the translate function never gets called.
My opinion is that you should pull the glTranslateF() call out of the else {...}, just have it get called every time. However, it seems you're using the exact same 'draw' function for every rectangle, not just the player sprite. You'll probably have to ind a way to distinguish between regular rectangles (such as the platforms) and the player rectangle. Perhaps the simplest way for you to implement this, would be to have two different drawSprite functions: one for regular platforms, and the other for the player. Only call the move() function from within the player's draw function (perhaps called drawPlayer()?)
I don't quite have the time to look over all of your code to make a more educated and specific suggestion at the moment; however, I'll be free later this evening if this question is still open and needing help.
As you've already figured out, the problem is related to glTranslate(). Since you operate on both sprite's position and velocity, you should repeatedly update the positions using the velocities. That is:
sprite.x += x_vel;
sprite.y += y_vel;
and do it simply all the time (i.e. by some timer or every frame, if the scne is redrawn repeatedly). A collision then is equivalent to changing the velocity vector (x_vel, y_vel) in some way to simulate the collision effect: either zero it to stop any movement at all, or change the velocity component sign (x_vel = -x_vel) to make it rebound in an absolutely elastic manner, or do something else that fits.
What happens now with glTranslate() is that x_vel, y_vel actually hold offsets from the starting position, but not velocities of movement.

can't understand following c++ code line

I'm new with C++, and try to figuring out what this line of code means:
cur_rect = cv::Rect(cur_rect) & cv::Rect(0, 0, mat->cols, mat->rows); // here
if( cv::Rect(cur_rect) == cv::Rect() ) //here
{
.......
}
The Rect & Rect part intersects two rectangles and gives a non-empty rectangle back when the two inputs overlap.
So you can compare the result to Rect() to see whether there was an intersection. Your code crops cur_rect to (0, 0, mat->cols, mat->rows) and then checks whether it is empty or not.
Sources:
http://opencv.willowgarage.com/documentation/cpp/core_basic_structures.html?highlight=rect
How can one easily detect whether 2 ROIs intersects in OpenCv?
Edit
An alternative implementation, a bit cleaner:
// crop cur_rect to rectangle with matrix 'mat' size:
cur_rect &= cv::Rect(0, 0, mat->cols, mat->rows);
if (cur_rect.area() == 0) {
// result is empty
...
}
I am assuming that cv::Rect(...) methods (or family of them) returns a rectangle object. The line that you do not understand, I assume is an overloaded operator (==) that compares rectangles.
But I am making a lot of assumptions here as I do not have the code for cv class.
As to the & overloaded operator - one assumes that this is doing an intersection or union. Once again without the code it is hard to say.