I try to find a solution for drawing ellipses based on the center point, not the upper left corner as it is specified in the constructor of Ellipse2D.Double. As seen in the picture the ellipses should have the same center point and scale, is that somehow possible?
Thanks in advance for your help.
If (x,y) is the center you want to use and you can only specify the upper left corner, then use the following:
private Ellipse2D getEllipseFromCenter(double x, double y, double width, double height)
{
double newX = x - width / 2.0;
double newY = y - height / 2.0;
Ellipse2D ellipse = new Ellipse2D.Double(newX, newY, width, height);
return ellipse;
}
If called with the center point and the width and height, this will "transform" your center point to the upper left corner and create an Ellipse2D which is located just as you want it to be.
The 'Upper' coordinate is misleading , it only works assuming y >=0 ( which works fine for a screen referential , bur not if you use the primitive with y <0 , for instance calculating object collisions )
With the usual math referential , where y<0 is possible , up is at the bottom
so it lacks a general definition not to get confused
The exact definition is that x and y are the min coordinates of the bounding rectangle.
It can be 'up' or 'down' ( relatively to your screen i suppose ) depending on the y axis orientation and y coordinate sign
Related
I am experimenting with LWJGL2 and I want to be able to tell if the camera is able to see a certain point in 3D space. I was trying on my own to see if I could do it, and ended up with something that kinda works and only for rotation on the Y axis.
This code works, but not in both axes. I am not sure if this is the correct way to do it either.
public boolean isInFrame(float x, float y, float z){ //The z isn't used
float camera = rotation.y; //The cameras y rotation
double object = Math.atan2(y, x)*(180/Math.PI);
object += (180 - camera);
if (object <0 ) object += 360;
if (object >360 ) object -= 360;
return 270>object&&90<object; //set to 180˚ for test
}
For the code, I am assuming the camera is centered around 0,0,0.
I just want to know how I could change this so that it works for x and y rotation of the camera. For example, it could tell me if if a point is visible regardless of the cameras rotation.
NOTE:
I am not worrying about anything obstructing the view of the point.
Thanks for the help in advance.
If you have the view and projection matrices of the camera (let's call them V, P), you can just apply the transformations to your point and check whether the result lies within the clip volume of the camera.
Say your point is at (x, y, z). Construct a vector p = (x, y, z, 1) and apply the camera transform to it:
q = P * V * p
The view transform V applies the transformation of the world relative to the camera, based on the camera position and orientation. Then, the projection P deforms the camera's view frustum (i.e., the visible space of the camera) into a unit cube, like this:
(Image source: Song Ho Ahn)
In order to read off the coordinate values of the resulting point, we must first de-homogenize it by dividing by its w component:
r = q / q.w
Now, the components r.x, r.y, r.z tell you whether the point lies within the visible range of the camera:
If r.x < -1, the point lies beyond the left border of the screen.
If r.x > 1, the point lies beyond the right border of the screen.
If r.y < -1, the point lies beyond the bottom border of the screen.
If r.y > 1, the point lies beyond the top border of the screen.
If r.z < -1, the point lies beyond the near plane of the camera, i.e., the point is behind the camera or too close for the camera to see.
If r.z > 1, the point lies beyond the far plane of the camera, i.e., the point is too far away for the camera to see.
Otherwise, the point is in the visible range of the camera.
I searched and implemented things from this forum, it doesn't come out right.
What I'm trying to achieve is to calculate a spawnPoint for player bullets relative to his position and rotation.
The spawnPoint should be and his X + his width (the player is set to point to the right by default) and y + height/2 (to spawn from his center on the Y axis).
This is what I got from this forum:
this.bulletSpawn.x = (float)(this.position.x + this.width/2 + this.width * Math.cos(rotation));
this.bulletSpawn.y = (float)(this.position.y + this.height/2 + this.height/2 * Math.sin(rotation));
The rotation is in Radians. The this is the Player class.
Images showing what I expect to happen:
Original Position
Expected Behaviour
The red dot is the spawnPoint I'm trying to calculate knowing the player position and rotation.
The player Sprite is what rotates, and it rotates related to his center x and y, which is done with a lib, i do not have these variables. The entire arrow would be the player , the arrow direction is where the player is pointing at, and the red dot would be the bulletSpawn point (or the expected one)
Using the code I posted, the bullets seem to be spawning from somewhere else. Even at the beggining they have an offset and when I rotate the player the spawnPoint seems to be relative to a different origin than what I'm expecting.
This is the bullet position code:
position.x = holder.bulletSpawn.x - (float)(this.width/2 * holder.rotation);
position.y = holder.bulletSpawn.y - (float)(this.height/2 * holder.rotation);
This is inside the Bullet class. The position variable is a Vector2 of bullet, and holder is the player instance. This code is merely to give an offset for the bullet to spawn at the center of its own size
I added some fixes related to the comments, but the bullets still have a tiny offset that looks wrong at certain angles.
Basically the distance i want to get is the width of the player, and his center y which is height/2.
Let's initial position is X0, Y0, rotation is about center point CX, CY, and rotation angle is Theta. So new position after rotation is:
NX = CX + (X0-CX) * Cos(Theta) - (Y0-CY) * Sin(Theta)
NY = CY + (X0-CX) * Sin(Theta) + (Y0-CY) * Cos(Theta)
This equations describe affine transformation of rotation of arbitrary point about center point, and affine matrix is combination of translation, rotation, and back translation matrices.
About center CX, CY - you wrote
it rotates related to his x and y origin at his bottom left
About initial point coordinate - for bullet it seems to be
X + Width, Y + Height/2
Swift extension:
extension CGSize {
static func offsetFrom(angle:CGFloat, distance:CGFloat) -> CGSize {
let rad = angle * CGFloat.pi / 180
return CGSize(width: sin(rad) * distance, height: cos(rad) * distance)
}
}
Im trying to render a map for a game I am making using tiled map from the slick class but im having a lot of trouble understanding the difference between the parameters x and y. Below is a googled explanation but im not understanding it
public void render(int x,
int y,
int sx,
int sy,
int width,
int height)
Render a section of the tile map
Parameters:
x - The x location to render at
y - The y location to render at
sx - The x tile location to start rendering
sy - The y tile location to start rendering
width - The width of the section to render (in tiles)
height - The height of the secton to render (in tiles)
My game consists of a car and a camera locked onto it which will follow the car around on the map. The map starts to render as the car move. Could someone give me an explanation on how x and y and sx and sy applies to this.
The render function takes a rectangular area of tiles and draws them onto a rectangular area of pixels on the screen.
x and y specify the top left corner of the pixel rectangle
sx and sy specify the top left corner of the tile rectangle
width and height specify the area of the tile rectangle
Im trying to draw an arc that stretches around part of the circle. Im confused on how to use the DrawArc method. I read few articles online and to simply put, im confused on how the parameters exactly work. My circle is centered at 100, 100 with radius of 50. How would i use the drawArc method to draw an arc that overlaps the circle ? Any thoughts would be highly appreciated
Reading articles is good, but you should always read a method's documentation.
The drawArc method does not take a center and radius as arguments. Instead, it takes a rectangle. The x and y arguments are the upper-left corner of that rectangle; the width and height are the horizontal and vertical diameters of your arc's ellipse.
You can just do the math yourself:
int centerX = 100;
int centerY = 100;
int radius = 50;
graphics.drawArc(centerX - radius,
centerY - radius,
radius * 2,
radius * 2,
startAngle,
span);
Note that the final argument is the number of degrees the arc spans, not the absolute end angle.
I have a problem with JSlider in Java I have drawn a circle A, and I want to put ANOTHER circle B inside the first circle A. I want to place the CENTRE of the second circle B at the same coordinate with the centre of the first circle A, and then I want to use JSlider to INCREASE or DECREASE the radius of circle B. The trouble is, when you increase or decrease the slider, the CENTRE of circle B does not stay aligned with the centre of A. Basically, I want two circles with the SAME centre. Can someone point out my mistake, please?
slider1 = new JSlider(JSlider.HORIZONTAL,10,100,10);
window.add(slider1);
slider1.addChangeListener(this);
Graphics paper = panel.getGraphics();
int slider1Value = slider1.getValue();
paper.setColor(Color.white);
paper.fillRect(0, 0, 500, 500);
paper.setColor(Color.pink);
paper.fillOval(20,20,100,100); // this is circle A
paper.drawOval(60,60,slider1Value,slider1Value); // this is circle B slider
Because you have to change position of top-left "corner" of circle. If you change radius, the circle is bigger/smaller so it's obvious if you don't change position of top-left cornet, centers of 2 circles won't be aligned
Theory
From Graphics.drawOval() javadoc. When you draw a circle their (x,y) coordinates are not its center but its top-left corner. In order to make your B circle aligned with A circle, you need to calculate its (x,y) coordinates relatives to the last one:
Circle A: (x,y) = (20,20); diameter = 100 ==> radius = 50; center = (x + radius, y + radius) = (70,70)
Well, you have your center now: (70,70). Now, slider1Value is your new radius so you need to calculate circle B (x,y) coordinates:
Circle B: center = (70,70); (x,y) = (centerX - radius, centerY - radius) = (70 - slider1Value, 70 - slider1Value)
Finally, circle B width and height are equals to its diameter:radius * 2 = slider1Value * 2.
Facts
Make this change and it will work like a charm:
paper.drawOval(70 - slider1Value, 70 - slider1Value, 2*slider1Value, 2*slider1Value);