Home > AndEngine, AndPingus, Android, Software Development > Pingus On Android – Early Collision Detection

Pingus On Android – Early Collision Detection

January 1st, 2011

In Part 2 of this series I had finally managed to get the primary scene ground objects into place. Since then, I’ve made some reasonable progress on the game. The following demo shows some of the initial collision detection working.

Splash Loading Screen

The first thing that was changed since I last wrote was the addition of the splash/loading screen.  This screen provided a means to see what the engine was doing during load of the scene, while also providing feedback that something was happening.

Unfortunately, running OpenGL inside of the emulator causes 100% CPU utilization of the host machine and slows down everything else.  My first attempt was to use AndEngine graphics for this simple screen, but the scene load time was substantially longer due to the CPU utilization.  Because of this, the current implementation is just a simple Android Activity/View combination.

Character Animation

The Pingus character is now animated and moving.  The AndEngine AnimatedSprite class does most of the work in handling the looping animation based on a texture map.  For example, the texture map for the “walker” character looks like:

Each sprite is then defined using code like:

	
	private BaseSprite getAnimatedSprite(SpriteDefinition spriteDefinition) {
		
		// Pull the base texture region.  This will be further broken down.
		String file = spriteDefinition.getFile();
		TextureRegion baseTextureRegion = getTextureRegion(file, SpriteModifier.ROTATE0);
		
		// The information that helps us define the region and sprite
		Point position = spriteDefinition.getPosition();
		Size size = spriteDefinition.getSize();
		int x_frames = spriteDefinition.getArray()[0];
		int y_frames = spriteDefinition.getArray()[1];
		
		// Create a new texture region for this particular sprite
		TiledTextureRegion spriteRegion = new TiledTextureRegion(
			baseTextureRegion.getTexture(), 
			position.x, 
			position.y, 
			x_frames * size.width, 
			y_frames * size.height,
			x_frames,
			y_frames);
		
		AnimatedSprite sprite = new AnimatedSprite(0, 0, size.width, size.height, spriteRegion);
		
		int speed = spriteDefinition.getSpeed();
		sprite.animate((speed == 0) ? 60 : speed);
		
		return sprite;
	}

Because the Pingus character images change based on the current state (falling, walking, digging, etc.), a delegate object is added into the AndEngine scene rather than the individual sprites. The delegate is simply an AndEngine Entity:

public class Pingus extends Entity {

This entity object wraps the underlying Sprite objects and delegates the drawing and updates:


	@Override
	protected void onManagedDraw(GL10 pGL, Camera pCamera) {
		if (sprite != null) {
			sprite.onDraw(pGL, pCamera);
		}
	}

	@Override
	protected void onManagedUpdate(float pSecondsElapsed) {
		if (sprite != null) {
			sprite.onUpdate(pSecondsElapsed);
			
			if (collectionCalculator.calculateStateAndDirection(stateAndDirection)) {
				updateSprite(stateAndDirection);
			}
		}
	}

“Chasing” The Pingus

While working through the logic to support the Pingus characters, including things like gravity and collision detection, it seemed useful to be able to automatically follow the Pingus character. Thankfully, this is easily achieved with AndEngine’s “chase” functionality. The individual sprites hold the character position information, so as the wrapped sprite is updated, the camera’s chase target must also be updated.

	private void updateChaseCamera(final Engine engine, IShape shape) {
		ZoomCamera camera = (ZoomCamera) engine.getCamera();
		camera.setChaseShape(shape);
	}

Collision Detection

The video shows the result of some very early, rudimentary collision detection. There are a number of issues with the implementation as it currently stands:

  • Transparent regions should not count as collisions.
  • Small steps up should not count as collisions.
  • Gravity needs to be introduced while walking so that steps downward work correctly.

The current implementation sits on top of AndEngine’s support for collision detection using the collidesWith method of the IShape interface. On each update of the Pingus, the collidesWith method is used to calculate the sprites that the Pingus has contacted:

	public List<SurfaceBasedObject> findCollisions(IShape iShape, Set<LevelObjectType> includedTypes) {
		List<SurfaceBasedObject> shapes = new ArrayList<SurfaceBasedObject>();
		
		for (SurfaceBasedObject obj : levelObjects) {
			BaseSprite levelObjectSprite = obj.getSprite();
			
			if (includedTypes.contains(obj.getLevelObjectType()) && 
				iShape.collidesWith(levelObjectSprite)) 
			{
				shapes.add(obj);
			}
		}
		
		return shapes;
	}

There is definitely significant work left for the collision detection, but the current implementation provides the basis. In looking around the web, this appears to be a fairly difficult problem to solve. In this case, it will be compounded by the combination of AndEngine and its basis in OpenGL ES.

  1. January 5th, 2011 at 10:37 | #1

    A mere 100% CPU utilization? I managed 5%-over-max spikes emulating for Android tablets.

    But seriously, thanks for linking this to AndEngine. You’ll help a lot of folks.

Comments are closed.