package stu.tnt.gdx.graphics.graphics2d; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import stu.tnt.gdx.utils.Factory; import stu.tnt.gdx.utils.Pool; import com.badlogic.gdx.utils.Disposable; import com.badlogic.gdx.utils.LongMap; import com.badlogic.gdx.utils.LongMap.Values; import com.badlogic.gdx.utils.ObjectMap; /** NWorld.java * * Created on: Oct 7, 2012 Author: Trung */ public final class NWorld implements Disposable { private long address; // ============= Sprite mapping and pooling ============= final LongMap<NativeSpriteBackend> mSpriteMap = new LongMap<NativeSpriteBackend>(100); private final ObjectMap<Class<?>, Pool<?>> mSpritePoolMap = new ObjectMap<Class<?>, Pool<?>>(1); private final ObjectMap<Class<?>, Pool<?>> mSpriteAPoolMap = new ObjectMap<Class<?>, Pool<?>>(1); private CollideListener collideListener; // ============= Manager mapping ============= private final NManager mMainManager; final LongMap<NManager> mManagerMap = new LongMap<NManager>(3); // ============= SpriteDef manager ============= private final ObjectMap<String, NSpriteDef> mSpriteDefMap = new ObjectMap<String, NSpriteDef>(3); /*********************************************************** Constructors ***********************************************************/ public NWorld (int pool_Size_Of_NSprite, int pool_Size_Of_NSpriteA) { address = CreateWorld(); // create default sprite pool Pool<NSprite> sprite = new Pool<NSprite>(pool_Size_Of_NSprite, new Factory<NSprite>() { @Override public NSprite newObject () { return createNSprite(); } @Override public NSprite newObject (Object... objects) { return null; } }); mSpritePoolMap.put(NSprite.class, sprite); // create default spriteA pool Pool<NSpriteA> spriteA = new Pool<NSpriteA>(pool_Size_Of_NSpriteA, new Factory<NSpriteA>() { @Override public NSpriteA newObject () { return createNSpriteA(); } @Override public NSpriteA newObject (Object... objects) { return null; } }); mSpriteAPoolMap.put(NSpriteA.class, spriteA); // create default manager mMainManager = newManager(); mManagerMap.put(mMainManager.address, mMainManager); } // ============= WOrld method ============= @Override public void dispose () { Values<NManager> val = mManagerMap.values(); for (NManager m : val) { if (m != null) m.dispose(); } DisposeWorld(); } private final native long CreateWorld (); private final native void DisposeWorld (); public NManager getMainList () { return mMainManager; } public int getSpriteSize () { return mSpriteMap.size; } public int getSpriteDefSize () { return mSpriteDefMap.size; } /************************************************************ Sprite associate method ************************************************************/ // ===================================== // NSPrite vs NSpriteA pool manager public <T extends NSprite> Pool<T> makeNSpritePool (Class<T> type, Factory<T> factory, int maxSize) { final Pool<T> pool = new Pool<T>(maxSize, factory); mSpritePoolMap.put(type, pool); return pool; } public <T extends NSpriteA> Pool<T> makeNSpriteAPool (Class<T> type, Factory<T> factory, int maxSize) { final Pool<T> pool = new Pool<T>(maxSize, factory); mSpriteAPoolMap.put(type, pool); return pool; } // ===================================== // NSprite public NSprite newSprite () { NSprite sprite = (NSprite)mSpritePoolMap.get(NSprite.class).obtain(); sprite.isPooled = false; if (sprite.manager == null) mMainManager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public NSprite newSprite (NManager manager) { NSprite sprite = (NSprite)mSpritePoolMap.get(NSprite.class).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public NSprite newSprite (long managerAddress) { NManager manager = mManagerMap.get(managerAddress); if (manager == null) return null; NSprite sprite = (NSprite)mSpritePoolMap.get(NSprite.class).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } // =================================== // NSpriteA public NSpriteA newSpriteA () { NSpriteA sprite = (NSpriteA)mSpriteAPoolMap.get(NSpriteA.class).obtain(); sprite.isPooled = false; if (sprite.manager == null) mMainManager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public NSpriteA newSpriteA (NManager manager) { NSpriteA sprite = (NSpriteA)mSpriteAPoolMap.get(NSpriteA.class).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public NSpriteA newSpriteA (long managerAddress) { NManager manager = mManagerMap.get(managerAddress); if (manager == null) return null; NSpriteA sprite = (NSpriteA)mSpriteAPoolMap.get(NSpriteA.class).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } // =================================== // Sprite Customize public <T extends NSprite> T newSprite (Class<T> type) { T sprite = (T)mSpritePoolMap.get(type).obtain(); sprite.isPooled = false; if (sprite.manager == null) mMainManager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public <T extends NSprite> T newSprite (Class<T> type, NManager manager) { T sprite = (T)mSpritePoolMap.get(type).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public <T extends NSprite> T newSprite (Class<T> type, long managerAddress) { NManager manager = mManagerMap.get(managerAddress); if (manager == null) return null; T sprite = (T)mSpritePoolMap.get(type).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public <T extends NSpriteA> T newSpriteA (Class<T> type) { T sprite = (T)mSpriteAPoolMap.get(type).obtain(); sprite.isPooled = false; if (sprite.manager == null) mMainManager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public <T extends NSpriteA> T newSpriteA (Class<T> type, NManager manager) { T sprite = (T)mSpriteAPoolMap.get(type).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } public <T extends NSpriteA> T newSpriteA (Class<T> type, long managerAddress) { NManager manager = mManagerMap.get(managerAddress); if (manager == null) return null; T sprite = (T)mSpriteAPoolMap.get(type).obtain(); sprite.isPooled = false; manager.manage(sprite); mSpriteMap.put(sprite.address, sprite); return sprite; } // ==================================== // sprite generator private final NSprite createNSprite () { final NSprite sprite = new NSprite(CreateNSprite(), this); return sprite; } private final NSpriteA createNSpriteA () { final NSpriteA sprite = new NSpriteA(CreateNSprite(), this); return sprite; } // ============= Associate with sprite ============= /** Remove sprite from manage map , and reset it put it to the pool {@link NSprite} */ void poolSprite (NativeSpriteBackend sprite) { if (sprite instanceof NSprite) { final Pool pool = mSpritePoolMap.get(sprite.getClass()); if (!pool.freeNoReset(sprite)) sprite.dispose(); } else if (sprite instanceof NSpriteA) { final Pool pool = mSpriteAPoolMap.get(sprite.getClass()); if (!pool.freeNoReset(sprite)) sprite.dispose(); } mSpriteMap.remove(sprite.address); } /** delete given sprite from sprite map, and sprite pool */ void deleteSprite (NativeSpriteBackend sprite) { if (!sprite.isPooled()) mSpriteMap.remove(sprite.address); else { if (sprite instanceof NSprite) { final Pool pool = mSpritePoolMap.get(sprite.getClass()); pool.delete(sprite); } else if (sprite instanceof NSpriteA) { final Pool pool = mSpriteAPoolMap.get(sprite.getClass()); pool.delete(sprite); } } } // ============= Native method for sprite ============= /** Create a native reference of sprite * * @return native address of sprite */ public final native long CreateNSprite (); /************************************************************ Manager associate method ************************************************************/ public NManager newManager () { NManager manager = new NManager(CreateManager(), this); mManagerMap.put(manager.address, manager); return manager; } public NSpriter newSpriter () { NSpriter spriter = new NSpriter(CreateManager(), this); mManagerMap.put(spriter.address, spriter); return spriter; } public <T extends NSpriter> T newSpriter (Class<T> type) { T t = null; try { Constructor<T> cons = type.getDeclaredConstructor(long.class, NWorld.class); cons.setAccessible(true); t = cons.newInstance(CreateManager(), this); mManagerMap.put(t.address, t); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return t; } /** Direct delete manager 1. check manager = null 2. dispose sprite 3. clear manager list 4. dispose manager {@link NManager} */ public void delManager (long address) { if (address == mMainManager.address) return; mManagerMap.get(address).dispose(); } /** Direct delete manager 1. check manager = null 2. dispose sprite 3. clear manager list 4. dispose manager {@link NManager} */ public void delManager (NManager manager) { if (manager == mMainManager) return; manager.dispose(); } // ================================================= // native private final native long CreateManager (); final native void DisposeManager (long address); /************************************************************** NSpriteDef **************************************************************/ public NSpriteDef newSpriteDef (String name) { final NSpriteDef def = new NSpriteDef(name, CreateSpriteDef(), this); mSpriteDefMap.put(name, def); return def; } public NSpriteDef getSpriteDef (String name) { return mSpriteDefMap.get(name); } /** The sprite is dispose only when no sprite use it */ public void delSpriteDef (String name) { mSpriteDefMap.get(name).dispose(); } public void delSpriteDef (NSpriteDef def) { def.dispose(); } void deleteSpriteDef (String name) { DisposeSpriteDef(mSpriteDefMap.remove(name).address); } // ================================================= // native private final native long CreateSpriteDef (); private final native void DisposeSpriteDef (long spriteDefAddress); /************************************************************ Collision Processor ************************************************************/ public void setCollideListener (CollideListener listner) { this.collideListener = listner; } // ============= Collision with object ============= public void ProcessCollision (NManager manager1, NManager manager2, CollideListener listener) { this.collideListener = listener; processCollision(manager1.address, manager2.address); } public void ProcessCollision (NManager manager1, NManager manager2) { if (collideListener == null) return; processCollision(manager1.address, manager2.address); } public void ProcessCollision (NManager manager, CollideListener listener) { this.collideListener = listener; processCollision(manager.address); } public void ProcessCollision (NManager manager) { if (collideListener == null) return; processCollision(manager.address); } // ============= Collision with address ============= public void ProcessCollision (long manager1, long manager2, CollideListener listener) { this.collideListener = listener; processCollision(manager1, manager2); } public void ProcessCollision (long manager1, long manager2) { if (collideListener == null) return; processCollision(manager1, manager2); } public void ProcessCollision (long manager, CollideListener listener) { this.collideListener = listener; processCollision(manager); } public void ProcessCollision (long manager) { if (collideListener == null) return; processCollision(manager); } private void collide (long address1, long address2) { collideListener.Collided(mSpriteMap.get(address1), mSpriteMap.get(address2)); } // ============= Collision native configuration ============= public final native void StopCollisionProcessing (); public final native void ResumeCollisionProcessing (); public final native void CollisionConfig (int worldX, int worldY, int worldWidth, int worldHeight, int cols, int row); private final native void processCollision (long manager1, long manager2); private final native void processCollision (long manager); }