Jump to content

Java Game - Math Issue


Ronan

Recommended Posts

I finished building my Space Invaders / Arcadians clone the other day, so I've settled on starting another project I thought up whilst developing the previous game.

 

Currently it's all simply floating around in my head apart from mindless notes scribbled everywhere, but whenever I get the time to get round to it I'll get the brief down on paper in a (somewhat) orderly fashion.

 

The basic idea of the game will be a rocket / missile following the player's mouse with targets in a level to destroy based on the explosion of the rocket. Of-course, got all sorts of additions like obstacles, rocket-fuel perhaps, enemies (room for some A.I!), but that's all to come.

 

Right now, I drew up a very quick base for the rocket and animation. It's the first time I've done an animated-style object in Java but I think that's working reasonably. My problem is with the Rocket exploding upon contact with the mouse location. Sometimes it works, others it goes very odd.

 

As far as I can tell, it's because I'm forcing it to move too large a distance 'over' the mouse-location, making it jump back and forth past the mouse very quickly. But at the moment, I've hardly got any time on my hands due to assignments, so I figured I'd utilise the new forum! :smile:

 

The rogue issue is when the following happens :-

 

[spoiler=Large(ish) Image]

probleml.png

 

 

That image was modified in Photoshop to try and show what's happening as a print-screen doesn't quite cut it. If you run the App you'll see what I mean.

 

Oh, and the Red-Tip on the end of the missile corresponds to the stored Point2D location of the 'tip'. I'm comparing this to the mouse-location to check when to explode, rather than the Image (X,Y) coordinates as it would then try to collide with a point offset from the mouse cursor.

 

It's a bit of a strange issue, I'm sure that with a bit of time and fiddling it's solvable, but at the moment I just don't have that! Provides something interesting for anyone to puzzle over too! :P

 

I've uploaded the NetBeans Project folder as a 'zip' archive - easiest way I can think of providing it all in working condition, but if anyone knows a better way to do it feel free to say! :)

 

Link: mediafire.com/?eujn0gm2qyw

 

Alternatively, the relevant source code is here (Cheers sees_all!) :-

 

[spoiler=Main]

/* Fired every update. */
   private void processMove() {
	//Determine the angle between the tip of the rocket and the mouse.
       theta = Methods.AngleBetweenPoints(new Point2D.Double(tipX, tipY),
               new Point2D.Double(mouseX, mouseY));

	/* Determine the new point to move the image to based on the angle between the Tip of the rocket and the mouse location.
	 * I assume this is throwing it off as it's pushing it too far past rather than recognising collision. */
       Point2D.Double newPoint = Methods.GetNewAngle(4, theta, rocketX, rocketY);

	//Get a transform instance to get the new point of the rocket tip.
       AffineTransform at = AffineTransform.getRotateInstance(theta, rocket.getWidth() / 2, rocket.getHeight() / 2);
       Point2D newTipPoint = at.transform(new Point2D.Double(rTipX, rTipY), null);

	//Fix the angle.
       theta = Math.toRadians(Math.toDegrees(theta) + 90);

       rocketX = newPoint.x;
       rocketY = newPoint.y;

       tipX = newTipPoint.getX() + rocketX;
       tipY = newTipPoint.getY() + rocketY;
   }

   private void paintPanel(Graphics g) {
       ...

       if(!explosionVisible) {
           if(Methods.Distance(new Point2D.Double(tipX, tipY), new Point2D.Double(mouseX, mouseY)) < 5) {
               explosionVisible = true;
           }
       }

       ...
   }

 

 

 

[spoiler=Methods]

   public static Double AngleBetweenPoints(Point2D.Double point1, Point2D.Double point2) {
       double xDistance = point2.x - point1.x;
       double yDistance = point2.y - point1.y;

       double theta = Math.atan2(yDistance, xDistance);

       return theta;
   }

   public static Point2D.Double GetNewAngle(double value, double theta, double x, double y) {
       double dx = xComponent(value, theta);
       double dy = yComponent(value, theta);

       return new Point2D.Double(x + dx, y + dy);
   }

   public static double xComponent(double value, double theta) {
       return value * Math.cos(theta);
   }

   public static double yComponent(double value, double theta) {
       return value * Math.sin(theta);
   }

   public static double Distance(Point2D.Double p1, Point2D.Double p2) {
       return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
   }

 

 

 

Any ideas and i'd be happy to hear them!

Link to comment
Share on other sites

Looking at your code it appears you're basically saying

 

if(mouseLocation)

explodeanimation.setvisible;

 

Seems like it's doing exactly what you're telling it to - when do you want the explosion to occur?

Maybe I'm just reading your code wrong, I can't run it at the moment.

polvCwJ.gif
"It's not a rest for me, it's a rest for the weights." - Dom Mazzetti

Link to comment
Share on other sites

It's not the explosion that's an issue, that's all working fine - rather it's the movement of both the image (x,y) location and the rocket-tip (x,y) location. I believe that as it gets close, it is pushed past the mouse-location but I'm not certain.

 

I've varied the distance upon which the explosion occurs and yet the issue still occurs if the mouse is moved close enough to the tip of the rocket. :unsure:

 

It's a rather strange issue and pretty tricky to describe, if you can run the code at some point you'll see the symptoms. :)

Link to comment
Share on other sites

Basically you want it to (when it explodes) explode in a stationary fashion, but the explosion animation follows the mouse around?

 

I won't be able to run it for another 10 hours lol.

polvCwJ.gif
"It's not a rest for me, it's a rest for the weights." - Dom Mazzetti

Link to comment
Share on other sites

The Rocket is represented by a custom-designed Animation class, that all works ok though so it can simply be assumed to be the same as an Image. The rocket is supposed to follow the mouse around, in a reasonable fashion, basically moving in the direction of the mouse by a specified interval every update, rotated to point in the direction of the mouse.

 

Upon the tip of the rocket touching the mouse location, it should explode. Because of the way the images have been created, a square due to rotation issues, the point of the rocket isn't the same as the X,Y location of the image. Rather, it's (initially, at 0 Radians rotation) at ImageX + 30, ImageY.

 

Due to this, whenever the image is updated and moved towards the mouse position, and rotated, the tip of the rocket's (X,Y) location must be calculated too, this seems to be done fine. For collision, and exploding, we want it to occur when the tip of the rocket hits the mouse location. Sometimes this occurs fine, but in certain instances, seemingly when the rocket should only move a small distance towards the mouse (i.e When the mouse is close to the rocket's previous location), it distorts and flips around the mouse pointer, never exploding as the tip is never equal / close to the mouse's location.

 

The problem is with that, something's up with the logic / math when moving the position of the rocket when it's very close to the mouse cursor. And it's one of those annoying, hard to diagnose issues so frequently found in programming! :P

Link to comment
Share on other sites

Could you please provide the (relevant) source code here? Can you also describe the physics of what you're trying to accomplish?

You're probably going to need to add some conditional statements for fringe states.

99 dungeoneering achieved, thanks to everyone that celebrated with me!

 

♪♪ Don't interrupt me as I struggle to complete this thought
Have some respect for someone more forgetful than yourself ♪♪

♪♪ And I'm not done
And I won't be till my head falls off ♪♪

Link to comment
Share on other sites

Added the main snippets from the code up there, it's pretty messy at the moment due to being a mock-up but should be readable.

 

I've got a canvas with a rocket moving around in it. I'd like this rocket to move towards the mouse cursor, which can be moved around, at a steady interval. Upon collision with the mouse cursor, it should 'explode', removing the rocket and displaying an explosion animation at that point. The rocket should be rotated towards the mouse cursor location upon every update to look like it's 'tracking' the mouse. The collision is based on the tip of the rocket touching the mouse-cursor's location and the tip of the rocket is a bit offset from the top-left of the image.

 

Edit :- Had a slight breakthrough with this. From what I can tell, it's inconsistent to check for collision based upon the tip of the rocket and yet move the image based on the top-left of the image coordinates. I'll redesign the movement method to process 'everything' based upon the tip of the rocket and then calculate where the image should be drawn from that, rather than the other way around. Seems to make more sense the way I'm looking at it, but have to wait and see! :)

Link to comment
Share on other sites

Added the main snippets from the code up there, it's pretty messy at the moment due to being a mock-up but should be readable.

 

I've got a canvas with a rocket moving around in it. I'd like this rocket to move towards the mouse cursor, which can be moved around, at a steady interval. Upon collision with the mouse cursor, it should 'explode', removing the rocket and displaying an explosion animation at that point. The rocket should be rotated towards the mouse cursor location upon every update to look like it's 'tracking' the mouse. The collision is based on the tip of the rocket touching the mouse-cursor's location and the tip of the rocket is a bit offset from the top-left of the image.

 

Edit :- Had a slight breakthrough with this. From what I can tell, it's inconsistent to check for collision based upon the tip of the rocket and yet move the image based on the top-left of the image coordinates. I'll redesign the movement method to process 'everything' based upon the tip of the rocket and then calculate where the image should be drawn from that, rather than the other way around. Seems to make more sense the way I'm looking at it, but have to wait and see! :)

 

You could also to check to see if the rocket is within range - for instance, if the rocket's distance away from the mouse is within the length of the next update, blow it up next time instead of updating it's position.

I.E. - mouse is at 300,400, the rocket is at 305,400 and the update size is 10. Therefore, the rocket should blow up next time, but if the logic isn't there it could skip the mouse and move to 295,400

99 dungeoneering achieved, thanks to everyone that celebrated with me!

 

♪♪ Don't interrupt me as I struggle to complete this thought
Have some respect for someone more forgetful than yourself ♪♪

♪♪ And I'm not done
And I won't be till my head falls off ♪♪

Link to comment
Share on other sites

Funnily enough I tried implementing that idea previously, logically it sounded entirely feasible, and yet the problem was still occurring afterwards. <_< Likely it was an issue with my implementation of it but it certainly seems that I should rethink the system if it's causing this amount of confusion, flashes warning signs for future development!

Link to comment
Share on other sites

Funnily enough I tried implementing that idea previously, logically it sounded entirely feasible, and yet the problem was still occurring afterwards. <_< Likely it was an issue with my implementation of it but it certainly seems that I should rethink the system if it's causing this amount of confusion, flashes warning signs for future development!

 

Well, spam the terminal with print statements. It'll give you much more insight into whats happening than a stranger who only looks at your code :P

 

Best of luck.

99 dungeoneering achieved, thanks to everyone that celebrated with me!

 

♪♪ Don't interrupt me as I struggle to complete this thought
Have some respect for someone more forgetful than yourself ♪♪

♪♪ And I'm not done
And I won't be till my head falls off ♪♪

Link to comment
Share on other sites

I managed to solve it! :) The problem was in that it was trying to rotate to point in the direction of the mouse, but when close enough, due to the size of the image it was rotating the tip of the missile to the 'opposite' side of the mouse, and rotating back and forth due to that.

 

I've put a check on both the tip of the rocket and the image coordinates for collision and that seems to be working a lot better and with minimal side-effects.

 

Thanks both y_guy and sees_all for helping! :smile:

Link to comment
Share on other sites

Furthermore - don't go for time-constrained, dodgy solutions! :P The way I fixed it before it made the rocket explode a bit early obviously at certain rotations.

 

Rather, based upon the problem I've figured out the rotation point for the Tip of the missile, then modified it's location so it's at the same point as it was before and further modified the image's coordinates to make it display appropriately for rotation. This way it seems to work perfectly and as we're processing movement after moving the image's coordinates, it doesn't affect the position in a negative way! :)

 

The fixed method, before clean-up is here if anyone's interested in it :-

 

[spoiler=processMove()]

private void processMove() {
       theta = Methods.AngleBetweenPoints(new Point2D.Double(tipX, tipY), new Point2D.Double(mouseX, mouseY));

       AffineTransform at = AffineTransform.getRotateInstance(theta, rocket.getWidth() / 2, rocket.getHeight() / 2);
       Point2D newTip = at.transform(new Point2D.Double(rTipX, rTipY), null);

       double startingTipX = tipX;
       double startingTipY = tipY;

       tipX = rocketX + newTip.getX();
       tipY = rocketY + newTip.getY();

       double dX = tipX - startingTipX;
       double dY = tipY - startingTipY;

       tipX = startingTipX;
       tipY = startingTipY;
       rocketX = tipX - dX;
       rocketY = tipY - dY;

       double xChange = Methods.xComponent(4, theta);
       double yChange = Methods.yComponent(4, theta);

       tipX += xChange;
       tipY += yChange;

       rocketX = tipX - newTip.getX();
       rocketY = tipY - newTip.getY();

       theta = Math.toRadians(Math.toDegrees(theta) + 90);
   }

 

 

 

If anyone's interested in the code and the final solution (for the moment :P), it's uploaded here :- mediafire.com/?zmw0ddzn1jy

 

Edit :-

 

(Changed the explosion effect just slightly from the last uploaded source - rather than use an image, i've just got an increasing-size circle to tie in more with later ideas.)

 

Also wondering if this forum could be used for development 'plotting' purposes, pretty much to track and publish development - although I guess there's blogs for that...

Link to comment
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
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.