Simple Value Modificator

Hi everyone

Here is simple modificator

First, base class
[java]
public abstract class Modificator
{
// -------------------------------------------------------- \
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================

/**
 * Called to update modificator
 * 
 * @param timePerFrame 
 */
public abstract void onUpdate( final float timePerFrame );

/**
 * Called to start modificator
 */
public abstract void Start( );

/**
 * Called to stop modificator
 */
public abstract void Stop( );

/**
 * Called on finish
 */
protected abstract void onFinish( );

/**
 * Called on start
 */
protected abstract void onStart( );

// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
// -------------------------------------------------------- \\

}
[/java]

And here is simple realization
[java]

public final class ChangeableModificator extends Modificator
{
// -------------------------------------------------------- \
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================

/** Time for which modifier should reach maxValue **/
private float mDuration;

/** Current Value **/
private float mValue;

/** Maximum value **/
private float maxValue;

/** Is Modifier finished **/
private boolean mFinished = false;

/** Elapsed time **/
private float mElapsedTime;

/** Collection of listeners **/
private IModificatorListener mListener;

// ===========================================================
// Constructors
// ===========================================================

private ChangeableModificator( ) throws Exception
{
    throw new Exception( "ChangeableModificator empty constructor" );
}

/**
 * 
 * 
 * @param pDuration
 * @param pStartValue
 * @param pMaxValue 
 */
public ChangeableModificator( final float pDuration, final float pStartValue, final float pMaxValue)
{
    mDuration = pDuration;
    mValue = pStartValue;
    maxValue = pMaxValue;
}

// ===========================================================
// Getter & Setter
// ===========================================================

/**
 * 
 * Main point of <b>Changeable</b>Modifier
 * 
 * @param pDuration
 * @param pMaxValue 
 */
public final void setValues( final float pDuration, final float pMaxValue )
{
    mDuration = pDuration;
    maxValue = pMaxValue;
}

// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================

@Override
public final void onUpdate( final float timePerFrame )
{
    if ( mFinished )
        return;
    
    mElapsedTime += timePerFrame;
    
    //Change value according elapsed time
    if ( mElapsedTime >= mDuration )
    {
        //Modification time elapsed early
        mValue = maxValue;
        Stop( );
        return;
    }
    else
    {
        //Find out value
        final float deltaTime = mElapsedTime / mDuration;
        mValue = maxValue * deltaTime;
        
        if ( mValue >= maxValue )
        {
            //Modificator finished
            Stop( );
            return;
        }
    }
    
    //Inform listeners about mValue
    if ( mListener != null )
        mListener.onModifying( mValue, this );
}

@Override
public final void Start( )
{
    mFinished = false;
    mElapsedTime = 0f;
    
    onStart( );
}

@Override
public final void Stop( )
{
    mFinished = true;
    
    onFinish( );
}

/**
 * Add listener for this modificator
 * 
 * @param pListener 
 */
public final void setListener( final IModificatorListener pListener ) throws Exception
{
    mListener = pListener;
}

@Override
protected final void onFinish( )
{
    if ( mListener != null )
        mListener.onModificatorFinished( mValue, this );
}

@Override
protected final void onStart( )
{
    if ( mListener != null )
        mListener.onModificatorStarted( this );
}

// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
// -------------------------------------------------------- \\

}

[/java]

Listener of modificator
[java]

public interface IModificatorListener
{
/**
* Called after modificator finished
*
*
* @param pModificator
* @return
*/
public boolean onModificatorFinished( final float pValue, final Modificator pModificator );

/**
 * Called after modificator started
 * 
 * 
 * @param pModificator
 * @return 
 */
public boolean onModificatorStarted( final Modificator pModificator );

/**
 * Called when value changed
 * 
 * 
 * @param pValue
 * @param pModificator
 * @return 
 */
public boolean onModifying( final float pValue, final Modificator pModificator );

}

[/java]

It’s very usefull

2 Likes

It looks very cool!

How should I register the Listener?
And where shlould be used update()? Control or AppState?

Thanks.

Example

Main.class
[java]

/** Collection of GameObjects **/
private final ArrayList<GameObject> GAME_OBJECTS = new ArrayList<GameObject>( 1 );

@Override
public final void simpleInitApp( )
{
	//Create GameObject
	final GameObject gameObject = new GameObject( );
	GAME_OBJECTS.add( gameObject );
	
	//Create Cube
	final Box box = new Box( 1f, 1f, 1f );
	mBox = new Geometry( "GameObject", box );
	final Material material = assetManager.LoadMaterial( "Common/MatDefs/Misc/Unshaded.j3md" );
	
	//Attach cube to GameObject as Spatial
	gameObject.attachChild( mBox );
	
	//Create listener for modificator
	final IModificatorListener modificatorListener = new IModificatorListener( )
	{
		@Override
		public final boolean onModificatorFinished( final float pValue, final Modificator pModificator )
		{
			pModificator.Start( );//Start again
			return( true );
		}
		
		@Override
		public final boolean onModificatorStarted( final Modificator pModificator )
		{
			
		}
		
		@Override
		public final boolean onModifying( final float pValue, final Modificator pModificator )
		{
			gameObject.setLocalRotation( pValue );
		}
	};
	
	//Create modificator
	//From 0 to 180 in 10
	final ChangeableModificator modificator = new ChangeableModificator( modificatorListener, 10f, 0f, 180f );
	
	//Attach modificator to gameObject
	gameObject.attachModificator( modificator );
	
	/**
	 * Some code
	**/
}

@Override
public final void simpleUpdate( final float timePerFrame )
{
	for( GameObject gameObject : GAME_OBJECTS )
	{
		gameObject.Update( timePerFrame );
	}
	
	/**
	 * Some other code
	**/
}

@Override
public final void simpleRender( final RenderManager renderManager )
{
	for( GameObject gameObject : GAME_OBJECTS )
	{
		gameObject.Render( renderManager );
	}
	
	/**
	 * Some other code
	**/
}

[/java]

GameObject.class
[java]
public class GameObject extends Node
{
// -------------------------------------------------------- \
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================

/** Collection of modificators **/
protected ArrayList<Modificator> modificators;

/** Collection of attached GameObjects **/
protected ArrayList<GameObject> mChildren;

/** Skip Update logic **/
protected boolean mSkipUpdate;

/** Called to skip Rendering logic **/
protected boolean mSkipRender;

// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================

/**
 * Hides of shows this object
 * @param pAffectsChildren - True if this should affect's children as well
**/
public void setVisibility( final boolean pVisibility, final boolean pAffectsChildren ) throws Exception
{
	if ( pVisibility )
	{
		if ( mVisible )
			throw new Exception( "This GameObject is already visible" );
		
		//Make object visible
		mVisible = true;
		setCullHint( CullHint.Dynamic );
	}
	else
	{
		if ( !mVisible )
			throw new Exception( "This GameObject is already hidden" );
			
			//Hide object
			mVisible = false;
			setCullHint( CullHint.Always );
	}
	
	if ( pAffectsChildren && mChildren != null && !mChildren.isEmpty( ) )
	{
		for( GameObject child : mChildren )
		{
			child.setVisibility( pVisibility, pAffectsChildren );
		}
	}
}

public boolean isVisible( ) { return( mVisible ); }

public void setSkipUpdate( final boolean pValue ) { mSkipUpdate = pValue; }
public boolean isUpdateSkiped( ) { return( mSkipUpdate ); }

public void setSkipRender( final boolean pValue ) { mSkipRender = pValue; }
public boolean isRenderSkiped( ) { return( mSkipRender ); }

public void registerModificator( final Modificator pModificator )
{
	if ( modificators == nul )
		modificators = new ArralyList<Modificator>( 1 );
	
	if ( !modificators.add( pModificator ) )
		throw new Exception( "This modificator is already attached to this GameObject" );
}

public void unregisterModificator( final Modificator pModificator )
{
	if ( modificators == null || modificators.isEmpty( ) )
		return;
	
	if ( !modificators.remove( pModificator ) )
		throw new Exception( "This modificator never been attached" );
}

// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================

/**
 * Called to update logic
**/
public final void Update( final float timePerFrame )
{
	if ( mSkipUpdate )
		return;
	
	//Update all attached modificator
	for( Modificator modificator : modificators )
	{
		if ( !modificator.mFinished )
			modificator.onUpdate( timePerFrame );
	}
	
	onUpdate( timePerFrame );
	
	//Update all attached children
	for( GameObject child : mChildren )
	{
		child.Update( timePerFrame );
	}
}

/**
 * Override this method to handle logic update
**/
protected void onUpdate( final float timePerFrame )
{
	
}

/**
 * Called when it's time to render
**/
public final void Render( final RenderManager renderManager )
{
	if ( mSkipRender )
		return;
	
	onRender( renderManager );
	
	//Call Render for all attached children
	for( GameObject child : mChildren )
	{
		child.Render( renderManager );
	}
}

/**
 * Override this method to handle render logic
**/
protected void onRender( final RenderManger renderManager )
{
	
}

// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
// -------------------------------------------------------- \\

}
[/java]

@gforcer18 why should I use this instead of a Control?

@kwando said: @gforcer18 why should I use this instead of a Control?
no reason, it's all up to you to decide how game logic will work

it’s just an example of timePerFrame usage

The mining of this code is how to change the value depending on elapsed and given time

Have you looked at JME’s cinematics stuff? I was always under the impression that it was designed for these sorts of things also.

…but it does kind of seem like a long way to go to avoid using a 4 or 5 line control. But I admit I didn’t look at it in detail.

@pspeed said: Have you looked at JME's cinematics stuff? I was always under the impression that it was designed for these sorts of things also.

…but it does kind of seem like a long way to go to avoid using a 4 or 5 line control. But I admit I didn’t look at it in detail.

Is it possible to update Control without attaching it to a Spatial?

@mifth nothing is stopping you from calling the update method on your Control implementations, though I think it is a bad design decision to do so.

Sorry, i later realized my mistake

Here is totally other code
SpanValueModificator
[java]
public final class SpanValueModificator extends Modificator
{
// -------------------------------------------------------- \
// ===========================================================
// Constants
// ===========================================================

/** Collection of listeners **/
private final IModificatorListener mListener;

// ===========================================================
// Fields
// ===========================================================

/** Time for which modifier should reach maxValue **/
private float mDuration;

/** Value at start **/
private float minValue;

/** Current Value **/
private float mValue;

/** Span between start and finish value's **/
private float mSpan;

/** Maximum value **/
private float maxValue;

/** Is Modifier finished **/
private boolean mFinished = false;

/** Elapsed time **/
private float mElapsedTime;

// ===========================================================
// Constructors
// ===========================================================

public SpanValueModificator( final IModificatorListener pListener )
{
    if ( pListener == null )
        throw new IllegalArgumentException( "SpanValueModificator IModificatorListener is null" );
    
    mListener = pListener;
}

// ===========================================================
// Getter & Setter
// ===========================================================

/**
 * Set's Duration, Max and Min Values<br><br>
 * Also changing Span Value<br><br>
 * Usually called at first setup
 * 
 * @param pDuration time for this operation
 * @param pMinValue value at start
 * @param pMaxValue value at finish
 * @return 
 */
public final SpanValueModificator set( final float pDuration,
         final float pMinValue, final float pMaxValue )
{
    mDuration = pDuration;
    minValue = pMinValue;
    maxValue = pMaxValue;
    mSpan = pMaxValue - pMinValue;
    return( this );
}

// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================

@Override
public final void onUpdate( final float timePerFrame )
{
    if ( mFinished )
        return;
    
    mElapsedTime += timePerFrame;
    
    if ( mElapsedTime >= mDuration )
    {
        mValue = maxValue;
        Stop( );
        return;
    }
    else
    {
        final float deltaTime = mElapsedTime / mDuration;
        mValue = minValue + mSpan * deltaTime;
        
        if ( mValue >= maxValue )
        {
            mValue = maxValue;
            Stop( );
            return;
        }
    }
    
    //Inform listeners about mValue
    mListener.onModifying( mValue, this );
}

@Override
public final void Start()
{
    mFinished = false;
    mValue = minValue;
    mElapsedTime = 0f;
    
    onStart( );
}

@Override
public final void Stop()
{
    mFinished = true;
    
    onFinish( );
}

@Override
protected final void onFinish( )
{
    mListener.onModificatorFinished( mValue, this );
}

@Override
protected final void onStart( )
{
    mListener.onModificatorStarted( this );
}

// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
// -------------------------------------------------------- \\

}
[/java]

1 Like