Ship Lasers After Rotation

Started by AGP, November 06, 2008, 05:40:52 PM

Previous topic - Next topic

AGP

Test case #1: It's not happening. I already tested it without flipping firing to true. The second I rotate the ship I get weird locations for laserTarget. And again, what's odd is that the ship always flies towards targetCone (meaning it's not targetCone.getTransformedCenter()).

paulscode

Quote from: AGP on November 08, 2008, 01:03:42 AM
Test case #1: It's not happening.

This must mean that the problem is either in the align() or moveTowards() methods, right?

To rule out a problem in the align method, how does the orientation of laserTarget look?  You mentioned that it sometimes appears beside the ship.  In that case, is the laserTarget rotated the same way as targetCone or is it "sideways"?

AGP

If you notice, that line is more indented than the other ones: it was an attempted (and obviously failed) solution. But you make a good point: maybe neither the align method nor not aligning are working. Maybe I need to align differently. I'll try to answer your question and get right back to you.

paulscode

#18
I created a test applet to try and recreate the problem using the code as posted above.
http://www.paulscode.com/source/ShipFireProblem/

As you can see from this applet, both test cases I listed in my last post are successful.  This means that the align() and moveTowards() methods work fine.  The problem must be coming from somewhere else in your code, after you have placed the laser and laserTarget.

What else is happening behind the scenes in your program (how is the ship being rotated, etc)?  This really is a puzzling bug!

I also uploaded the source code for the above applet, but I doubt it will help much.  It is basically everything previously posted here plus methods to create the ship object and  rotate it with the mouse, etc:
http://www.paulscode.com/source/ShipFireProblem/ShipFireProblem.java


-- UPDATE --
When I created the above applet, I accidentally left out the following line:
laser1.addChild( laserTarget1 );

When I went back and added this line, the exact problem you described is showing up.  Here is another test applet demonstrating (exactly the same code as the last applet, except this time laserTarget is a child of laser1):
http://www.paulscode.com/source/ShipFireProblem/ShipFireProblem2.html
Source:
http://www.paulscode.com/source/ShipFireProblem/ShipFireProblem2.java

As you can see in this case, the laser is placed in the correct spot, but not laserTarget (as you described).  You can also see that the orientation of the laserTarget is correct, only it's position is wrong.

OK, so here is what APPEARS to be the source of the problem (still could be something else, of course).  It looks like the calls to "translate" are not being executed immediately.  They are happening later (perhaps when the frame is rendered), AFTER laserTarget has been assigned as a child to laser.  So when that first laser translation happens (to place it on top of the laserDummy), it drags the laserTarget along with it.

paulscode

A quick look at the javaDoc for the translate() method:
QuoteTranslates ("moves") the object in worldspace by modifying the translation matrix. The translation will be applied the next time the object is rendered.
This is definitely the source of your problem.

You'll have to rethink how laser firing works in your game, in order to take into account that translations do not happen immediately.

One way to do this would be to remove that line where you add the laserTarget as a child to laser.  For that matter, do not create a laserTarget object at all.  Instead, create a SimpleVector for the firing direction:
            firingVector = targetCone.getTransformedCenter().calcSub( laserDummy1.getTransformedCenter() );


Then in your firing method, use the following to move the laser:
                SimpleVector targetPoint = laser1.getTransformedCenter();
                targetPoint.add( firingVector );
                moveTowards( laser1, targetPoint, 0.2f );


I used this code in the test applet, which works nicely:
http://www.paulscode.com/source/ShipFireProblem/ShipFireProblem3.html
Source:
http://www.paulscode.com/source/ShipFireProblem/ShipFireProblem3.java

EgonOlsen

Quote from: paulscode on November 08, 2008, 08:55:19 AM
A quick look at the javaDoc for the translate() method:
QuoteTranslates ("moves") the object in worldspace by modifying the translation matrix. The translation will be applied the next time the object is rendered.
This is definitely the source of your problem.
Well, that's just bad wording. What i meant was, that the object won't move on screen until you render it. But that's only natural...i should remove this comment. If you translate something, getTransformedCenter() and similar methods immediately reflect the change. If you add something as a child, it inherits the translations of its direct and indirect parents. Maybe that is the problem here. Anyway, if laserTarget's purpose is to define a firing direction only, i agree that it would be better to calculate that by using some direction vectors instead of adding an invisible object for it and take the difference vector. Maybe that's the reason why i never really understood what laserTarget was about...

paulscode

Quote from: EgonOlsen on November 08, 2008, 10:12:18 AM
If you add something as a child, it inherits the translations of its direct and indirect parents. Maybe that is the problem here.
Ah, that makes sense.  So the parent's translations were being applied to the child, even though those translations were done before the child was added.  The resulting behavior (and the solution) is the same, just a different cause than the one I came up with  ;D

AGP

Paul, thank you very much. That direction vector will come in handy for the future. And I guess I missed re-reading the docs. I appreciate your time.

AGP

Now how would you make it so that the lasers don't stop mid-air (just keep going until they're out of sight, assuming they don't hit anything)?

paulscode

There are a few ways you could do that.  One way might be to stick them into a List, and have the firing method iterate through it to move them.  They could be removed from the world (and the list) after a certain amount of time or distance, or when they hit something.

I would create a new laser class that has the laser Object3D, the firing direction SimpleVector, the time (or frame number) that it was created (or distance traveled), and a boolean for if it has collided with something.  That would give the firing method enough information to move the laser or remove it, and start a collision animation of some sort if the boolean is true.

AGP

No, what I meant was that my lasers stop mid-air at what looks like twice the distance between the laserDummy and the targetCone. For some reason, in your applet the laser keeps going, but my code is just like yours as far as I can tell:


if (instance.firing) {
      SimpleVector firingVector1 = instance.targetCone.getTransformedCenter().calcSub(instance.laserDummy1.getTransformedCenter());
      SimpleVector firingVector2 = instance.targetCone.getTransformedCenter().calcSub(instance.laserDummy2.getTransformedCenter());

      SimpleVector target1 = instance.targetCone.getTransformedCenter();
      target1.add(firingVector1);

      SimpleVector target2 = instance.targetCone.getTransformedCenter();
      target2.add(firingVector2);
System.out.println("Target2 vector length: "+target2.length());

      instance.moveTowards(instance.laser2, target1, .2f);
      instance.moveTowards(instance.laser1, target2, .2f);
}

paulscode

You need to add the firing vector to the laser's position instead of the targetCone's position.  This will give the point in worldspace that the laser should be flying towards.

      SimpleVector target1 = instance.laser1.getTransformedCenter();
      target1.add(firingVector1);

      SimpleVector target2 = instance.laser2.getTransformedCenter();
      target2.add(firingVector2);
                                    System.out.println("Target2 vector length: "+target2.length());


The other thing I did differently, is that I didn't calculate the firingVectors inside of the firing method.  The way you are doing it, I immagine that if the ship were to rotate after the laser started flying, the laser would change direction mid-flight.  The firingVectors should be calculated when the laser is first created, and not change afterwards (unless you wanted to add in some type of homing behavior to the laser)

AGP

Absolutely right. Sloppy (or stupid, you decide) me. Thanks for holding my hand a little bit on this one. I appreciate it.

paulscode

LOL, np.  I am going to use a laser + targetCone setup like this in my game when I get around to working on shooting guns, so thanks for the concept.