moving items in JPanel - math

I am working on a pong game and I am working on the mechanism to move the ball. If I add 1 to x the ball moves 1 pixel to the right, if i add 1 to y the ball moves 1 pixel to the bottom. What if I want to move the ball at a certain angle how can 1 calculate the coordinates.

Trying to work with angles will get a bit more complicated than you need to get. For this kind of animation you generally want to use floats to store your objects x and y coordinates and move it by applying x and y deltas (The floats will preserve the detail of the position which is lost to rounding when drawn on the screen). The deltas represent the speed your object is moving in each axis and can be negative or positive.
For each iteration of your animation, add xdelta to your x coordinate and add ydelta to your y coordinate. Round them off to position them on the screen.
When you hit the top or bottom border, you would swap the sign on your ydelta component and likewise for side borders.
You wouldn't want to keep the same x and y delta all the time so when the objects hits a paddle, modify the x or y delta a little bit to change up the angle.

you are looking for line drawing algorithms, something like Bresenham or DDA you can find some reasonable implementations here ofcourse instead of drawing a complete line you would move your ball along that line but the way of finding the set of lines to move on is the same.

You might find these resources helpful.

for something like Pong you should be investigating vector math, but if all you want is to know an angle all you really need is SOHCAHTOA.

Related

Moving an object diagonally inside a square

I am stuck on a particular problem. I am learning on how to create a very basic game, where a ball will travel diagonally from either top left corner of a square or a rectangular down to the bottom right corner in a straight line (As shown in Fig 1 & 2). Now I know that the ball x and y position will both need to be changed frame by frame but I am unsure on how to go about this.
enter image description here
Math is not my strong point and I am unsure how do I calculate the exact route, especially since both the square and rectangle will have a different angles. Are there any math formulas I can use to calculate the diagonal line and by how much each of the x and y coordinates of the ball will need to be adjusted frame by frame.
From the research that I have done I think that I will most likely need to calculate the angle using the sin or cos functions but I am not sure how everything fits together. Have been using https://www.mathsisfun.com/sine-cosine-tangent.html to try and learn more.
I am planning on starting to code this but would really appreciate answers to these basic questions. I am trying to learn both the programming and the mathematical aspect at the same time and I feel that this approach would be the best fit.
Many Thanks for any suggestions/help, I would really appreciate it.
Since it's rectangular, just calculate the slope: rise (Y) / run (X). That will give you how much to increase the object's location in each direction per frame. Depending on how fast or slow you want the object to move, you'll need to apply some modifier to that (e.g., if you want the object to move twice as fast, you'll need to multiple 2 by the change in a particular direction before you actually change the object's location.
For square :
If you are using Frame or JFrame, you have coordinate with you.
You can move ball from left top to right down as follow ->
Suppose ur top left corner is at (0,0), add 1in both coordinate until you reach right bottom corner.
U can do this using for loop
You don't technically need the angle for this mapping. You know that the formula for a line is "y = m * x + b." I presume that you can calculate m,b. If not, let me know.
Given that - you can simply increment x based on anything you like (timer, event, etc. ). You can place your incremented x into the equation above to get your respective y.
Now, that won't be quite enough as you are dealing with pixels instead of actual numbers. For example, lest assume that in your game x/y are in feet. You will need to know how many pixels represent a foot. Then when you draw to the screen you adjust your coordinates by dividing by pixels per foot.
So...
1. Calculate your m and b for your path.
2. Use a timer. At each tick, adjust your x value
3. Use your x value to calculate your y value
4. Divide x and y by a scaling number
5. Use the new scaled x and y to plot your object
Now...There are all kinds of tricks you can play with the math, but that should get you started.
Let's left bottom corner of rectangle (or square) has coordinates (x0, y0), and right top corner (x1, y1). Then diagonal has equation
X(t) = x0 + t * (x1 - x0)
Y(t) = y0 + t * (y1 - y0)
where t is parameter in range 0..1. Point at t=0 corresponds to (x0, y0), at t=1 to (x1, y1), and at t=0.5 - to the center of rectangle. So all you need is vary parameter t and calculate position.
When your object will move with constant absolute speed in arbitrary direction, use horizontal and vertical components of velocity vx and vy. At every moment get coordinates as x_new = x_old + delta_time * vx. Note that reflection from vertical edge just changes horizontal component of velocity 'vx = - vx' and so on.

Centering Perspective Camera on two objects by panning

In Unity, I have a perspective camera, and I've got two transforms in my scene that I want the camera to perfectly center on screen. The camera will pan left/right/up/down to the appropriate location.
So far my approach has been to convert the transform positions to screen positions using Camera.WorldToScreenPoint, and taking their average to find the screen midpoint. From there, I know I want to pan the camera a certain number of units toward that midpoint. What I'm having trouble with is figuring out the formula for deciding how much to pan (or, maybe this isn't even the preferred way to determine this).
I think your approach is great. Let me expand the idea.
So this is your screen :D. Blue circle is where you want your objects to be. There are two scenarios. We will use green dots as an example of zooming scenario. Then red dots for panning scenario.
The trick is, you want to keep the dots as close as possible to circumference of blue circle.
Let's say you get red dots as your objects' screen position. You have to shift them towards the center. Let's calculate CenterOfDots. Then calculate it's difference to CenterOfBlueCircle. That's how much pan you need in screen coordinates.
So you have calculated the pan. Now you want to know how much you need to zoom. Let's say you get green dots this time. Calculate DistanceBetweenDots and compare it to DiameterOfBlueCircle. You want them to be the same. So their difference is how much zoom you need in screen coordinates.
There comes the tricky part. Now you know how much to pan and zoom in screen space. But you need to move the camera in world space. Trying to solve it using geometry magic is fine. But I hate headache :D
So instead, I would iteratively shift my camera using the data I calculated above. Just shift the camera in it's local x-y axes towards HowMuchPan, multiplied by a manually given coefficient PanSpeed. This will give a smooth transition to the camera. Same is for the zoom. This time you shift the camera in it's local z axis using HowMuchZoom multiplied by your manually given coefficient ZoomSpeed.
Hope it helps. Have fun :)
i figured out the mathy approach!
for panning, you want to figure out the average screen position of your objects (i.e. the middle). then you want to generate a couple world points against an arbitrary plane some distance away from the camera. the difference between these points is how much to pan the camera
center=Camera.ScreenToWorldPoint(Screen.width*0.5f, Screen.height*0.5f, 10f)
mid=Camera.ScreenToWorldPoint(averageScreenPoint.x, averageScreenPoint.y, 10f)
Camera.transform.Translate(mid-center)
zooming is a bit more complicated, but very similar to the panning approach. you want to use Camera.ScreenToWorldPoint against an arbitrary plane, but you want to do this for 4 points, which will help you figure out a scale to apply to your camera's z position. psuedocode -
screenMin = Camera.ScreenToWorldPoint(0f,0f,10f);
screenMax = Camera.ScreenToWorldPoint(Screen.width,Screen.height,10f);
objMin = Camera.ScreenToWorldPoint(screenPosMin.x, screenPosMin.y, 10f);
objMax = Camera.ScreenToWorldPoint(screenPosMax.x, screenPosMax.y, 10f);
screenDiff = screenMax-screenMin;
objDiff = objMax-objMin;
Vector3 scale = new Vector3(objDiff.x/screenDiff.x, objDiff.y/screenDiff.y, 0f);
ratio = scale.x < scale.y ? scale.y : scale.x;// pick the one that best puts fits on screen.
Camera.localPosition.z = Mathf.Min(ZoomMin, Camera.localPosition.z*ratio);

Math help for parallelograms on canvas

First let me say that I'm not very good with math. I have a canvas with multiple text "boxes" that are rotated to 300°, which basically makes them parallelograms. They are very similar to this:
I'm trying to detect if the mouse is over one of them, but I don't know how to do that. Please help. Thank you!
The simplest method is to use the inverse transform on the mouse point and then do simple rectangle testing on the transformed point. As long as the affine transform you're using doesn't map everything to a line, it will have a well-defined inverse.
Each parallelogram can first of all be contained in a rectangular bounding box like the one illustrated above. If the mouse is not within that rectangle, then it is definitely not a hit. You have many easy tests for that already. The rest of the space can be decomposed into the parallelogram of interest in green, and the areas you don't want. So we just need to test if the mouse is in the red areas with the following tests:
Left: x < a - (a/h)*y
Right: x > (a+b) - (a/h)*y
If either of those conditions is true, then the mouse is outside the parallelogram.
Note, in this case I am assuming y is 0 at the top and increases as you move down, and x is zero at the left and increases as you move right.
For more information about the value of a, we can turn to trig.
If we know the angle theta and h, then
a = h tan(Ɵ)

Math/Calculations for infinite/repeating world with rotation

How do I make a infinite/repeating world that handles rotation, just like in this game:
http://bloodfromastone.co.uk/retaliation.html
I have coded my rotating moving world by having a hierarchy like this:
Scene
- mainLayer (CCLayer)
- rotationLayer(CCNode)
- positionLayer(CCNode)
The rotationLayer and positionLayer have the same size (4000x4000 px right now).
I rotate the whole world by rotating the rotationLayer, and I move the whole world by moving the positionLayer, so that the player always stays centered on the device screen and it is the world that moves and rotates.
Now I would like to make it so that if the player reaches the bounds of the world (the world is moved so that the worlds bounds gets in to contact with the device screen bounds), then the world is "wrapped" to the opposite bounds so that the world is infinite. If the world did not rotate that would be easy, but now that it does I have no idea how to do this. I am a fool at math and in thinking mathematically, so I need some help here.
Now I do not think I need any cocos2d-iphone related help here. What I need is some way to calculate if my player is outside the bounds of the world, and then some way to calculate what new position I must give the world to wrap the world.
I think I have to calculate a radius for a circle that will be my foundry inside the square world, that no matter what angle the square world is in, will ensure that the visible rectangle (the screen) will always be inside the bounds of the world square. And then I need a way to calculate if the visible rectangle bounds are outside the bounds circle, and if so I need a way to calculate the new opposite position in the bounds circle to move the world to. So to illustrate I have added 5 images.
Visible rectangle well inside bounds circle inside a rotated square world:
Top of visible rectangle hitting bounds circle inside a rotated square world:
Rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world:
Another example of top of visible rectangle hitting bounds circle inside a rotated square world to illustrate a different scenario:
And again rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world:
Moving the positionLayer in a non-rotated situation is the math that I did figure out, as I said I can figure this one out as long as the world does not get rotate, but it does. The world/CCNode (positionLayer) that gets moved/positioned is inside a world/CCNode (rotationLayer) that gets rotated. The anchor point for the rotationLayer that rotates is on the center of screen always, but as the positionLayer that gets moved is inside the rotating rotationLayer it gets rotated around the rotationLayer's anchor point. And then I am lost... When I e.g. move the positionLayer down enough so that its top border hits the top of the screen I need to wrap that positionLayer as JohnPS describes but not so simple, I need it to wrap in a vector based on the rotation of the rotationLayer CCNode. This I do not know how to do.
Thank you
Søren
Like John said, the easiest thing to do is to build a torus world. Imagine that your ship is a point on the surface of the donut and it can only move on the surface. Say you are located at the point where the two circles (red and purple in the picture) intersect:
.
If you follow those circles you'll end up where you started. Also, notice that, no matter how you move on the surface, there is no way you're going to reach an "edge". The surface of the torus has no such thing, which is why it's useful to use as an infinite 2D world. The other reason it's useful is because the equations are quite simple. You specify where on the torus you are by two angles: the angle you travel from the "origin" on the purple circle to find the red circle and the angle you travel on the red circle to find the point you are interested in. Both those angles wrap at 360 degrees. Let's call the two angles theta and phi. They are your ship's coordinates in the world, and what you change when you change velocities, etc. You basically use them as your x and y, except you have to make sure to always use the modulus when you change them (your world will only be 360 degrees in each direction, it will then wrap around).
Suppose now that your ship is at coordinates (theta_ship,phi_ship) and has orientation gamma_ship. You want to draw a square window with the ship at its center and length/width equal to some percentage n of the whole world (say you only want to see a quarter of the world at a time, then you'd set n = sqrt(1/4) = 1/2 and have the length and width of the window set to n*2*pi = pi). To do this you need a function that takes a point represented in the screen coordinates (x and y) and spits out a point in the world coordinates (theta and phi). For example, if you asked it what part of the world corresponds to (0,0) it should return back the coordinates of the ship (theta_ship,phi_ship). If the orientation of the ship is zero (x and y will be aligned with theta and phi) then some coordinate (x_0,y_0) will correspond to (theta_ship+k*x_0, phi_ship+k*y_0), where k is some scaling factor related to how much of the world one can see in a screen and the boundaries on x and y. The rotation by gamma_ship introduces a little bit of trig, detailed in the function below. See the picture for exact definitions of the quantities.
!Blue is the screen coordinate system, red is the world coordinate system and the configuration variables (the things that describe where in the world the ship is). The object
represented in world coordinates is green.
The coordinate transformation function might look something like this:
# takes a screen coordinate and returns a world coordinate
function screen2world(x,y)
# this is the angle between the (x,y) vector and the center of the screen
alpha = atan2(x,y);
radius = sqrt(x^2 + y^2); # and the distance to the center of the screen
# this takes into account the rotation of the ship with respect to the torus coords
beta = alpha - pi/2 + gamma_ship;
# find the coordinates
theta = theta_ship + n*radius*cos(beta)/(2*pi);
phi = phi_ship + n*radius*sin(beta)/(2*pi));
# return the answer, making sure it is between 0 and 2pi
return (theta%(2*pi),phi%(2*pi))
and that's pretty much it, I think. The math is just some relatively easy trig, you should make a little drawing to convince yourself that it's right. Alternatively you can get the same answer in a somewhat more automated fashion by using rotations matrices and their bigger brother, rigid body transformations (the special Euclidian group SE(2)). For the latter, I suggest reading the first few chapters of Murray, Li, Sastry, which is free online.
If you want to do the opposite (go from world coordinates to screen coordinates) you'd have to do more or less the same thing, but in reverse:
beta = atan2(phi-phi_ship, theta-theta_ship);
radius = 2*pi*(theta-theta_ship)/(n*cos(beta));
alpha = beta + pi/2 - gamma_ship;
x = radius*cos(alpha);
y = radius*sin(alpha);
You need to define what you want "opposite bounds" to mean. For 2-dimensional examples see Fundamental polygon. There are 4 ways that you can map the sides of a square to the other sides, and you get a sphere, real projective plane, Klein bottle, or torus. The classic arcade game Asteroids actually has a torus playing surface.
The idea is you need glue each of your boundary points to some other boundary point that will make sense and be consistent.
If your world is truly 3-dimensional (not just 3-D on a 2-D surface map), then I think your task becomes considerably more difficult to determine how you want to glue your edges together--your edges are now surfaces embedded in the 3-D world.
Edit:
Say you have a 2-D map and want to wrap around like in Asteroids.
If the map is 1000x1000 units, x=0 is the left border of the map, x=999 the right border, and you are looking to the right and see 20 units ahead. Then at x=995 you want to see up to 1015, but this is off the right side of the map, so 1015 should become 15.
If you are at x=5 and look to the left 20 units, then you see x=-15 which you really want to be 985.
To get these numbers (always between 0 and 999) when you are looking past the border of your map you need to use the modulo operator.
new_x = x % 1000; // in many programming languages
When x is negative each programming language handles the result of x % 1000 differently. It can even be implementation defined. i.e. it will not always be positive (between 0 and 999), so using this would be safer:
new_x = (x + 1000) % 1000; // result 0 to 999, when x >= -1000
So every time you move or change view you need to recompute the coordinates of your position and coordinates of anything in your view. You apply this operation to get back a coordinate on the map for both x and y coordinates.
I'm new to Cocos2d, but I think I can give it a try on helping you with the geometry calculation issue, since, as you said, it's not a framework question.
I'd start off by setting the anchor point of every layer you're using in the visual center of them all.
Then let's agree on the assumption that the first part to touch the edge will always be a corner.
In case you just want to check IF it's inside the circle, just check if all the four edges are inside the circle.
In case you want to know which edge is touching the circumference of the circle, just check for the one that is the furthest from point x=0 y=0, since the anchor will be at the center.
If you have a reason for not putting the anchor in the middle, you can use the same logic, just as long as you include half of the width of each object on everything.

Vector math, finding the angle

I am trying to learn XNA by writing a small 2D game, it's a Top-Down perspective and Im trying to have double movement, moving along the axis using Left-Right and Up-Down keys, as well as looking right at the mouse cursor, so that the player can run and aim at the same time.
I have one vector for the player position (m_PlayerPos), and one vector for the mouse position (m_MousePos), and im trying to get the correct angle towards the mouse position.
Im using the formula method:
public static float Angle(Vector2 from, Vector2 to)
{
return (float)Math.Atan2(from.X - to.X, from.Y - to.Y);
}
This works, but for some reason the method only works half-way, along the x-axis. When the mouse is to the exact left of right of the player, the player looks right at the mouse.
But if I move to the top of the player, it looks down, and if the mouse is below the player, the player looks up. So I need to inverse the Y axis, but Im not sure how.
Thanks in advance for any feedback.
Use to.Y - from.Y.
Multiply it with (0.0, -1.0) (or just multiply the Y component by -1.0). This will mirror the vector along the horizontal axis and should achieve the result you want.
In screen space the origin is in the top-left corner with the Y axis pointing downward whereas in eucledean space the Y axis points upwards. That's why you observe the Y axis being "flipped".

Resources