290 likes | 517 Views
Android Game Development. Android Game Engine – Advanced topics. Base project. Download our base project and open it in NetBeans cg.iit.bme.hu/ gamedev /KIC/11_AndroidDevelopment/11_05_Android_AnimationScripts_Base.zip Change the android sdk location path
E N D
Android Game Development Android Game Engine – Advanced topics
Base project • Downloadourbase project and open it inNetBeans • cg.iit.bme.hu/gamedev/KIC/11_AndroidDevelopment/11_05_Android_AnimationScripts_Base.zip • Changetheandroidsdklocationpath • Per-userproperties (local.properties) • sdk.dir=changepath here • Start an emulator • Build • Run
Animation • Change of a value in time • What? • Position • Color • orientation • … • How to store? • Can be multi dimensional • Array of floats • How to define the change of the value • Keyframe animation • Interpolation (step/linear)
AnimationTrackData - AnimationTrack • AnimationTrackData • Represents a keyframe animated value • Stores a float array for each keyframe • Keys are evenly placed in time • The arrays should have the same size (the dimension of the value) • AnimationTrack • Represents a keyframe animation • Works on an AnimationTrackData • Handles animation time • Updates current value (interpolation) • Playback speed can be given • Animation can loop
AnimationTrack example float keys[][] = {{-1,0},{1,0},{-1,0}}; AnimationTrackDataatd = new AnimationTrackData(2); atd.addKeyframe(keys[0]); atd.addKeyframe(keys[1]); atd.addKeyframe(keys[2]); AnimationTrackanimTrack = new AnimationTrack(atd); animTrack.setUseLinearInterpolation(true); animTrack. setLoop(true); //dt between two frames should be 0.5 sec. animTrack. setPlaybackSpeed(2.0); … animTrack.update(t,dt); float currentX = (animTrack. getCurrentValue())[0]; float currentY = (animTrack. getCurrentValue())[1]; mySceneNode.setPosition(currentX, currentY, 0);
AnimatedTexture • A texture that contains frames of animations • Can contain several animations (assigned with a unique name) • Texture coordinates will be transformed with the texture matrix to use only a subregion of the texture • Subregion is defined with a bounding box (min/max corners) • The bounding box is calculated in each rendered frame using an AnimationTrack • AnimationTrackData contains 4 floats: minX, minY, maxX, maxY
AnimatedTexture example AnimatedTexture at = new AnimatedTexture("myAnimTexture"); AnimationTrackDataatd = new AnimationTrackData(4); float keys0[] = {0.0f, 0.0f, 0.2f, 0.2f}; float keys1[] = {0.2f, 0.0f, 0.4f, 0.2f}; float keys2[] = {0.4f, 0.0f, 0.6f, 0.2f}; float keys3[] = {0.0f, 0.0f, 0.2f, 0.2f}; atd.addKeyframe(keys0); atd.addKeyframe(keys1); atd.addKeyframe(keys2); atd.addKeyframe(keys3); at.addAnimation("walk", atd, loopAnimation, animationPlaybackSpeed ); at.setFileName("animtex.png"); at.load(); ... at.lookLeft(true); //mirror subimage in the x direction at.playAnimation("walk"); at.update(t, dt);
MeshEntity public void update(float t, float dt) { Texture texture = this.material.getTexture(); if(texture != null && texture instanceofAnimatedTexture) ((AnimatedTexture) texture).update(t, dt); }
SpriteMap example • Also a texture that contains subimages defined with bounding boxes • Each subimage has its unique name (literal) • The texture coordinates are transformed with the texture matrix • Only one literal can be active at a time • Can draw the subimage to screen at a given position and with a given height (width is adjusted to bounding box ratio) • Can be used to store several small images in one texture (these images are related) • E.g.: • GUI strings • Images of numbers or letters • This class can be extended to implement a bitmap font drawing (StringDrawer)
SpriteMap example SpriteMapsm = new SpriteMap("MySMap"); sm.setFileName(“HUD.png"); sm.addLiteral("score", scoreMinX, scoreMinY, scoreMaxX, scoreMaxY); sm.addLiteral("life", lifeMinX, lifeMinY, lifeMaxX, lifeMaxY); sm.load(); ... sm.draw("score", x, y, height, alignLeft, alignBottom);
StringDrawer package gamedev.android.UEngine.Engine; import gamedev.android.UEngine.Engine.Resources.SpriteMap; public class StringDrawer { public static void drawString(SpriteMap map, String s, float x, float y, float h){ char[] chars = s.toCharArray(); float t = x; for(inti = 0; i < chars.length; i++) { t += map.draw(""+chars[i], t, y, h, true, true); } } }
Script loaders I. • Storematerial and texturedefinitionsinscripts • Easiertoedit • Nothardwiredincode • Human readable (no programmingskillsneeded) • Wewilluse XML filestostoreproperties • Placenewclassesinnewpackage: Engine.Scripts
Script loadersII. • ScriptLoader class • Base class • XML pull parser, state machine handling • TextureScriptLoader • loads a Texture, AnimatedTexture or SpriteMap • MaterialScriptLoader • Loads a Material • Usually refers to a texture name • KeyframeAnimationDataScriptLoader • Loads an AnimationTrackData • The data can be passed to an AnimationTrack or AnimatedTexture • MeshEntityScriptLoader • Loads a MeshEntity • Refers to a material name and a mesh name • Physics2DObjectScriptLoader • Loads a Physics2DObject • Box and circle shapes can be defined • Friction, density, restitution and type (static/dynamic/kinematic) can be given
Script loadersIII. • Game related script loaders are in PlatformGame package • GameObjectScriptLoader • Loads a game object • MeshEntity and Physics2DObject can be defined • Initial position and orientation can be defined • LevelScriptLoader • Loads a level • Level scripts list gameobjects
Resource managers with script loading public class TextureManager extends ResourceManager<Texture>{ private TextureScriptLoader loader = new TextureScriptLoader(); protected Texture loadImpl(String name){ this.loader.loadScript(name + ".texture.xml"); return this.loader.getTexture(); } } public class MaterialManager extends ResourceManager<Material>{ private MaterialScriptLoader loader = new MaterialScriptLoader(); protected Material loadImpl(String name){ this.loader.loadScript(name + ".material.xml"); return this.loader.getMaterial(); } }
Texture script examples <texture name="Brick"> <file filename = "brick.jpg"/> </texture> <texture name="g_Item"> <file filename = "g_item.png"/> </texture>
Material script examples <material name="Basic" lighting="false"> </material> <material name="Brick“ > <texture_unit texture = "Brick"/> </material> <material name="g_Item" lighting="false" blending="blend"> <texture_unit texture = "g_Item"/> </material>
MeshEntity script example <meshentity name = "Ground" meshname="UnitQuad" material="Basic"> </meshentity>
Physics2DObject script examples <physics2dobject> <aabox dim ="50 10"/> </physics2dobject> <physics2dobject density="2" friction="0.8" restitution="0.3" type="dynamic"> <aabox dim ="0.5 0.5" /> </physics2dobject>
GameObject script example <gameobject name="MyBox" position="0 4 0" rotation="0 0 0" scale="0.5 0.5 1" > <meshentity name = "MyBox" meshname="UnitQuad" material="Brick"> </meshentity> <physics2dobject density="2" friction="0.8" restitution="0.3" type="dynamic"> <aabox dim ="0.5 0.5" /> </physics2dobject> </gameobject>
AnimatedTexture script example <animtexture name="g_DarkMan"> <file filename = "g_darkman.png"/> <animation name="stand" loop="true" speed="5.0"> <key value="0 0 0.33 0.5"/> <key value="0 0 0.33 0.5"/> </animation> <animation name="walk" loop="true" speed="5.0"> <key value="0 0 0.33 0.5"/> <key value="0.33 0 0.66 0.5"/> <key value="0.66 0 1.0 0.5"/> <key value="0 0.5 0.33 1.0"/> <key value="0 0 0.33 0.5"/> </animation> <animation name="jump" loop="true" speed="5.0"> <key value="0 0 0.33 0.5"/> <key value="0.33 0 0.66 0.5"/> <key value="0.66 0 1.0 0.5"/> <key value="0 0.5 0.33 1.0"/> <key value="0 0 0.33 0.5"/> </animation> </animtexture>
Excersise • Change material and texture loading in LevelGenerator to use the automatic load from script functionality of material and texture managers !! (We have to write the scripts too)
Physics contact events I. • Create new class in Physics package: public interface PhysicsContactEventListener { public abstract void onContact(PhysicsObject other); public abstract PhysicsObjectgetObject(); }
Physics contact events II. • PhysicsEngine2D: public class PhysicsEngine2D { class ContactEvent{ public PhysicsContactEventListener listener; public PhysicsObjectotherObject; public ContactEvent(PhysicsContactEventListener l, PhysicsObject o){ listener = l; otherObject = o; } }; private LinkedList<ContactEvent> contactEvents = new LinkedList<ContactEvent>(); …
Physics contact events III. class MyContactListener implements ContactListener{ public void beginContact(Contact contact) { PhysicsObject o1 = (PhysicsObject) contact.m_fixtureA.m_body.m_userData; PhysicsObject o2 = (PhysicsObject) contact.m_fixtureB.m_body.m_userData; for(PhysicsContactEventListener l : contactEventListeners) { if(o1 == l.getObject()) contactEvents.add(new ContactEvent(l, o2)); if(o2 == l.getObject()) contactEvents.add(new ContactEvent(l, o1)); } } public void endContact(Contact contact) { } public void preSolve(Contact contact, Manifold manifold) { } public void postSolve(Contact contact, ContactImpulse impulse) { } }; private LinkedList<PhysicsContactEventListener> contactEventListeners = new LinkedList<PhysicsContactEventListener>();
Physics contact events IV. private PhysicsEngine2D(){ world.setContactListener(new MyContactListener()); } public Contact getContacts(){ return world.getContactList(); } public void update(float dt) { … for(ContactEvent e : contactEvents){ e.listener.onContact(e.otherObject); } contactEvents.clear(); } public void registerContactListener(PhysicsContactEventListener l){ contactEventListeners.add(l); }