package com.codebynumber.java3d.breakout; import javax.media.j3d.Appearance; import javax.media.j3d.Material; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Vector3d; import com.sun.j3d.utils.geometry.Sphere; /** * Transform group that contains the ball for Breakout. Methods update() and * hitsomething() get called by TimeBehavior and Collision respectively. These * methods affect the translation position and direction of the TransformGroup for * the ball sphere. * @author codebynumber.com * */ public class Ball extends TransformGroup { /** Ball radius is 20 cm. */ public static final float BALL_RADIUS = 0.2f; /** Move at 2.0 m/s. */ private static final double moveRate = 2.0 / 1000; /** Place the ball 1.0 units into the scene to begin with */ private Vector3d startingPosition = new Vector3d(0.0, 0.0, -1.1); /** Send it into the scene to the right to begin with */ private Vector3d direction = new Vector3d(1.0, 0.0, -1.0); private Sphere ball; /** Last timestamp that an update was made, used in movement code. */ private long lastUpdate; private Transform3D t3d; /** * Create ball and add it to transform group, ready to place in scene. */ public Ball() { super(); setCapability(TransformGroup.ALLOW_TRANSFORM_READ); setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); createBall(); } /** * Initializes ball and Transform3D for location. */ private void createBall() { t3d = new Transform3D(); ball = new Sphere(BALL_RADIUS); Appearance app = new Appearance(); Material greenMat = new Material(Breakout.green, Breakout.black, Breakout.green, Breakout.white, 65.0f); greenMat.setLightingEnable(true); app.setMaterial(greenMat); ball.setAppearance(app); //Grab the system time for movement lastUpdate = System.currentTimeMillis(); t3d.setTranslation(startingPosition); TransformGroup tg = new TransformGroup(t3d); tg.addChild(ball); addChild(tg); } /** * Move ball according to moveRate * elapsed frames */ public void update() { long currUpdate = System.currentTimeMillis(); Transform3D newMove = new Transform3D(); //Determine how much the ball should move in elapsed time double z = moveRate * (currUpdate-lastUpdate); if (direction.z < 0) { z = -z; } double x = 0.0; if (direction.x != 0.0) { x = moveRate * (currUpdate-lastUpdate); if (direction.x < 0) { x = -x; } } //Add amount to this.Transform3D getTransform(t3d); newMove.setTranslation(new Vector3d(x, 0.0, z)); t3d.mul(newMove); setTransform(t3d); lastUpdate = currUpdate; } /** * Change direction according to changeVect. Called after a collision. * @param changeVect multiplier for direction (-1 to change) */ public void hitSomething(Vector3d changeVect) { direction.x = changeVect.x * direction.x; direction.y = changeVect.y * direction.y; direction.z = changeVect.z * direction.z; } }