/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.schedops.movement;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.Vector3f;
import org.xith3d.loop.opscheduler.Animatable;
import org.xith3d.loop.UpdatingThread.TimingMode;
import org.xith3d.scenegraph.Transform3D;
import org.xith3d.scenegraph.TransformGroup;
/**
* This class can be used as a base for a bullet.
* Add it to the scheduler of an ExtRenderLoop by calling the method addScheduledOperation(bullet).
* It is automatically removed from its parent BranchGroup and the scheduler when maxLifetime has been reached.
*
* @author Marvin Froehlich (aka Qudus)
*/
public abstract class Bullet extends TransformGroup implements Animatable
{
private Vector3f velocity = null;
private Tuple3f location = null;
private long birthTime = -1L;
private long lifeTime = -1L;
private long maxLifeTime;
private boolean alive;
/**
* A Bullet's animation is always running until it is dead.
*
* @return is this object's animation running
*/
public boolean isAnimating()
{
return ( false );
}
/**
* Starts the animation of this Bullet.
*/
public void startAnimation( long gameTime, TimingMode timingMode )
{
this.birthTime = gameTime;
}
/**
* A Bullet's animation cannot be stopped.
* Use setAlive() instead.
*
* @see #setAlive(boolean)
*/
public void stopAnimation()
{
throw new UnsupportedOperationException( "A Bullet's animation cannot be stopped. Use setAlive() instead." );
}
/**
* A Bullet is always persistent until it is dead.
*/
public boolean isPersistent()
{
return ( true );
}
/**
* @return the milliseconds this Bullet is alive.
*/
public long getLifeTime()
{
return ( lifeTime );
}
/**
* Sets this bullet's velocity vector.
* The length of this vector is the speed.
*
* @param velocity the new velocity vector
*/
public void setVelocity( Vector3f velocity )
{
this.velocity = velocity;
}
/**
* @return this Bullet's velocity vector.
* The length of this vector is the speed.
*/
public Vector3f getVelocity()
{
return ( velocity );
}
/**
* Sets this Bullet's current location.
*
* @param location the new location
*/
public void setLocation( Tuple3f location )
{
this.location = location;
Transform3D t3d = this.getTransform();
t3d.setTranslation( location );
this.setTransform( t3d );
}
/**
* @return this Bullet's current location.
*/
public Tuple3f getLocation()
{
return ( location );
}
/**
* @return this Bullet's speed along its velocity vector.
*/
public float getSpeed()
{
return ( velocity.length() );
}
/**
* Sets this Bullet's speed along its velocity vector.
*
* @param speed the new speed for this Bullet
*/
public void setSpeed( float speed )
{
velocity.normalize();
velocity.scale( speed );
}
/**
* {@inheritDoc}
*/
public void update( long gameTime, long frameTime, TimingMode timingMode )
{
lifeTime = ( gameTime - birthTime );
if ( lifeTime < maxLifeTime )
{
Tuple3f loc = getLocation();
final float factor = timingMode.getSecondsAsFloat( frameTime ) * 2f;
loc.set( loc.getX() + velocity.getX() * factor, loc.getY() + velocity.getY() * factor, loc.getZ() + velocity.getZ() * factor );
setLocation( loc );
}
else
{
setAlive( false );
}
}
/**
* Sets the maximum time, this Bullet will be alive.
*
* @param maxLifeTime maximum life time in milliseconds
*/
public void setMaxLifeTime( long maxLifeTime )
{
this.maxLifeTime = maxLifeTime;
}
/**
* @return the maximum time, this Bullet will be alive
*/
public long getMaxLifeTime()
{
return ( maxLifeTime );
}
/**
* Sets this Object alive or dead.
* If it is killed, is is also removed from its parent group.
*
* @param alive if false, the object will be removed from the scheduler next loop iteration
*/
public void setAlive( boolean alive )
{
this.alive = alive;
if ( ( !alive ) && ( this.getParent() != null ) )
detach();
}
/**
* @return false -> the object will be removed from the scheduler next loop iteration, true otherwise
*/
public boolean isAlive()
{
return ( alive );
}
/**
* Creates a new Bullet.
* This calls setVelocity, setLocation, setAlive, setMaxLifeTime.
*
* @param velocity the velocity vector this bullet will move along. Its length is the speed.
* @param maxLifeTime the maximum amount of milliseconds this bullet will remain in the scheduler.
*/
public Bullet( Vector3f velocity, long maxLifeTime )
{
super();
setVelocity( velocity );
setLocation( new Vector3f( 0f, 0f, 0f ) );
setAlive( true );
setMaxLifeTime( maxLifeTime );
}
}