I am making a 3D Java game but i have got problems when rotating a hitbox. I, upon this point, only used a method which detects if a Vector3f is in a box.
But in my game I want to rotate houses, for example, so that method won't work. I could use circulair hitboxes but that wouldn't work for every instance of objects.
So far i have used this simple calculation to detect if a location is in a hitbox.
public boolean isinbox(Vector3f pos) {
Vector3f entPos = ent.getPosition();
float x1 = entPos.x + xOffset;
float z1 = entPos.z + zOffset;
float y1 = entPos.y + yOffset;
float x2 = entPos.x - xOffset;
float z2 = entPos.z - zOffset;
float y2 = entPos.y;
return pos.x < x1 && pos.x > x2 && pos.z < z1 && pos.z > z2 && pos.y > y2 && pos.y < y1;
}
This works in many ways, but I can't figure out how to rotate them and still be able to detect it. The xOffset is the ofset if side a to the center and negative side b to the center.
How would I be able to rotate a hitbox and detect if an Vector is in it?
There are a couple of ways of getting around this issue and one (or more) ways of solving this issue:
Solving It
SAT Collision
SAT Stands for Separating Axis Theorem.
TutsPlus and MetaSoftware are great websites to learn how it works and how to implement it.
The Separating Axis Theorem (SAT for short) essentially states if you are able to draw a line to separate two polygons, then they do not collide. It's that simple. (gamedevelopment.tutsplus.com)
Here is the basic idea:
It can also be used for more complex shapes:
Getting Around It
AABB Collision
This is done by assuming that collisions will only ever happen on the X/Y axis (never on an axis defined by an arbitrary line).
Here is an example of what this looks like:
Therefore, you must define this axis-aligned hitbox by using the minimum X-and-Y values and the maximum X-and-Y values of the original box.
Circle Collision
This is a much simpler collision check which only detects when two objects are within a certain distance of each other.
Here is an example of what this looks like:
The way this works is that if the distance between the two objects is less than the sum of each circle's radius, then the objects are colliding.
Using an External Library
Bullet Physics
Box2D
Related
I'm making a simple test program to try and develop a bullet hell game, but my problem is that I want to make an entity move in a desired path, and I don't know where to start.
Their movement system works by having an angle, and making it's cos and sin the x and y vectors for it's movement (that's the method my teacher taught me). Here's the part of the code that involves that
this.dx = Math.cos(Math.toRadians(angle));
this.dy = Math.sin(Math.toRadians(angle));
}
public void tick() {
x+=dx*speed;
y+=dy*speed;
//this makes it reverse when the window's wall
if(x > Game.WIDTH || x < 0) {
dx = -dx;
}
if(y > Game.HEIGHT || y < 0) {
dy = -dy;
}
//this is here so angles are stored correctly
if(angle < 0) {
angle += Math.PI*2;
}else if(angle > Math.PI*2) {
angle -= Math.PI*2;
}
}
But as I've said, I want it to follow a path I choose. I could specify it with an equation or another method (I really don't know what's more practical), but I don't know how to manipulate the angle to make it follow my desired path.
While I'm making this question, I've figured how to make a circle
angle -= 0.05;
this.dx = Math.cos(angle);
this.dy = Math.sin(angle);
but I'd like to have a way to feed in an equation and manipulate the angle in the right way as to make them follow the path the equation provides on a graph
I have a few different potential ideas that might be what you're looking for:
Option 1:
If you want it to follow a smooth path defined by a line on a graph, you could try to parameterise the equation, e.g. have both x and y depend on a variable t, rather than having x and y depend on one another. Then, you can use time as this parameter t, and set the entity's x and y directly based on plugging the time into the parametric equations rather than setting an angle.
Option 2:
If you're okay with the path not being a perfectly smooth curve, you could store the path as just a sequence of points in space. The entity stores which point it's currently heading towards and once that point is within a certain distance it moves onto heading towards the next point instead
Note:
With option 1, it involves updating the entity's x and y directly instead of setting an angle. If you do still want to update the angle so that the entity faces / fires in the direction it's moving, then you could keep track of where the entity is in the previous tick. Then using it's current position and previous position you can get a vector of the direction it's moving in, and use that to set the angle.
I'm making a 2d game in libgdx and I would like to know what the standard way of moving (translating between two known points) on the screen is.
On a button press, I am trying to animate a diagonal movement of a sprite between two points. I know the x and y coordinates of start and finish point. However I can't figure out the maths that determines where the texture should be in between on each call to render. At the moment my algorithm is sort of like:
textureProperty = new TextureProperty();
firstPtX = textureProperty.currentLocationX
firstPtY = textureProperty.currentLocationY
nextPtX = textureProperty.getNextLocationX()
nextPtX = textureProperty.getNextLocationX()
diffX = nextPtX - firstPtX
diffY = nextPtY - firstPtY
deltaX = diffX/speedFactor // Arbitrary, controlls speed of the translation
deltaX = diffX/speedFactor
renderLocX = textureProperty.renderLocX()
renderLocY = textureProperty.renderLocY()
if(textureProperty.getFirstPoint() != textureProperty.getNextPoint()){
animating = true
}
if (animating) {
newLocationX = renderLocX + deltaX
newLocationY = renderLocY + deltaY
textureProperty.setRenderPoint(renderLocX, renderLocY)
}
if (textureProperty.getRenderPoint() == textureProperty.getNextPoint()){
animating = false
textureProperty.setFirstPoint(textureProperty.getNextPoint())
}
batch.draw(texture, textureProperty.renderLocX(), textureProperty.renderLocY())
However, I can foresee a few issues with this code.
1) Since pixels are integers, if I divide that number by something that doesn't go evenly, it will round. 2) as a result of number 1, it will miss the target.
Also when I do test the animation, the objects moving from point1, miss by a long shot, which suggests something may be wrong with my maths.
Here is what I mean graphically:
Desired outcome:
Actual outcome:
Surely this is a standard problem. I welcome any suggestions.
Let's say you have start coordinates X1,Y1 and end coordinates X2,Y2. And let's say you have some variable p which holds percantage of passed path. So if p == 0 that means you are at X1,Y1 and if p == 100 that means you are at X2, Y2 and if 0<p<100 you are somewhere in between. In that case you can calculate current coordinates depending on p like:
X = X1 + ((X2 - X1)*p)/100;
Y = Y1 + ((Y2 - Y1)*p)/100;
So, you are not basing current coords on previous one, but you always calculate depending on start and end point and percentage of passed path.
First of all you need a Vector2 direction, giving the direction between the 2 points.
This Vector should be normalized, so that it's length is 1:
Vector2 dir = new Vector2(x2-x1,y2-y1).nor();
Then in the render method you need to move the object, which means you need to change it's position. You have the speed (given in distance/seconds), a normalized Vector, giving the direction, and the time since the last update.
So the new position can be calculated like this:
position.x += speed * delta * dir.x;
position.y += speed * delta * dir.y;
Now you only need to limit the position to the target position, so that you don't go to far:
boolean stop = false;
if (position.x >= target.x) {
position.x = target.x;
stop = true;
}
if (position.y >= target.y) {
position.y = target.y;
stop = true;
}
Now to the pixel-problem:
Do not use pixels! Using pixels will make your game resolution dependent.
Use Libgdx Viewport and Camera instead.
This alows you do calculate everything in you own world unit (for example meters) and Libgdx will convert it for you.
I didn't saw any big errors, tho' i saw some like you are comparing two objects using == and !=, But i suggest u to use a.equals(b) and !a.equals(b) like that. And secondly i found that your renderLock coords are always being set same in textureProperty.setRenderPoint(renderLocX, renderLocY) you are assigning the same back. Maybe you were supposed to use newLocation coords.
BTW Thanks for your code, i was searching Something that i got by you <3
i am trying to develop a game in libgdx in which i want to use explode effect with sprite when i clicked on it. is it possible or i should use BOX2D physics to apply the explode effect.?
You should use the API that handles Animations for you, or if you want to use particles you must use the API that provides Emmiters for you.
I'm doing explosion effects on my own. For every particle object I have variables that hold X and Y coords and in VX and VY I'm holding particle speed.
When explosion happens I'm creating some number of those objects (I'm storing them in a list). For every one of those particles I set X and Y coords with the coords of explosion it self. So they all start at same point. But for every particle I set different, random VX and VY (initial speed). So they will start moving in different directions.
I'm also implementing some gravity effect - in every frame I'm decreasing VY for some constant (multiplied with that delta time - time since last frame rendering, to get constant moving).
At end you should check somehow when to remove particle object. I.e. when it's coordinates are out of screen or after some time or something...
To make it even nice you can animate particles...use transparency...
One simple way you can achieve what you wanted is through the use of particles
I am guessing that your game is 2d so here is the official wiki about 2d particles
As MilanG stated the easiest way ist to create a Particle class
public class Particle{
public float x;
public float y;
public float vx;
public float vy;
public Particle(float x, float y, float vx, float vy){...}
}
Then when the user clicks on the Texture you would instantiate a lot of these particles and add them to an ArrayList. X and Y coordinates should be the center of your texture. vx can be a random number (negative and positive). vy can also be a random number depending on the visual effect of your particles. Experiment with the values a bit
for(int i = 0; i < 100; i++){
arrayList.add(new Particle(textureX,
textureY,
MathUtils.randomFloat(-200, 200),
MathUtils.randomFloat(0, 200)));
}
In the update loop you would change the x and y coordinates according to vx and vy values. The vy value should be decrased because of gravity:
for(Particle p : arrayList){
p.x += p.vx * delta;
p.y += p.vy * delta;
p.vy += -200 * delta; // -200 is gravity value
}
In you render code you draw the particle texture for every element in the arraylist:
for(Particle p : arrayList){
batch.draw(particleTexture, p.x, p.y);
}
Important:
You also need to implement some logic to remove particles from the arrayList (like checking for x and y coordinate boundings together with a CopyOnWriteArrayList or a second deleteParticles ArrayList)
Important as well:
Another point to mention is that this technique generates a lot of objects causing a heavy GC to follow. You can reduce that by using a Pooling technique. LibGDX has some pretty nice classes for that.
This question already has answers here:
What algorithm can I use to determine points within a semi-circle?
(11 answers)
Closed 8 years ago.
I have a points x and y and I need to check the point which intersect within a semi- pie.
I need an algorithm to find the point is intersect in the semi circle. for rectangle we have point contains method to check the point intersect the rectangle, but this doesn't work for semi circle segments with start and end angle.
I have created many semi pie segment, when I touch the pie segment, I need to check the point intersect of which segment.
I'm assuming this is speed-critical, and also that you want to be able to specify the semi-circle as having a center and arbitrary start and end angles, so not just a semi-circle but a circular sector. For a semi-circle just make the start and end angles 180 degrees apart, or remove the test against endVector.
Make the test a two-step process. For a given point, first check that it is inside a rectangle enclosing the semi-circle. You can use your existing sort and binary search algorithm for this. If a point is not in the rectangle then reject the point, if it is then test against the semi-circle.
Also, outside of the loop, convert the values specifying the semi-circle into a form that will enable the tests to be done faster:
Convert the radius to radius squared. Compare the distance of a point from the center squared, to the radius squared. This saves a square root when computing the distance.
Convert the start and end angles of the semi-circle to a couple of 2D vectors, and then use these to check whether the point is inside the sector. Then you won't have to use any trig functions like atan2(y, x), which are slow, or do annoying fiddly comparisons to start and end angles and handling the case where angles wrap around from 360 to 0.
pseudo code:
float radiusSquared;
float startVectorX;
float startVectorY;
float endVectorX;
float endVectorY;
float centerX;
float centerY;
void convertSector(float radius, float startAngle, float endAngle)
{
radiusSquared = radius * radius;
startVectorX = cos(startAngle);
startVectorY = sin(startAngle);
endVectorX = cos(endAngle);
endVectorY = sin(endAngle);
}
boolean testPoint(float x, float y)
{
// check if point is within the radius:
float distanceX = x - centerX;
float distanceY = y - centerY;
if((distanceX * distanceX) + (distanceY * distanceY)) > radiusSq)
return false;
// check if point is outside start radius vector using 2D dot-product with normal:
if(((distanceX * -startVectorY) + (distanceY * startVectorX)) < 0.0f)
return false;
// check if point is outside end radius vector using 2D dot-product with normal:
if(((distanceX * -endVectorY) + (distanceY * endVectorX)) > 0.0f)
return false;
return true;
}
The above code will only work for sectors with an internal angle of <= 180 degrees. To test a point against sectors larger than that (i.e. Pac-Man like shapes), test if the point is inside the circle and then test that it is not inside the sector making up the remainder of the circle.
I believe this is more of a logic question than a java question, sorry.
My intent is rather straightforward, i want the ship to move and rotate with a matrix, with the bitmap ship1 being the center pivot of the rotation. The code works great except the pivot is off by a strange offset. (picture of conundrum linked at bottom)
The default value rotation at 0 works but all the other values seem to slide away from the center, with 180 being the furthest from the center.
centerX = playerValues[Matrix.MTRANS_X] + ship1.getWidth()/2;
centerY = playerValues[Matrix.MTRANS_Y] + ship1.getHeight()/2;
newRotation = ((float) Math.toDegrees(Math.atan2(fingery1 - centerY, fingerx1 - centerX)));
matrix.postRotate((newRotation - prevRotation), centerX, centerY);
prevRotation = newRotation;
if (fingerx1 > playerX) {
xspeed = 1;
} else
if (fingerx1 < playerX) {
xspeed = 0;
} else
if (fingery1 > playerY) {
yspeed = 1;
} else
if (fingery1 < playerY) {
yspeed = 0;
}
matrix.postTranslate(xspeed, yspeed);
matrix.getValues(playerValues);
I tried to draw how the relation of the bitmap looks at different angles. (the blue dot is where I intend to rotate the bitmap around, the arrow pointing right is the only correct one).
http://i.stack.imgur.com/2Yw76.png
Please let me know if you see any errors or any feedback helps! I just need a second pair of eyes on this because mine are going to explode soon.
Consider studying a good computer graphics text re matrix math. Foley and Van Dam is always a safe bet.
The matrix A is applied to point x with multiplication Ax. You have A = RT a rotation with translation post multiplied. The result is RTx which is R (T x) meaning the point is translated then rotated, when you probably meant the opposite.
Additionally it appears you are concatenating incremental changes repeatedly. Floating point errors will accumulate, visible as worsening distortions. Instead maintain orientation parameters x, y, theta for each ship. These are controlled by the UI. Set the matrix from these in each rendering. The transform will be rotation about the point (w/2, h/2) followed by translation to (x, y). But the matrix to effect this is the translation post multiplied by the rotation! Also you must reset the matrix for each ship.