📄 lasershot.java
字号:
// LaserShot.java
// Andrew Davison, May 2003, dandrew@ratree.psu.ac.th
/* Creates the scene subgraph:
beamTG --> beamSW --> beamDir TG --> beam cylinder
|
--> explShape (explosion anim)
The beamTG is for moving the beam and explosion. The Switch is
for visibility (nothing, beam, or explosion), and the beamDir TG
is for tweaking the position of the cylinder and rotating it.
The KeyBehavior object calls fireBeam() in AmmoManager, which
then calls requestFiring() in each of its LaserShot objects.
If the LaserShot is not in use (inUse == false) then LaserShot starts
an AnimBeam thread which calls LaserShot's moveBeam(). inUse is set
to true.
moveBeam() incrementally moves the beam forward, starting from the
current viewer position (steerTG). If the beam gets close
to the target then the explosion is shown, otherwise the beam disappears
after reaching a ceratin MAX_RANGE from the gun. inUse is set to false
again.
*/
import java.text.DecimalFormat;
import javax.media.j3d.*;
import com.sun.j3d.utils.geometry.*;
import javax.vecmath.*;
public class LaserShot
{
private static final double MAX_RANGE = 6.0; // max distance travelled
private static final double STEP = 1.0; // distance travelled each increment
private static final Vector3d INCR_VEC = new Vector3d(0, 0, -STEP);
private static final long SLEEP_TIME = 100; // delay between moves of beam
private static final double HIT_RANGE = 1.0; // how close to count as a hit
private TransformGroup steerTG; // the TG for the user's viewpoint
private TransformGroup beamTG; // moving the beam/explosion
private Switch beamSW; // for beam/explosion visibility
private Cylinder beam; // the beam is a cylinder
private ImageCsSeries explShape; // holds the explosion
private boolean inUse; // whether beam is in flight or not
private Vector3d targetVec; // location of target
// for repeated calcs
private Transform3D tempT3d = new Transform3D();
private Transform3D toMove = new Transform3D();
private Transform3D localT3d = new Transform3D();
private Vector3d currVec = new Vector3d();
public LaserShot(TransformGroup steerTG,
ImageComponent2D[] exploIms, Vector3d tarVec)
{
this.steerTG = steerTG;
makeBeam(exploIms);
targetVec = tarVec;
inUse = false;
} // end of LaserShot()
private void makeBeam(ImageComponent2D[] exploIms)
// Create the beam and explosion subgraph detailed above.
{
// beam position
Transform3D beanT3d = new Transform3D();
beanT3d.rotX(Math.PI/2); // 90 degrees, so pointing into scene
beanT3d.setTranslation(new Vector3d(0, -0.3, -0.25)); // down and in
TransformGroup beanDir = new TransformGroup();
beanDir.setTransform(beanT3d);
beam = new Cylinder(0.05f, 0.5f, makeRedApp() ); // thin red cylinder
beam.setCapability(Node.ALLOW_LOCAL_TO_VWORLD_READ); // for testing posn later
beanDir.addChild( beam );
// create switch for visibility
beamSW = new Switch();
beamSW.setCapability(Switch.ALLOW_SWITCH_WRITE);
beamSW.addChild( beanDir ); // add beam to the switch
beamSW.setWhichChild( Switch.CHILD_NONE ); // invisible initially
// add the explosion to the switch, centered at (0,0,0), size 2.0f
explShape = new ImageCsSeries( new Point3f(), 2.0f, exploIms);
beamSW.addChild( explShape );
beamSW.setWhichChild( Switch.CHILD_NONE ); // invisible initially
// top-level beam TG
beamTG = new TransformGroup();
beamTG.addChild( beamSW );
beamTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
beamTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
} // end of makeBeam()
private Appearance makeRedApp()
{
Color3f medRed = new Color3f(0.8f, 0.4f, 0.3f);
Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f specular = new Color3f(0.9f, 0.9f, 0.9f);
Material redMat = new Material(medRed, black, medRed, specular, 80.0f);
redMat.setLightingEnable(true);
Appearance redApp = new Appearance();
redApp.setMaterial(redMat);
return redApp;
} // end of makeRedApp()
public TransformGroup getTG()
// accessed by AmmoManager
{ return beamTG; }
// ------------------------ shot methods ----------------
public boolean requestFiring()
// If the beam is not being used then fire it
{ if (inUse)
return false;
else {
inUse = true;
new AnimBeam(this).start(); // calls moveBeam() inside a thread
return true;
}
} // end of fireBeam()
public void moveBeam()
/* Move the beam with a delay between each move.
If the beam gets close to the target then show the explosion
otherwise the beam disappears when it reaches MAX_RANGE
*/
{ // place the beam at the current gun hand position
steerTG.getTransform( tempT3d );
// System.out.println("steerTG Transform3D: " + tempT3d);
beamTG.setTransform( tempT3d);
showBeam(true);
double currDist = 0.0;
boolean hitTarget = closeToTarget();
while ((currDist < MAX_RANGE) && (!hitTarget)) {
doMove(INCR_VEC);
hitTarget = closeToTarget();
currDist += STEP;
try {
Thread.sleep(SLEEP_TIME);
}
catch (Exception ex) {}
}
showBeam(false); // make beam invisible
if (hitTarget)
showExplosion(); // if a hit, show explosion
inUse = false; // shot is finished
} // end of moveBeam()
private void doMove(Vector3d mv)
{
beamTG.getTransform( tempT3d );
toMove.setTranslation( mv );
// System.out.println("Moving: " + mv);
tempT3d.mul(toMove);
beamTG.setTransform( tempT3d );
} // end of doMove()
private boolean closeToTarget()
/* The beam is close if its current position (currVec)
is a short distance from the target position (targetVec).
*/
{
beam.getLocalToVworld( localT3d ); // get beam's TG in world coords
localT3d.get(currVec); // get (x,y,z) component
// System.out.println("currVec: " + currVec);
currVec.sub(targetVec); // distance between two positions
double sqLen = currVec.lengthSquared();
if (sqLen < HIT_RANGE*HIT_RANGE)
return true;
return false;
} // end of closeToTarget()
private void showBeam(boolean toVisible)
// make beam visible/invisible
{
if (toVisible)
beamSW.setWhichChild(0); // make visible
else
beamSW.setWhichChild( Switch.CHILD_NONE ); // make invisible
} // end of showBeam()
private void showExplosion()
// start the explosion
{
beamSW.setWhichChild(1); // make visible
explShape.showSeries(); // boom!
beamSW.setWhichChild( Switch.CHILD_NONE ); // make invisible
} // end of showExplosion()
// -------------------- for debugging ---------------------
private void printTG(TransformGroup tg, String name)
// display info about TransformGroup called name
{
Transform3D t3d = new Transform3D();
tg.getTransform( t3d );
// System.out.println(name + " Transform:\n" + t3d);
Vector3d vec = new Vector3d();
t3d.get(vec);
DecimalFormat df = new DecimalFormat("0.00"); // 2 dp
// System.out.println(name + " Vector: " + vec);
System.out.println(name + " Vector: (" +
df.format(vec.x) + ", " + df.format(vec.y) + ", " +
df.format(vec.z) + ")");
} // end of printTG()
} // end of LaserShot class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -