In my game, the player is a circle texture, and there are lots of tall, narrow, rotating square textures. I know how to use the Intersector class for collision, but from what I have discovered, it doesn't account for rotation. Is there some way/class that can create shapes from a texture, then use those as the bounds?
I dont know if there is class for this but i came up with a simple idea.
People believed that sun rotates around earth for years. Because they saw it from earth.
Lets assume rotating square is our world and actually not rotating. In both way we know when is day or night.
Look at those pictures and you will understand better.
This case is harder to check collision.
And this case is easier. But actually two cases are same.
So just change case to 2.
You know
Rotation angle of square/rectangle
Width and height of square/rectangle
You can find angle between circle and center point of rectangle/square.
Here is what it will look like in square/rectangle class.
public boolean check_collision(Player player)
{
Vector2 pvector=new Vector2(player.xcenter , player.ycenter);
Vector2 svector=new Vector2(this.xcenter , this.ycenter);
float radi=player.radius;
if( pvector.dst2(svector) <
(width + radi) * (width + radi) +
(height + radi) * (height + radi) )// dont check if player is too far for collision
{
Vector2 rvector= pvector.sub(svector);// rvector from square center to player center
rvector.setangle(rvector.angle()+ this.rotation);//make sure rotations is CCW
pvector=rvector.add(svector); //new player vector to check collision
return new Rectangle(pvector.x-radi/2f ,pvector.y-radi/2f,radi,radi).overlaps(new Rectangle(svector.x-width/2f ,svector.y-height/2f,width,height));
//assume that player is also rectangle because we already checked worst case with if condition.
}
return false;
}
Related
I am trying to shoot an object(a spell) depending on the rotation of the players arm. The spell is supposed to come out of the hand and shoot towards where the mouse cicked(the arm rotates and points to where the mouse is). This is how the arm rotates in game.
public boolean mouseMoved(int screenX, int screenY) {
tmp.x = screenX;
tmp.y = screenY;
tmp.z = 0;
cam.unproject(tmp);
rot = MathUtils.radiansToDegrees * MathUtils.atan2((float)tmp.y - (float)player.getArmSprite().getY() - player.getArmSprite().getHeight(),
tmp.x -player.getArmSprite().getX() - player.getArmSprite().getWidth());
if (rot < 0) rot += 360;
//Last right or left means if hes looking left or right
if(player.lastRight)
player.setObjectRotation(rot + 80);
if(player.lastLeft)
player.setObjectRotation(-rot - 80);
And this is how the spell is supposed to shoot based off rotation
//destination is a vector of where on screen the mouse was clicked
if(position.y < destination.y){
position.y += vel.y * Gdx.graphics.getDeltaTime();
}
if(position.x < destination.x){
position.x += vel.x * Gdx.graphics.getDeltaTime();
}
However this is very wonky and never really reacts the way it supposed to with a few exceptions. It fires from the hand and then if the y axis is equal it completely evens out and goes till it reaches the x position, I want it to fire from the hand to the position clicks perfectly straight from point a to point b, this is clearly a rotation problem that I just can't seem to figure out how to tackle.
Here is an image of what is happening
Example image
The red indicates where I clicked, as you can see it reached the x pos first and now is traveling to the y when it should have reached the x and y pos of where I clicked first
Any help with this problem is extremely appreciated!
I'm pretty bad at radians and tangents but luckily we have vectors.
Since you have the rot ation in degrees of the arm. I advice to use Vectors to use for any Vector related math now.
//A vector pointing up
Vector2 direction = new Vector2(0, 1);
//Let's rotate that by the rotation of the arm
direction.rotate(rot);
Now direction is the direction the arm is pointing. If your rotation is calculated where up = 0. So you might need to rotate it 180, 90 or -90 degrees. Or in the case you did something silly any degrees.
Your spell should have a Vector too for it's position. Set that to the hand or wherever you want to start from. Now all you need to do is scale that direction since it's currently has a length of 1. If you want to move 5 units each frame you can do direction.scl(5) now it is of length 5. But technically speaking it's no direction anymore now everybody calls it velocity so let's do.
//when you need to fire
float speed = 5;
Vector2 velocity = direction.cpy().scl(speed);
//update
position.add(velocity);
draw(fireballImage, position.x, position.y);
I copied direction first, otherwise it would also be scaled. Then I just added the velocity to the position and draw using that Vector.
And to show Vectors are awesome you should see this awesome badlogic vs mouse program I created. https://github.com/madmenyo/FollowMouse there are just a view lines of my own code. It just takes a little bit of vector knowledge and it's very readable.
I'm using rectangles for collision detection and a rectangle is created every 3 seconds, I wan't the rectangle to move upward just like my sprite but .translateY() method can't be used on rectangle.
this is what I did to my sprites stored on ArrayList:
for(Sprite sprite:mySprite){
sprite.translateY(deltaTime*movementSpeed);
}
and this is what I did on rectangles which does not work:
for(Rectangle rect:myRect){
rect.setY(deltaTime*movementSpeed);
}
it is possible that your rectangle is being drawn in posciciĆ³n you tell them, but setY is not the same, which translateY, simple explanation:
if for example deltaTime = 1 aprox. and movementeSpeed = 5.
you always drawing the rectangle in the same position, with minimal variation in delta maybe just not appreciated:
your position is rect.setY(5); all time.
try this
for(Rectangle rect:myRect){
rect.setY(rect.getY() + (deltaTime*movementSpeed));
}
I hope this help.
I've been stuck on a bug regarding collision in my 2D Mario-like game.
public void collision() {
if (Rect.intersects(Robot.rect2, r)){
robot.setSpeedY(0);
robot.setCenterY(tileY - 32);
robot.setJumped(false);
} else if (Rect.intersects(Robot.rect, r)){
robot.setSpeedY(0);
robot.setCenterY(tileY + 32);
}
updateRect();
if (Rect.intersects(Robot.rect3, r)){
robot.setCenterX(tileX + 32);
robot.setSpeedX(0);
} else if (Rect.intersects(Robot.rect4, r)){
robot.setCenterX(tileX - 32);
robot.setSpeedX(0);
}
}
Collision in my game is checked by comparing rectangles. My robot's rectangles: rect (bottom collision, so rectangle on bottom half of my robot sprite), rect2 (top collision), rect3 (left collision), and rect4 (right collision).
Every tile in my game is bounded by an instanced Rectangle r. When my robot's rectangle and the tile's rectangle intersect, I call collision(), which sets the position of my robots direction.
Here is my problem: If my robot is at a corner, where it is in bottom collision and right collision, and I move to the right, my robot moves INTO the right tile, and that triggers the bottom collision, and screws everything up.
Switching the postiions of the Bottom/Top & Right/Left collision doesn't help since then the same problem occurs, where the robot falls into the ground, triggering the Right/Left collision.
Essentially, I need a way to run all four at the same time.
Thanks
Yku are trying to build it one check at a time. Why not something like
if(!Rect.intersects(robot.rect1) && !Rect.intersects(robot.rect2) && !Rect.intersects(robot.rect3) && !Rect.intersects(robot.rect4)
{
//act normally
} else {
//collieion
}
What youre doing now is checking one side and base your result on that.
yes I also had a trouble with that, what you are missing is to call updateRect(); again after you made the collision detection on the X axis.
And I recommendto check the X axis first.
here is a nice Article about tile based Collision:
http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/
The issue involves an Android Path shape. It's a triangle that I'm using as an arrow to point towards objects on a screen Canvas. This is for a 2d game. player in the middle of the screen, objects around him and offscreen.
These arrows are supposed to rotate around the center of the screen, with a radius so that they rotate in a circle around the player. The arrows point towards objects that the player needs to move towards.
What I have right now is somewhat working, but the arrows are zipping around the circle at ridiculous speeds. Funny enough, they're pointing in the right direction, but they aren't staying at the right point on the circle. (if arrow is pointing northeast, arrow should be on the northeast part of the circle, etc)
I'm sure it's because of the math. I'm probably using atan2 wrong. Or canvas.translate wrong. Or maybe I shouldn't be using atan2 at all. Help! :)
Here is the code:
// set the shape of our radar blips
oBlipPath.moveTo(0, -5);
oBlipPath.lineTo(5, 0);
oBlipPath.lineTo(0, 5);
// Paint all the enemies and radar blips!
for(int i=0; i<iNumEnemies; i++){
if (oEnemies[i].draw(canvas, (int)worldX, (int)worldY)){
//calculate the degree the object is from the center of the screen.
//(user is the player. this could be done easier using iWidth and iHeight probably)
//we use a world coordinate system. worldY and worldX are subtracted
fDegrees = (float)Math.toDegrees(Math.atan2((oEnemies[i].getEnemyCenterY()-worldY)-user.getShipCenterY(), (oEnemies[i].getEnemyCenterX()-worldX)-user.getShipCenterX()));
canvas.save();
//get to the center
canvas.translate((iWidth / 2) , (iHeight / 2) );
//move a little bit depending on direction (trying to make arrows appear around a circle)
canvas.translate((float)(20 * Math.cos(fDegrees)), (float)(20* Math.sin(fDegrees)));
//rotate canvas so arrows will rotate and point in the right direction
canvas.rotate(fDegrees);
//draw arrows
canvas.drawPath(oBlipPath, oBlipPaint);
canvas.restore();
}
}
Affine transformations are are not commutative. They are typically applied in an apparent last-specified-first-applied order. As an alternative, consider the rotate() variation that rotates about a point.
Well, I've got it doing what I wanted, but I don't really know how. I threw in some random numbers until things showed up on the screen the way I wanted. If anyone wants to clue me in as to a better way to do this, I'm all ears.
The code:
// set the shape of our radar blips
oBlipPath.moveTo(0, -5);
oBlipPath.lineTo(6, 0);
oBlipPath.lineTo(0, 5);
oBlipMatrix.setRotate(45, 0, 0);
oBlipPath.transform(oBlipMatrix);
// Paint all the enemies and radar blips!
for(int i=0; i<iNumEnemies; i++){
oEnemies[i].draw(canvas, (int)worldX, (int)worldY);
if (oEnemies[i].bActive){
//calculate the degree the object is from the center of the screen.
//(user is the player. this could be done easier using iWidth and iHeight probably)
//we use a world coordinate system. worldY and worldX are subtracted
fDegrees = (float)Math.toDegrees(Math.atan2((oEnemies[i].getEnemyCenterY()-worldY)-(iHeight / 2), (oEnemies[i].getEnemyCenterX()-worldX)-(iWidth / 2)));
canvas.save();
//get to the center
canvas.translate((iWidth / 2 + 50) , (iHeight / 2 + 50) );
//move a little bit depending on direction (trying to make arrows appear around a circle)
//canvas.translate((float)(20 * Math.cos(fDegrees)), (float)(20* Math.sin(fDegrees)));
//rotate canvas so arrows will rotate and point in the right direction
canvas.rotate(fDegrees-45, -50, -50);
//draw arrows
canvas.drawPath(oBlipPath, oBlipPaint);
canvas.restore();
}
}
For whatever reason, I have to subtract 45 degrees from the canvas rotation, but add 45 degrees to the matrix rotation of the path shape. It works, but why?! :)
Im trying to get into some basic JavaFX game development and I'm getting confused with some circle maths.
I have a circle at (x:250, y:250) with a radius of 50.
My objective is to make a smaller circle to be placed on the circumference of the above circle based on the position of the mouse.
Where Im getting confused is with the coordinate space and the Trig behind it all.
My issues come from the fact that the X/Y space on the screen is not centered at 0,0. But the top left of the screen is 0,0 and the bottom right is 500,500.
My calculations are:
var xpos:Number = mouseEvent.getX();
var ypos:Number = mouseEvent.getY();
var center_pos_x:Number = 250;
var center_pos_y:Number = 250;
var length = ypos - center_pos_y;
var height = xpos - center_pos_x;
var angle_deg = Math.toDegrees(Math.atan(height / length));
var angle_rad = Math.toRadians(angle_deg);
var radius = 50;
moving_circ_xpos = (radius * Math.cos(angle_rad)) + center_pos_x;
moving_circ_ypos = (radius * Math.sin(angle_rad)) + center_pos_y;
I made the app print out the angle (angle_deg) that I have calculated when I move the mouse and my output is below:
When the mouse is (in degrees moving anti-clockwise):
directly above the circle and horizontally inline with the center, the angle is -0
to the left and vertically centered, the angle is -90
directly below the circle and horizontally inline with the center, the angle is 0
to the right and vertically centered, the angle is 90
So, what can I do to make it 0, 90, 180, 270??
I know it must be something small, but I just cant think of what it is...
Thanks for any help
(and no, this is not an assignment)
atan(height/length) is not enough to get the angle. You need to compensate for each quadrant, as well as the possibility of "division-by-zero". Most programming language libraries supply a method called atan2 which take two arguments; y and x. This method does this calculation for you.
More information on Wikipedia: atan2
You can get away without calculating the angle. Instead, use the center of your circle (250,250) and the position of the mouse (xpos,ypos) to define a line. The line intersects your circle when its length is equal to the radius of your circle:
// Calculate distance from center to mouse.
xlen = xpos - x_center_pos;
ylen = ypos - y_center_pos;
line_len = sqrt(xlen*xlen + ylen*ylen); // Pythagoras: x^2 + y^2 = distance^2
// Find the intersection with the circle.
moving_circ_xpos = x_center_pos + (xlen * radius / line_len);
moving_circ_ypos = y_center_pos + (ylen * radius / line_len);
Just verify that the mouse isn't at the center of your circle, or the line_len will be zero and the mouse will be sucked into a black hole.
There's a great book called "Graphics Gems" that can help with this kind of problem. It is a cookbook of algorithms and source code (in C I think), and allows you to quickly solve a problem using tested functionality. I would totally recommend getting your hands on it - it saved me big time when I quickly needed to add code to do fairly complex operations with normals to surfaces, and collision detections.