Sign in to follow this  
nuclearfission

Java Physics: Why isn't this working?!?!

Recommended Posts

I'm working on a simple java applet/game. I'm trying to make this game have the atari missile command feel to it. So far I have somewhat of a player/ship firing red lines(missiles) onscreen everytime the mouse is clicked. However I'm having trouble sending the missiles to where the mouse is being clicked. I've tried using vectors(trigonometry) to set a missile X velocity, but it just isn't working. Everytime I click on the mouse the missile shoots either in 1)a fixed point
or 2)Not where the mouse is. Anothing thing is that java works in radians not degrees, and I have not a clue how to relate radians on a graph?(probebly could have googled: to lazy though)

please help me!

code:(mouse pressed funtion is near the bottom)

meteorD main java class

/**
* @(#)meteorD.java
*
* meteorD Applet application
*
* @author
* @version 1.00 2010/10/9
*/


import java.applet.*;
import java.awt.*;
import java.awt.event.*;


public class meteorD extends Applet implements Runnable, MouseListener, MouseMotionListener{


//declare some variables
private player gunShip;
private Thread game;
private projectile [] missile;

//make a constant projectileSpeed = -4
private final int projectileSpeed = -4;

//if game loop is running
boolean running = false;


//init
public void init() {
//new player object
gunShip = new player(235,285);

//10 new projectile objects
missile = new projectile[10];

//mouse listener
addMouseListener(this);


}

//create and start the thread and set running = true
public void start(){
//create the thread
game = new Thread(this);
game.start();

running = true;

}


//stop the thread
public void stop(){
game.stop();
if(game != null){
game = null;
}
running = false;

}

//this is supposedly called when the user exits the browser?
public void destroy(){
game.stop();
if(game != null){
game = null;
}
running = false;

}


//run
public void run(){

Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

//while running = true
while(true){


for(int i=0; i < missile.length; i++){
if(missile[i] != null){
missile[i].move();

if(missile[i].outOfBounds()){
missile[i] = null;
}

}
}

//clear screen and call function paint?
repaint();

//try and let the thread sleep
try{
game.sleep(30);

}
catch (InterruptedException e){

}

Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

}

}


//draw graphics to screen
public void paint(Graphics g) {
gunShip.draw(g);

for(int i=0; i < missile.length; i++){
if(missile[i] != null){
missile[i].draw(g);

}
}

}


public void mousePressed(MouseEvent e)
{
//loop through the amount of missiles
for(int i=0; i < missile.length; i++){

//if one of the missiles is null
if(missile[i] == null){

//set a missile object and break from the loop
missile[i] = gunShip.fireMissile(e.getX(), e.getY());
break;
}
}

}


public void mouseClicked(MouseEvent e)
{

}

public void mouseEntered(MouseEvent e)
{

}

public void mouseExited(MouseEvent e)
{

}

public void mouseReleased(MouseEvent e)
{

}

public void mouseMoved(MouseEvent e)
{

}

public void mouseDragged(MouseEvent e)
{
}
}




player class
public projectile fireMissile(int mouseXpos, int mouseYpos); is what you want to look at


import java.awt.*;
import java.applet.*;
import java.math.*;

public class player {

//position variables
private int xPos;
private int yPos;


//constructer
public player(int x, int y){
xPos = x;
yPos = y;

}

//set X and Y
public void setX(int x){
xPos = x;
}

public void setY(int y){
yPos = y;
}

public projectile fireMissile(int mouseXpos, int mouseYpos){
projectile missile = new projectile(xPos,yPos-15);

//final vector x y
int Cx = xPos + mouseXpos;
int Cy = yPos + mouseYpos;

//final vector magnitude and angle
double Cmagnitude = Math.sqrt((Cx)^2 + (Cy)^2);
double Cangle = Math.atan(Cy/Cx);

//send the vector angle to radians?
Cangle = Math.toRadians(Cangle);

//final equation for determining x velocity
//found this online
double CxFinal = -4*Math.cos(Cangle);

//set missile objects speed
missile.setX_speed( CxFinal );
missile.setY_speed( -4 );

return missile;
}


//drawing function
public void draw(Graphics g){

g.drawOval(xPos,yPos,15,15);
g.drawLine(xPos+7,yPos+7,xPos +7,yPos-5);
}

}




and just to be thorough here is the last java class:
projectile

import java.awt.*;
import java.applet.*;

public class projectile {

//position variables
private int xPos;
private int yPos;
private double speedX;
private int speedY;


//constructer
public projectile(int x, int y){
xPos = x;
yPos = y;

speedX = 0;
speedY = -4;

}

//set X and Y
public void setX(int x){
xPos = x;
}

public void setY(int y){
yPos = y;
}


//set the X and Y speed of the projectile
public void setX_speed(double x){
speedX = x;
}

public void setY_speed(int y){
speedY = y;
}


//move the projectile
public void move(){
xPos += speedX;
yPos += speedY;

}

//check and see if prijectile is out of screens bounds
public boolean outOfBounds(){
if(yPos > 300){
return true;
}
if(yPos < 0){
return true;
}

if(xPos > 500){
return true;
}
if(xPos < 0){
return true;
}

return false;

}


//drawing function
public void draw(Graphics g){
g.setColor(Color.red);
g.drawLine(xPos+7,yPos+7,xPos +7,yPos-5);
}

}


Share this post


Link to post
Share on other sites
Quote:
Original post by nuclearfission
...However I'm having trouble sending the missiles to where the mouse is being clicked. I've tried using vectors(trigonometry) to set a missile X velocity, but it just isn't working. Everytime I click on the mouse the missile shoots either in 1)a fixed point
or 2)Not where the mouse is. Anothing thing is that java works in radians not degrees, and I have not a clue how to relate radians on a graph?(probebly could have googled: to lazy though)


So yeah you need trigonometry, vectors, etc. First off you have trouble with the concept of radians. Here's a little history: some time a long time ago some bloke discovered that the ratio of a circle's circumference to its diameter is a constant. He called this pi. Then someone invented the radian. It is a way to measure an angle. Basically you take the length of the arc, cut out by an angle, like a piece of pie, in the circle and divide it by the circle's radius. This is how many radians the angle is. You can also convert this to degrees. Then since pi was on the scene and now radians blokes decided to get together and formalize. The rest is history.

180 degrees = pi radians (where pi = 3.14.........................).

So if you have theta degrees and wish to convert it to radians then
radians = theta * pi / 180(degrees).
If you wish to convert someRadians to degrees, just
degrees = someRadians * 180(degrees)/ pi.

I'm not going to look thru your code, but hopefully the following will be enough for you:

1) get mouse coordinates (where you are firing) -- call this
m = <mx, my>.
This is vector notation; if you do not get this ask.

2) get missile origination point. You should know this; it is where the missile tower sprite is --
o = <ox, oy>.

NOTE: (1) and (2) should be both described using coordinates from the same coordinate system. If you do not get this ask. It's important.

Then form a vector,
p = <mx - ox, my - oy>.

Then form a vector called
u = norm( <px, py> ),
where norm ( * ) is the vector normalization operation. Again ask or google if you're not familiar.

Then each frame the fired missiles position vector, f, can be updated like
f += speed * u,
where speed is the speed of the missile, and speed * u is the velocity of the missile.

Obviously, this last part, you can adjust to your taste, like if you need to do frame independent movement....

Hope this helps a bit (hopefully I didn't type in any mistakes).

Share this post


Link to post
Share on other sites
Okay sorry for the long wait, I had some priorities to attend. After trying your solutions(thanks btw), the missiles are still not moving towards the mouse. I might not understand the normalizing of the vectors?

Quote:
Then form a vector,
p = <mx - ox, my - oy>.


okay I was adding mx to ox, and my to oy. I fixed that, thank you.


Quote:
Then form a vector called
u = norm( <px, py> )


Is normalizing a vector the same as:

x = px/magnitude
y = py/magnitude

this is what I was understanding from the website: http://www.fundza.com/vectors/normalize/index.html

Quote:
Then each frame the fired missiles position vector, f, can be updated like
f += speed * u


I beleive I now have something simuliar to this in my program. Except f is the xPosition of the missile.

Share this post


Link to post
Share on other sites
I wrote a quick example in c#/xna. I think it will break everything down for you:

Code:

Vector2 target;
Vector2 gun;
Vector2 missile;

Console.WriteLine("Welcome to missile/vector sim.");
//
Console.WriteLine("The origin is at the bottom left (0,0).");
Console.WriteLine("The game area is 100x100.");
Console.WriteLine("Positive x is to the right; positive y is up.");
Console.WriteLine("Missile tower is located at (50,0).");
Console.WriteLine("\nFire missile to (0 to 100) => (x):");

string str = Console.ReadLine();
int x = int.Parse(str);


Console.WriteLine("Fire missile to (0 to 100) => (y):");
str = Console.ReadLine();
int y = int.Parse(str);

Console.WriteLine("\nYou're firing the missile to location: (" + x + "," + y + ").");

target = new Vector2(x, y);
gun = new Vector2(50, 0);
missile = new Vector2(50, 0);

Vector2 direction = new Vector2(0, 0);
direction = Vector2.Subtract(target, gun);
direction.Normalize();

Console.WriteLine("\n\nThe missile's direction vector is: <" + direction.X + "," + direction.Y + ">.");

float missileSpeed = 1.0f;

while (Vector2.Subtract(missile, target).Length() > 0.5)
{
Console.WriteLine("The missile's position is: (" + missile.X + "," + missile.Y + ").");
missile += missileSpeed*direction;
}
//
Console.Read();



Output:

Welcome to missile/vector sim.
The origin is at the bottom left (0,0).
The game area is 100x100.
Positive x is to the right; positive y is up.
Missile tower is located at (50,0).

Fire missile to (0 to 100) => (x):
87
Fire missile to (0 to 100) => (y):
37

You're firing the missile to location: (87,37).


The missile's direction vector is: <0.7071068,0.7071068>.
The missile's position is: (50,0).
The missile's position is: (50.70711,0.7071068).
The missile's position is: (51.41422,1.414214).
The missile's position is: (52.12132,2.12132).
The missile's position is: (52.82843,2.828427).
The missile's position is: (53.53554,3.535534).
The missile's position is: (54.24265,4.24264).
The missile's position is: (54.94975,4.949747).
The missile's position is: (55.65686,5.656854).
The missile's position is: (56.36397,6.36396).
The missile's position is: (57.07108,7.071067).
The missile's position is: (57.77818,7.778173).
The missile's position is: (58.48529,8.48528).
The missile's position is: (59.1924,9.192387).
The missile's position is: (59.89951,9.899493).
The missile's position is: (60.60661,10.6066).
The missile's position is: (61.31372,11.31371).
The missile's position is: (62.02083,12.02081).
The missile's position is: (62.72794,12.72792).
The missile's position is: (63.43504,13.43503).
The missile's position is: (64.14215,14.14213).
The missile's position is: (64.84926,14.84924).
The missile's position is: (65.55637,15.55635).
The missile's position is: (66.26347,16.26345).
The missile's position is: (66.97058,16.97056).
The missile's position is: (67.67769,17.67767).
The missile's position is: (68.3848,18.38478).
The missile's position is: (69.0919,19.09188).
The missile's position is: (69.79901,19.79899).
The missile's position is: (70.50612,20.5061).
The missile's position is: (71.21323,21.21321).
The missile's position is: (71.92033,21.92031).
The missile's position is: (72.62744,22.62742).
The missile's position is: (73.33455,23.33453).
The missile's position is: (74.04166,24.04164).
The missile's position is: (74.74876,24.74874).
The missile's position is: (75.45587,25.45585).
The missile's position is: (76.16298,26.16296).
The missile's position is: (76.87009,26.87007).
The missile's position is: (77.57719,27.57717).
The missile's position is: (78.2843,28.28428).
The missile's position is: (78.99141,28.99139).
The missile's position is: (79.69852,29.6985).
The missile's position is: (80.40562,30.4056).
The missile's position is: (81.11273,31.11271).
The missile's position is: (81.81984,31.81982).
The missile's position is: (82.52695,32.52692).
The missile's position is: (83.23405,33.23403).
The missile's position is: (83.94116,33.94114).
The missile's position is: (84.64827,34.64825).
The missile's position is: (85.35538,35.35535).
The missile's position is: (86.06248,36.06246).



To understand about vector normalization, this this wiki article section.

Also note I used XNA's Vector2 class for the vector op's to implement the thing I talked about in the last post. You can prolly just follow the code and implement something similar in yr program. Also, note how all physical objects in my simulation have a consistent coordinate system; if this requirement is not met, results may suck.

So basically my output has me firing the missile from position (50,0) -- the gun's position, to the user chosen target-- in this case, I chose target = (87,37); in your situation this would just be the target position chosen by the user's mouse.

Share this post


Link to post
Share on other sites
You should change the position and speed variables of the projectile to float or double. Here is a changed version of of the player.fireMissile function.


public projectile fireMissile(int mouseXpos, int mouseYpos){
float startX = xPos;
float startY = yPos-15;

projectile missile = new projectile(startX, startY);

float angle = Math.atan2(mouseYpos - startY, mouseXpos - startX);

missile.setX_speed( Math.cos(angle) );
missile.setY_speed( Math.sin(angle) );

return missile;
}

Share this post


Link to post
Share on other sites
Sorry about that, the Math functions return a double so you need to typecast them to a float or change the variables to doubles.
Some angles will be impossible if you use an integer instead of a type with a decimal point for your position and speed.

Share this post


Link to post
Share on other sites
HaHa! Sure it may not exactly go to the very point/tip of the mouse but it at least hits the mouse. For now it's good enough for me [grin]
public projectile fireMissile(int mouseXpos, int mouseYpos){
int startX = xPos;
int startY = yPos-15;

float mouseX = mouseXpos;
float mouseY = mouseYpos;

float finalX = startX;
float finalY = startY;

projectile missile = new projectile(startX, startY);

double angle = Math.atan2(mouseY - finalY, mouseX - finalX);

missile.setX_speed( Math.round(4*Math.cos(angle)) );
missile.setY_speed( Math.round(4*Math.sin(angle)) );

return missile;
}


Thank you signal_ and zoto for your time and help. I believe I'm going to now work on adding a meteor class. Hopefully I won't run into another issue again.[headshake]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this