[Code submit] OffScreenHandler

  ... the case you feel the need for a new feature or want to submit one.

[Code submit] OffScreenHandler

Postby darklord » Tue Aug 24, 2010 4:36 pm

Hi,

I've created an OffScreenHandler which, as the name says, handles in the case of a iShape going off screen. I find it useful for cleaning up bullets who are outside the screen. Looking at all the examples I would think this is the correct way to handle entities that need to be removed when leaving the screen. If i'm wrong correct me please.

Anyways, the code:

OffScreenHandler.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. import org.anddev.andengine.engine.handler.IUpdateHandler;
  2. import org.anddev.andengine.entity.shape.IShape;
  3.  
  4. /**
  5.  * @author Jeffrey Pijnappels
  6.  * @since 16:00:00 - 24.08.2010
  7.  */
  8.  
  9. public class OffScreenHandler implements IUpdateHandler {
  10.         // ===========================================================
  11.         // Constants
  12.         // ===========================================================
  13.  
  14.         // ===========================================================
  15.         // Fields
  16.         // ===========================================================
  17.  
  18.         private final IOffScreenCallback mOffScreenCallback;
  19.         private final IShape mShape;
  20.         private final int mWidth;
  21.         private final int mHeight;
  22.  
  23.         // ===========================================================
  24.         // Constructors
  25.         // ===========================================================
  26.  
  27.         /**
  28.          * This handler is used to determine if an IShape-object is within
  29.          * the given boundaries. Usage of this handler could be bullets that
  30.          * are off screen and need to be "cleaned up".
  31.          */
  32.         public OffScreenHandler(final IOffScreenCallback pOffScreenCallback,
  33.                         final IShape pShape,
  34.                         final Integer pWidth,
  35.                         final Integer pHeight) throws IllegalArgumentException
  36.         {
  37.                 if (pOffScreenCallback == null) {
  38.                         throw new IllegalArgumentException( "pOffScreenCallback must not be null!");
  39.                 }
  40.                 if (pShape == null)
  41.                 {
  42.                         throw new IllegalArgumentException( "pShape must not be null!");
  43.                 }
  44.                 if(pWidth == null)
  45.                 {
  46.                         throw new IllegalArgumentException( "pWidth must not be null!");       
  47.                 }
  48.                 if(pHeight == null)
  49.                 {
  50.                         throw new IllegalArgumentException( "pHeight must not be null!");      
  51.                 }
  52.  
  53.                 this.mOffScreenCallback = pOffScreenCallback;
  54.                 this.mShape = pShape;
  55.                 this.mWidth = pWidth.intValue();
  56.                 this.mHeight = pHeight.intValue();
  57.         }
  58.  
  59.         // ===========================================================
  60.         // Getter & Setter
  61.         // ===========================================================
  62.  
  63.         // ===========================================================
  64.         // Methods for/from SuperClass/Interfaces
  65.         // ===========================================================
  66.  
  67.         @Override
  68.         public void onUpdate(final float pSecondsElapsed)
  69.         {
  70.                
  71.                 if(mShape.getX() > mWidth)
  72.                 {
  73.                         final boolean proceed = this.mOffScreenCallback.isOffScreen(mShape);
  74.                         if(!proceed)
  75.                         {
  76.                                 return;
  77.                         }
  78.                 }
  79.                 else if ((mShape.getX()+mShape.getWidth()) < 0)
  80.                 {
  81.                         final boolean proceed = this.mOffScreenCallback.isOffScreen(mShape);
  82.                         if(!proceed)
  83.                         {
  84.                                 return;
  85.                         }
  86.                 }
  87.                 else if(mShape.getY() > mHeight)
  88.                 {
  89.                         final boolean proceed = this.mOffScreenCallback.isOffScreen(mShape);
  90.                         if(!proceed)
  91.                         {
  92.                                 return;
  93.                         }
  94.                 }
  95.                 else if ((mShape.getY()+mShape.getHeight()) < 0)
  96.                 {
  97.                         final boolean proceed = this.mOffScreenCallback.isOffScreen(mShape);
  98.                         if(!proceed)
  99.                         {
  100.                                 return;
  101.                         }
  102.                 }
  103.         }
  104.  
  105.         @Override
  106.         public void reset() {
  107.  
  108.         }
  109.  
  110.         // ===========================================================
  111.         // Methods
  112.         // ===========================================================
  113.  
  114.         // ===========================================================
  115.         // Inner and Anonymous Classes
  116.         // ===========================================================
  117. }
  118.  
Parsed in 0.014 seconds, using GeSHi 1.0.8.4


IOffScreenCallback.java
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. import org.anddev.andengine.entity.shape.IShape;
  2.  
  3. /**
  4.  * @author Jeffrey Pijnappels
  5.  * @since 16:00:00 - 24.08.2010
  6.  */
  7.  
  8. public interface IOffScreenCallback
  9. {
  10.         // ===========================================================
  11.         // Final Fields
  12.         // ===========================================================
  13.  
  14.         // ===========================================================
  15.         // Methods
  16.         // ===========================================================
  17.  
  18.         /**
  19.          * @param pShape
  20.          * @return <code>true</code> to proceed, <code>false</code> to stop further OffScreen-checks.
  21.          */
  22.         public boolean isOffScreen(final IShape pShape);
  23. }
  24.  
Parsed in 0.010 seconds, using GeSHi 1.0.8.4



An example with this would look like this
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. bulletSprite.setPosition(0-(bulletSprite.getWidth()), 30);
  2. bulletSprite.setAccelerationX(10);
  3. scene.registerUpdateHandler(new OffScreenHandler(new IOffScreenCallback()
  4.       {                
  5.                                 @Override
  6.                                 public boolean isOffScreen(IShape pShape) {
  7.                                         // iShape is off screen, return false to continue checking, return true to stop.
  8.                                         //Add cleanup logic here such as:
  9.                                         scene.getTopLayer().removeEntity(pShape);
  10.                                         return true;
  11.                                 }
  12.         },bulletSprite, CAMERA_WIDTH, CAMERA_HEIGHT));
  13.  
Parsed in 0.010 seconds, using GeSHi 1.0.8.4
darklord
 
Posts: 121
Joined: Thu Aug 12, 2010 2:48 pm

Re: [Code submit] OffScreenHandler

Postby Nicolas Gramlich » Tue Aug 24, 2010 5:03 pm

Thanks for submitting. I'm sure this will be useful for some.

Just a few question and improvements:
  1. Why are you using Integer-objects. This is likely to introduce a lot of boxing/unboxing in most use-cases.
  2. I think you should add a mX and mY as your "OffScreen-Rectangle" is currently always based to 0/0.
  3. Try to cache things like "mShape.getX()" in local variables when the method is called more than once.
  4. Maybe use this method: ShapeCollisionChecker.checkAxisAlignedRectangleCollision(pLeftA, pTopA, pRightA, pBottomA, pLeftB, pTopB, pRightB, pBottomB)
  5. Maybe rename IOffScreenCallback to IOffScreenHandlerListener and its method from: isOffScreen to onOffScreen
  6. Maybe add a parameter to the IOffScreenHandlerListener of the type OffScreenHandler in the case somebody is using one IOffScreenHandlerListener for multiple OffScreenHandlers

Best Regards,
Nicolas
Nicolas Gramlich
Site Admin
 
Posts: 1734
Joined: Mon Jun 07, 2010 6:20 pm
Location: Schriesheim, Germany

Re: [Code submit] OffScreenHandler

Postby darklord » Tue Aug 24, 2010 6:07 pm

Nicolas Gramlich wrote:Thanks for submitting. I'm sure this will be useful for some.

Just a few question and improvements:
  1. Why are you using Integer-objects. This is likely to introduce a lot of boxing/unboxing in most use-cases.
  2. I think you should add a mX and mY as your "OffScreen-Rectangle" is currently always based to 0/0.
  3. Try to cache things like "mShape.getX()" in local variables when the method is called more than once.
  4. Maybe use this method: ShapeCollisionChecker.checkAxisAlignedRectangleCollision(pLeftA, pTopA, pRightA, pBottomA, pLeftB, pTopB, pRightB, pBottomB)
  5. Maybe rename IOffScreenCallback to IOffScreenHandlerListener and its method from: isOffScreen to onOffScreen
  6. Maybe add a parameter to the IOffScreenHandlerListener of the type OffScreenHandler in the case somebody is using one IOffScreenHandlerListener for multiple OffScreenHandlers

Best Regards,
Nicolas


Thanks for your comments. I've taken your advice on the first 5 points. I wasn't really sure how your last point would be implemented. Also I fail to see what benefit it would give to add multiple OffScreenHandlers to one IOffScreenHandlerListener. I'm curious to hear your view.

Edit: About your ShapeCollisionChecker.checkAxisAlignedRectangleCollision-method. It produces unexpected result, or perhaps I'm misunderstanding its use. Let me elaborate:

Rectangle A = Bullet
Rectancle B = Screen

Whenever A enters B with less than ~50% of its size, the method returns False.
Whenever A enters B with more than ~50% of its size, the method returns True.

What I expected is whenever A enters B with atleast one pixel, the method returns true. Else, it returns false.

Edit2: Also another question... For each bullet I create I make a "scene.registerUpdateHandler(handler);"-call but as soon as the bullet is off screen, I would guess that it is best to unregister the handler. What is the suggested approach for this?

Thanks!
darklord
 
Posts: 121
Joined: Thu Aug 12, 2010 2:48 pm

Re: [Code submit] OffScreenHandler

Postby Mimminito » Sat Aug 28, 2010 11:18 am

What I am currently doing is the following for my Update Handlers:

1. In my class I have a private Update Handler.
2. In my createParticleSystem() method, I first unregister the update handler, set it to null, and then create a new one for the next particle system.

This works pretty well for me, I think :). I would be interested to see what other people think.
---------------------------------------
Adam Goodchild
Your AndEngine Forum Moderator!
My Tutorials List
http://www.adam-goodchild.co.uk
---------------------------------------
Mimminito
 
Posts: 360
Joined: Wed Jul 21, 2010 3:08 pm
Location: Chelsmford, UK


Return to Features

Who is online

Users browsing this forum: No registered users and 4 guests