Where am I wrong about this bitwise expression? - bit-manipulation

Game Maker Studio 2 has a downloadable demo of a dungeon top down game. In it there is a collision check script. The part of it for walking left is as follows:
x += -4;
var tx = (x-16)>>5; /* check right edge (my note: this gets the tile x-index
for the wall on the left, as each tile is 32 pixels wide. I think they
copied the part for walking right and didn't fix the comment)*/
var ty1 = ((y+16)>>5);
var ty2 = ((y-16)>>5);
// collision data never has flips etc...
var tile1 = tilemap_get(WallMap, tx,ty1 )& tile_index_mask;
var tile2 = tilemap_get(WallMap, tx,ty2 )& tile_index_mask;
if(( tile1!=0 ) || (tile2!=0))
{ x = (x&~31)+16; }
(I replaced some variables and macros with their value. The +16 parts are for sprite adjustment. The sprite origin of the player (x,y) is set 16 pixels away from its edges).
The last line is what bothers me.
31 in bit is 00000000000000000000000000011111.
~31 in bit then is 11111111111111111111111111100000.
so x&~31 should really just set the last 5 digits of the x bit to 0.
But x=0,y=0 is the upper left part of the room. The smaller x is, the closer it is to the left side.
So what I gather from this is that when x collides with a wall on its left while walking left, this function sets its origin closer to the left, into the wall. Which doesn't make sense.
To my understanding, the last line should have been { x = (x&~31)+32+16; }, to snap the player origin to the left side of the wall tile, move it 32 pixels to the right side of the wall, then 16 pixels more to adjust to the sprite width.
Yet running the game, it works as intended. Trying to walk left into a wall keeps you in place. Where am I mistaken?

I don't think this issue is really about the bitwise aspect of it. The way I interpret this code, is that x represents the "origin" of the sprite and x - 16 its left edge. Then tx = (x-16)>>5 computes the x coordinate of the tile that the left edge is in, which is collision tested and so forth.
However, at that same moment, the origin of the sprite is still in the tile that you're standing on (the movement offset is smaller than half the sprite width, so the tentative movement does not move the origin into a different tile in one step), and that is the x which is used in (x&~31)+16. Therefore, x&~31 rounds down to the left border of the tile you're standing on, not the left border of the wall tile.

Related

Move 3d object right/left + up/down independent of its rotation

Goal:
Move a 3D object as if it is in 2D space (screen). So if the user moves the mouse left the object should move left (the same should apply for all other directions: right, up, down).
Description:
I am working with OpenTK (OpenGL - 3D space)
Since the object itself should always rotate around it's center I first apply the rotation then the translation matrix.
What works
With trying out I was able to get the translation for the x-Axis and y-Axis (both 2d space) working separately.
// works for x-Axis movement
var rotation = _control.Rotation;
// vector is a 2d vector that contains the vector from the mouse drag start position
// (so the pixels the mouse was moved from the drag start to its current position)
// factor is a value that depends on the current zoom value - can be ignored for the problem itself
var xTranslationVector = new Vector3(
vector.X * (float)Math.Cos(rotation.Y) * factor,
0,
vector.X * (float)Math.Sin(rotation.Y) * factor);
// initial value is the original translation on drag start
_control.Translation = initialValue + xTranslationVector;
// vector for y-Axis
var yTranslationVector = new Vector3(0,
-vector.Y * (float) Math.Cos(rotation.X) * factor,
vector.Y * (float) Math.Sin(rotation.X) * factor);
// _control.Translation = initialValue + yTranslationVector;
Both work when used independent from each other.
Questions
How do I need to combine the xTranslationVector and yTranslationVector so that it would work as expected (multiplication doesn't work because any vector component could be 0 which results in no movement at all; addition does not work when the object is rotated around some axis partially)
I would like to understand what I am doing there, what are the mathematical terms i should look for to find explanations?
How can I do the same for rotation (f.e. the object is rotated 45° degrees around the y axis and I want to rotate - currently the object would tilt around it's x axis but i would like to tilt it always as if the object was not rotated around it's x axis - sorry not sure how to word this well)

recalculate ray tracing/casting costs when changing size of rectangle

I have an array of "rays" which I need to measure the costs in relation to the rectangular boxes below. The outer red box is always 1m larger than the dark green box and light green box is 10cm smaller than the dark green box. If a ray
passes through the dark green box I would assign cost c
ands on the dark green box I would assign cost d
lands on the red area i would assign
cost e
does not intersect the dark green box and not land in red box, cost f
and d < f < c < e
I currently have the following data structures and functions to calculate the cost. I am required to calculate the cost for the given rectangles (represented by 4 xy coordinates), but at the same time, find the approximate/local optimal length/width of the dark green rectangle(i.e shrink or grow the dimension by holding the closest corner of the rectangle fixed) such that the cost is minimum.
A concrete example is the screenshot below. The smaller rectangle corresponds to the dark green box in the figure. Green lines are the rays with cost d, yellow lines cost f and the turquoise lines are the ones with cost c. If I fix the top left hand corner of the inner rectangle and reduce the width, I can reduce the turqoise rays from cost c to f.
My question is, I am stuck at how should I alter my code or change my data structure, such that I can find the best dimensions by only recomputing the affected rays (i.e without looping through all the rays again).
struct VRay{
float range, x, y;
enum RayType{ PASSTHROUGH, FREE, SURFACE, OCCLUDED, UNIFORM};
RayType r;
};
struct VScan{
VRay rays[401];
int closestIdx;
int firstIdx;
int lastIdx;
} vscan;
The function to calculate the costs:
for (int i = 0; i < 401; i++){
VRay& r = vscan.rays[i];
Vector2f cray(r.y, -r.x);
bool ppBound = false;
bool ppSurf = false;
Vector2f vertex = outBox.row(0);
Vector2f vertexSurf = surface.row(0);
float init = cray.dot(vertex);
float initSurf = cray.dot(vertexSurf);
//this part finds whether ray intersects rectangle or not
for (int j = 1; j < 4; j++){
Vector2f v2 = outBox.row(j);
Vector2f vSurf = surface.row(j);
float i2 = cray.dot(v2);
float iSurf = cray.dot(vSurf);
if (i2 * init < 0){
ppBound = true;
}
if (iSurf * initSurf < 0){
ppSurf = true;
}
}
//ray does not intersect all rectangles
if (!ppBound){
z += log(1/100.);
continue;
}
//ray is inside red box
if (inPolygon(outBox, r)){
//ray inside dark green box
if (inPolygon(surface, r)){
//ray inside light green box
if (inPolygon(inBox,r))
c = passTCost;
else
c = surfaceCost;
}
else{
c = freeCost; //free space
}
}
else if (ppSurf){
c = passTCost; //before all boxes
}
else { //ray does not intersect dark green box
z += log(1/100.);
continue;
}
z += -(c * c)/(2 * deviation * deviation);
}
If I understand you right, you want vary the size of the dark green rectangle such that it retains a common center with the light green rectangle the edges of both remain parallel. The dark green rectangle will never leave the red one at any point and will never be smaller than the light green one. Red and light green rectangle remain constant. You only want to recalculate those rays that might change their cost if you vary the dark green rectangle (DGR from now on...).
So my proposition is as follows:
Have another std::vector<VRay*> being empty at the start, and a second sum variable. In a first run, calculate your costs as you do. Additionally, for each ray, decide if it might change at all when varying the DGR.
If it could, add a pointer to it to the vector above, otherwise, add its current cost to the second sum. From now on, you only have to re-calculate those rays in the pointer vector and add the pre-calculated sum of the other ones to this new sum.
How to decide, if a ray might change cost? Well, those not crossing the red rectangle will not, of course. Those ending in the light green rectangle won't either, as well as those crossing both the light green and the red rectangle. So the relevant rays are those ending within the red rectangle, but not within the light green one and additionally those entirely crossing the red one but not intersecting the light green one.
A further optimisation can be gatherd if you consider the maximum DGR (if it is not necessarily parallel to the red one): Those lines not intersecting this maximum rectangle or ending in front of it won't ever change either.
Am I correct that a ray can never land in the light green box? i.e. rays are stopped when they reach the light green area? Are there any rules determining if a ray lands on the red area, on the dark green area, or passes through both of them?
If these rules are independent of the size of the car, but only depend on the relative position of the "end point" of the ray, e.g. if rays to the middle of the front of the car surface do always land on the free space around the car, then the relation of the quantity of rays with cost d, c, or e are independent of the size of the car. The quantity of rays with cost f (marked yellow) is just the rest of the rays, i.e. rays that do not have cost d, c, or e.
This means that in a first step, calculate the optimal (minimal) sum of costs, given the constant ratio of costs for d/c/e and knowing that the remainder of the rays have costs f.
Example: you have 5% of rays with cost c (turquoise lines), 10% of rays with cost e (red lines), and 40% of rays with cost d (green lines), and 45% of rays with cost f (yellow lines). Therefore for each ray with cost c you have two rays with cost e and eight rays with cost d. All the remaining rays have cost f.
-> let x be the number of rays with cost c, then total costs are: 1*c*x + 2*e*x + 8*d*x + (totalNumberOfRays - (1+2+8)*x) * f
Now find the minimum of this function (which is easy because it is a linear function, but probably you have some constraints on the size of your car), and use the resulting x to calculate the size of your car: if you had in the beginning e.g. 10 rays with cost c, and the resulting x is 5, you have to find the car size which produces only 5 rays of costs c, i.e. the car width and length each should be multiplied by 0.5.
Now, the only thing I hope, is that my assumptions were right :-)
(Other options that I thought of, in case my assumptions are wrong, are grouping the rays together in a certain way, and only do the calculations per group)

confused about a simple formula to move player to mouse position

I encountered a simple formula on the internet to move a player to mouse position based on calculating the distance between characters X position and Mouse X position and dividing it by the distance between the two entities like below
//the below statement moves the player to the left towards the mouse pointer
if(player.position.x > Mouse_Position_X)
player.setPosition(player.position.x - ( ( player.position.x - Mouse_Position_X)/distance * 2.0f ));
...
..
.
// similar statements for other three checks to move player to right, top and bottom
// distance value is found out by a getDistance function which calculates the distance between two entites(player and mouse pointer in this case)
I would like to know what the above formula does as compared to a simple formula like below
which also moves the player to the left.
if(player.position.x > Mouse_Position_X)
player.setPosition(player.position.x - 2.0f);
Why would we subtract the players current position with the mouse position and divide it by their distance?
Thanks a lot!
The first formula also depends on some variable distance which is not defined. It seems to move the player's position somewhat in the direction of the mouse coordinate.

rectangle collision

This is more of a programming problem than a technical question but since it relates to programming and math, I'm hoping to get some helpful feedback.
I have two rectangles: rectangle1 and rectangle2.
Both are defined by four float values:
float left;
float right;
float top;
float bottom;
For the sake of this example, say that each rectangle is 100 x 100 and that rectangle1 is:
float left = 100.0;
float right = 200.0;
float top = 500.0;
float bottom = 600.0;
And rectangle2 is:
float left = 150.0;
float right = 250.0;
float top = 550.0;
float bottom = 650.0;
When a collision occurs, I am trying to determine which side of rectangle1 hit which side of rectangle2 using the eight float values.
If my question was answered, I might be able to determine something like the following when a collision occurs:
rectangle1's right side hit rectangle2's left side
So far, I have tried using simple math to determine the distance between each possibility:
float distance1 = rectangle2.left - rectangle1.right;
float distance2 = rectangle2.top - rectangle1.bottom;
float distance3 = rectangle2.right - rectangle1.left;
float distance4 = rectangle2.bottom - rectangle1.top;
And then taking the minimum of those values to determine which side of each rectangle was involved in the collision. It doesn't seem so simple, though. There were two basic problems with this attempt:
1) The rectangles will already be overlapping by the time the collision code is reached.
2) If multiple rectangles are stacked on top of each other, the calculation will produce strange results (ie, even if rectangle1 is moving in the upper right direction and should hit both rectangles on their left side, it may actually hit one rectangle on the bottom and the other on the left.)
(This is because the rectangles are overlapping when the collision code is reached AND because distance1 and distance4 will be close or equal in this case.)
Is there a better way to answer this question using simple math? Any help would be appreciated.
And, before it's mentioned, this is not homework but a real problem I'm trying to solve for my game.
If you can correctly identify the collision, then to determine the faces draw a line joining the center of the 2 rectangles and check for intersection with the faces of each rectangle. At any given time the line will intersect 2 faces as long as the 2 rectangles are not overlapping or to be precise, as long as the center of 1 is not inside the other.
When they are overlapping, you can get 1 or 0 intersection.
case 0: 1 rectangle is totally inside the other so you can decide how you want to decide which sides are hitting, may be choose the one closest to each center.
case 1: rectangle is totally or partially inside the other. In either case, continue to extend your line joining the centers until you cross the outer (containing) rectangle. If u cross the contained rectangle before again, just change the hit face to the newly crossed face.
Hope its not too confusing :)

How would I implement strafe using opengl in java?

This is my gluLookAt setup:
glu.gluLookAt(x,y,z, // eye location
x + Math.cos(Math.toRadians(eyeAngle)),
y,
z - Math.sin(Math.toRadians(eyeAngle)), // point to look at (near middle)
0.f,1.f,0.f); // the "up" direction
The x, y, z are the coordinates and change when turning left and right and moving forward and backward. But I'm having difficulty implementing strafe right and left. Any help would be appreciated.
Finally figured everything out. If you have move forward and turn left and right, then strafe is actually simple. Strafe right, for example, is basically you turning 90 degrees to the right, moving forward, and then turning 90 degrees back to the left.
My forward was:
x += distance*Math.cos(Math.toRadians(eyeAngle));
z += -distance*Math.sin(Math.toRadians(eyeAngle));
You don't want to change the eyeAngle, because you still want to look in the same direction. For strafe right, you want to move as if you turned 90 degrees to the right and then went forward, similarly for left. So right would be my forward method above with an angle 90 to the right of my original eyeAngle, but because you want to keep eyeAngle the same, you don't change the variable, you just add 90 to it.
So, the right strafe method would be:
x += distance*Math.cos(Math.toRadians(eyeAngle+90));
z += -distance*Math.sin(Math.toRadians(eyeAngle+90));
Left would be subtracting 90. It is actually pretty simple after you've got forward and the overall glulookat set up. Thanks for the help everyone, it did aid me in understanding how it all works.
I don't have an idea about the GLU APIs but given X,Y and Z co-ordinates,
a Left relative to it's current Y rotation is,
position of X -= distance*Math.sin(Math.toRadians(Y-90));
position of Z += distance*Math.cos(Math.toRadians(Y-90));
a Right relative to it's current Y rotation is,
position of X -= distance*Math.sin(Math.toRadians(Y+90));
position of Z += distance*Math.cos(Math.toRadians(Y+90));
Try replacing Y with eyeAngle coz thts what is the rotating point.