Let's take a look inside the new features of R49!
One thing that is bread-and-butter gotta have is cross-fading between textures. You have some object, and it has to appear with more than one different texture, and of course you want a nice "transition" when that changes, don't you?
So to start, we need a component that knows how to interpolate [0..1] over a given time interval, and do some other necessary bookkeeping. Let's paste that right in:
public class AnimateRatio extends GameObject implements TimerCallback, RequireResourceLoader, Effect, LoadedCallback, UnloadedCallback { final MixTextures mt; final String[] targets; final long dur; final Material ft; public AnimateRatio(String name, long dur, MixTextures mt, Material ft, String target) { super(name, true); if(mt == null) throw new IllegalArgumentException("mt"); if(ft == null) throw new IllegalArgumentException("ft"); this.dur = dur; this.mt = mt; this.ft = ft; this.targets = new String[] { name, target }; } @Override public void execute(long delta, long elapsed, boolean last, Locator arg3, Pipelines arg4) { final float ratio = Math.min(1f, (float)elapsed/(float)dur); mt.setRatio(ratio); if(last) { try { arg4.uninstall(name, targets); } catch (Exception e) { Log.e("AR", "uninstall", e); } } } @Override public boolean getRegisterOnInstall() { return true; } @Override public void setConfig(TimerConfig tc, int arg1) { tc.durationMS = dur; tc.continuous = true; tc.autoRepeat = false; } @Override public void load(ResourceLoader arg0, Services arg1) { mt.load(arg0, arg1); if(ft instanceof RequireResourceLoader) { ((RequireResourceLoader)ft).load(arg0, arg1); } } @Override public Shader getShader() { return mt.getShader(); } @Override public void setup() { mt.setup(); } @Override public void unloaded(GameObject arg0, Exception arg1, Locator arg2, Pipelines pps) { if (arg0 == this) { final GameObjectWithProperties go = arg2.locate(targets[1]); if (go != null) { go.set(Constants.Property.MATERIAL, ft); } } } @Override public void loaded(GameObject arg0, Exception arg1, Locator arg2, Pipelines pps) { } }
This is a typical GO in terms of callbacks implemented, but it does lots:
Consult the Javadoc for details on MixTextures; it does what its name says.
In the Bashing Game, the "field" pieces change "actions" based on a random "spawner" GO that doles out randomly-generated actions, e.g. "switch to score multiplier x5" which come in as Event Pipeline to these field GOs. When these GOs receive Box 2D Contact Events, they perform the corresponding action, e.g. "add N points to the score".
Actions eventually expire, and new actions are assigned as the game continues. Each action has a texture associated with it, and the field has already a default Material ("cpv" shader) attached.
Finally we get to AnimateRatio! As actions get "accepted" the field GO starts a transition from its default Material to a TextureMaterial corresponding to the action. At the end of the transition, the action's material get applied as the current Material. When the action expires, the transition is reversed, back to the field's original Material.
Here is an example from the field GO, how it starts the first transition:
void animateOn(Pipelines pps) { if(animating) return; // transition visual to this action if(mtoriginal != null) { mtswitchto = new TextureMaterial(sa.txname); final AnimateRatio ar = new AnimateRatio(pps.freshName("AnimateOn"), 2000L, new MixTextures("MixTextures", false, mtoriginal.name, mtswitchto.name), mtswitchto, name); try { pps.install(ar, new String[] { ar.name, name }); animating = true; } catch (Exception e) { animating = false; mtswitchto = null; } } }
And how it starts the second transition:
void animateOff(Pipelines pps) { if(animating) return; if(mtswitchto != null) { // transition visual back to normal if (mtoriginal != null) { final AnimateRatio ar = new AnimateRatio(pps.freshName("AnimateOff"), 2000L, new MixTextures("MixTextures", false, mtswitchto.name, mtoriginal.name), mtoriginal, name); try { pps.install(ar, new String[] { ar.name, name }); animating = true; mtswitchto = null; } catch (Exception e) { animating = false; mtswitchto = null; } } } }
qed.