Chaining Logical Operations in Lua - if-statement

Is this the most efficient way to do this in Lua? Thank you!
if X >= 0 and Y >= 0 then
if X1 <= 960 and Y1 <= 720 then
someCode()
else end
else end

It is a good idea to avoid nested if statements, I would try a single if check.
The best way to be sure is to profile the functions and see what works faster.
-- Be paranoid and use lots of parenthesis:
if ( ( (X >= 0) and (Y >= 0) ) and ( (X1 <= 960) and (Y1 <= 720) ) ) then
someCode()
end
This is the same but easier to read. Good code is not only fast, but easy to read.
local condition1 = ((X >= 0) and (Y >= 0))
local condition2 = ((X1 <= 960) and (Y1 <= 720))
if (condition1 and condition2) then
someCode()
end

You can also use operators to make it a tad bit shorter:
if ((X >= 0 && Y >= 0) && (X1 <= 960 && Y1 <= 920)) then
someCode()
end
The answer by Yowza should also suffice tho, if you're looking for readability.

Related

2D obstacle collision

Hi I am trying to make 2d collision but I dont get it to work
i am doing :
if (collider.posX + collider.sizeX >= obstacle.posX && obstacle.posX + obstacle.sizeX >= collider.posX && collider.posY + collider.sizeY >= obstacle.posY)
the obstacle cannot move on the y axis so this is why i only check for
collider.posY + 50 >= obstacle.posY
the collision works but they are only start when the obstacle is half in the collider
What about:
if( obstacle.posX >= collider.posX &&
obstacle.posX <= collider.posX + collider.sizeX &&
obstacle.posY >= collider.posY &&
obstacle.posY <= collider.posY + collider.sizeY
)
This code should check if obstacle point intersects collider rectangle.
This is better solution because it detects overlapping between 2 rectangles:
if ( obstacle.posX <= collider.posX + collider.sizeX &&
obstacle.posX + obstacle.sizeX >= collider.posX &&
obstacle.posY <= collider.posY + collider.sizeY &&
obstacle.posY + obstacle.sizeY >= collider.posY )
You're running into logical errors, seen by the following code:
collider.posX + collider.sizeX >= obstacle.posX
Suppose the two colliding objects are circles with their positions being their center points. The first object is moving in the positive X direction while the second is static (stationary). You need to check if the first object's X position plus its radius (not diameter) touches the second object's X position minus its radius.
Example code:
collider.posX + (collider.sizeX / 2) >= obstacle.posX - (obstacle.sizeX / 2)
Note: The above inequality assumes that collider.sizeX represents the diameter of collider.
Presumably later on you'll also need to check if the first object is passed the second object. Since the above inequality only accounts for the first object having an increasing X position and its X position being less than the second object's X position.

Optimization while mixing c style strings with c++ strings

I was trying to solve a programming problem from a website and got time limit exceed. Now I'm trying to change some parts of my code where I use C++ string to C style strings.
Here is a part from my code that I wanted some advice:
x1 = X1 + X2 + X3;
x2 = X1 + X3 + X2;
x3 = X2 + X1 + X3;
x4 = X2 + X3 + X1;
x5 = X3 + X2 + X1;
x6 = X3 + X1 + X2;
Before, all of those variables above were C++ strings, now I have changed the uppercase ones to C-style, so those assignments are no longer valid...
What would be the fastest way to initialize the lower-case ones?
x1 = X1;
x1 += X2;
x1 += X3;
or
char buffer[20]; //would use x1 instead of a buffer if the answer to the second question
//is to convert it(x1) to C-style
strcpy(buffer, X1);
strcat(buffer, X2);
strcat(buffer, X3);
x1 = buffer;
the only use for the lowercase ones is in this comparison:
if(current == x1 || current == x2 || current == x3 || current == x4 || current == x5 || current == x6)
where 'current' is C++ string (And this one I won't change because I'm updating its value through elements inside a container)
this IF is going to be executed MANY times, so I want to know if it is better to let x1 ... x6 as C++ strings (I suppose if I compare C++ string with a C-style string it will call a constructor from C++ string and pass the C-style as argument before the comparison).
EDIT:
Reformulating: I what I want to know in the second is:
When I make a comparison like this:
string st = "something";
char st2[20] = "other thing";
if(st == st2)
Is it going to call the constructor string(st2) and the compare constructed string to the one at the left? Lets say I do this comparison 500000x, would it be faster if st2 were already a C++ string?
EDIT2: The complete code is here
If you want speed, don't create a string just in order to do a comparison; especially, don't create six strings since you might sometimes only need one or two of them. It's not relevant whether they are C strings or C++ strings.
Do you know how long X1, X2 and X3 are? It's easy enough to find out, if not. Assuming you do, what you want to know is something like:
if ( current.compare(0, lenX1, X1) == 0 &&
( current.compare(lenX1, lenX2, X2) == 0
&& current.compare(lenX1+lenX2, lenX3, X3) == 0
|| current.compare(lenX1, lenX3, X3) == 0
&& current.compare(lenX1+lenX3, lenX2, X2) == 0)
|| current.compare(0, lenX2, X2) == 0 &&
( current.compare(lenX2, lenX1, X1) == 0
&& current.compare(lenX2+lenX1, lenX3, X3) == 0
|| current.compare(lenX2, lenX3, X3) == 0
&& current.compare(lenX2+lenX3, lenX1, X1) == 0)
|| current.compare(0, lenX3, X3) == 0 &&
( current.compare(lenX3, lenX1, X1) == 0
&& current.compare(lenX3+lenX1, lenX2, X2) == 0
|| current.compare(lenX3, lenX2, X2) == 0
&& current.compare(lenX3+lenX2, lenX1, X1) == 0))
Your version is more readable, of course, and mine might have typos.
I suspect that this, too, is unnecessary; you need to reexamine your design. Why are you using concatenated strings instead of, for example, tuples of small integers?

Recursive floodFill function? C++

So recursion is not my strong point, and I have been challenged to make a recursive floodFill function that fills a vector of a vector of ints with 1's if the value is zero. My code keeps segfaulting for reasons beyond me. Perhaps my code will make that sound more clear.
This is the grid to be flood filled:
vector<vector<int> > grid_;
It belongs to an object I created called "Grid" that is basically a set of functions to help manipulate the vectors. The grid's values are initialized to all zeros.
This is my flood fill function:
void floodFill(int x, int y, Grid & G)
{
if (G.getValue(x,y))
{
G.setValue(x,y,1);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x+1,y,G);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x,y+1,G);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x-1,y,G);
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x,y-1,G);
}
}
The intention here is to have the function check if a point's value is zero, and if it is, change it to one. Then it should check the one above it for the same. It does this until it either finds a 1 or hits the end of the vector. Then it tries another direction and keeps going until the same conditions as above and so on and so forth until its flood filled.
Can anyone help me fix this? Maybe tell me whats wrong?
Thanks!
if(x < G.getColumns()-1 && x >= 0 && y < G.getRows()-1 && y >= 0)
floodFill(x-1,y,G);
won't work, since you can access index -1 of the underlying vector if x == 0
Same goes for floodFill(x,y-1,G);
This code has a lot of problems. First of all you check with if(G.getValue(x,y)) whether the value at a position is 1, and if so, then you set it to 1 with G.setValue(x,y,1). Think about this for a second, this can't be right. When will you ever set non-zero values to 1?
Then, another more subtle point is that you shouldn't do the recursion into neighbors if they are already set to 1.
As it stands the code you have will likely run until you overflow the stack because just going to recurse forever on the 1's that are connected to wherever you start from.
How about this?
void floodFill(int x, int y, Grid &g) {
if(x >= g.getColumns() || y >= g.getRows()) {
return;
}
floodFill(x+1, y, g);
if( x == 0 ) {
floodFill(x, y+1, g);
}
g.setValue(x, y, 1)
}
I think that will fill the grid without every hitting the same coordinate multiple times, and whenever either index is out of bounds it just returns so no chance of a seg fault.

C++ 2D Box-Collision, is this right?

Well I've got a 2D box collision code that basically loops through every block in a list called "Blocks" and it checks if I'm near the sides and whatnot.
It works very well except for the bottom of the block. When I'm jumping up towards the bottom I want my player to simply "bounce" off. It does this, but it is very glitchy. It's hard to explain so I was hoping you guys could possibly spot out what's wrong with my bottom collision code.
Here's the entire thing (this is ran in a loop):
for(unsigned int i = 0; i<blocks.size(); i++){
Block &b = blocks.at(i);
if(!b.passable==true){
//Check if we are on the sides
if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)
{
//Right side
if(x + hspeed <= b.worldX+b.width-1 && x + hspeed > b.worldX+b.width + hspeed-2)
{
x = b.worldX + b.width; hspeed = 0;
}
//Left side
if(x + width + hspeed >= b.worldX +1 && x + width + hspeed <= b.worldX + hspeed + 2)
{
x = b.worldX - width; hspeed = 0;
}
}
//Check if we are on the top or the bottom
if(x + width + hspeed >= b.worldX+2 && x + hspeed <= b.worldX+b.width-2)
{
if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")
{
y = b.worldY - height; jumpstate.assign("ground"); vspeed = 0;
}
if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")
{
y = b.worldY + b.height; jumpstate.assign("falling"); vspeed = 0;
}
}
}
}
I'm not sure you'll get it to work like this. I'll explain a solution that I thought of for some collision detection and bouncing that works smoothly. Record the time interval from when you last checked collisions and adjusted position. If Xplayer+Vplayer*deltaT>Xtarget (if the player would overlap the target) then compute the actual time when it would be touching the target deltaTtouch=(Xtarget-Xplayer)/Vplayer. Now bounce the player back Xplayer=Xtarget-Vplayer*(deltaT-deltaTtouch). You'll have to figure out all the cases when moving forward, backward, up, down.
LE: You can also implement gravity, this involves solving a quadratic equation for finding out the deltaTtouch.
Well I can see a few little details:
1) In this line the hspeed when checking the old position is quite redundant, best to remove it for clarity.
if(x + hspeed <= b.worldX+b.width-1 && x + hspeed > b.worldX+b.width + hspeed-2)
Becomes:
if(x + hspeed <= b.worldX + b.width - 1 && x > b.worldX + b.width - 2)
Same goes for the other similar lines.
2) The small offsets of -2 and -1 are a bit confusing I presume you are trying to achieve a small buffer such that a slight amount of overlap is required. Especially this line where you have used a < instead of the <= you have used every else:
if(x + hspeed <= b.worldX+b.width-1 && x + hspeed > b.worldX+b.width + hspeed-2)
To keep consistancy with the rest of the program I would probably write:
if(x + hspeed <= b.worldX + b.width - 1 && x >= b.worldX + b.width - 1)
3) You seem to be missing a few of your small offsets in the vert checks:
So this check first:
if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")
You seem to have forgotten your small offset:
if(y + height + vspeed >= b.worldY + 1 && y + height <= b.worldY + 1 && jumpstate=="falling")
Then the second check:
if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")
Offset again:
if(y + vspeed <= b.worldY + b.height - 1 && y >= b.worldY + b.height - 1 && jumpstate=="jumping")
4) You will need to be very careful that vspeed and jumpstate always remain in sync as the sign of vspeed needs to always match jumpstate or you will miss collisions. I imagine this might be where your problem is coming from.
5) In both directions if speed exceeds the block size you will skip collision detection and fire through the block.
if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)
The second check in these lines will be false if speed is higher than b.height and the y coords are similar.
Hope that helps some.

Rectangle intersect code - Is this right?

Can someone tell me whether my rectangle intersect code is correct?
bool checkCollide(int x, int y, int oWidth, int oHeight,
int x2, int y2, int o2Width, int o2Height) {
bool collide = false;
if (x >= x2 && x <= x2+o2Width && y >= y2 && y <= y2+o2Height)
collide = true;
if (x+oWidth >= x2 && x+oWidth <= x2+o2Width && y >= y2 && y <= y2+o2Height)
collide = true;
if (x >= x2 && x<= x2+o2Width && y+oHeight >= y2 && y+oHeight <= y2+o2Height)
collide = true;
if (x+oWidth >= x2 && x+oWidth <= x2+o2Width && y+oHeight >= y2 && y+oHeight <= y2+o2Height)
collide = true;
return collide;
}
Nope, a corner of a rectangle doesn't have to be in the other rectangle for the rectangles to collide. What you want to do is to find the logic when they do not intersect and use the negation of that. The picture below shows two rectangles that clearly intersect each other, but only the sides are intersecting, not the corners.
Just formulate the logic as follows: What does it take for the blue to not intersect the red? Well it's either completely to the right, completely to the left, up or below. Formulate an if statement to that and negate it.
Let me help you with the beginning:
if (!(x2 > x+oWidth || x2+o2Width < x || ..))
collide = true;
Following on from Magnus's answer, I'd take a slightly different approach.
As he says, if the two don't intersect then one will be completely left, completely right, etc. For performance however you can stop testing as soon as any of these conditions are found to be false, e.g.:
if (x2 + owidth2 < x)
return false; // box 2 is left of box 1
if (x + owidth < x2)
return false; // box 1 is left of box 2
// etc...
First implement interval intersection (i.e. one dimension).
Then you can implement rectangle intersection by first applying interval intersection to the x-coordinates and then applying interval intersection to the y-coordinates.
checkCollide(0, 0, 3, 3, 1, 1, 1, 1) == false
I'm guessing that's not what you want.