package org.andengine.examples.game.snake.entity;
import java.util.LinkedList;
import org.andengine.entity.Entity;
import org.andengine.examples.game.snake.adt.Direction;
import org.andengine.examples.game.snake.adt.SnakeSuicideException;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 17:11:44 - 09.07.2010
*/
public class Snake extends Entity {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
private final SnakeHead mHead;
private final LinkedList<SnakeTailPart> mTail = new LinkedList<SnakeTailPart>();
private Direction mDirection;
private boolean mGrow;
private final ITextureRegion mTailPartTextureRegion;
private Direction mLastMoveDirection;
// ===========================================================
// Constructors
// ===========================================================
public Snake(final Direction pInitialDirection, final int pCellX, final int pCellY, final TiledTextureRegion pHeadTextureRegion, final ITextureRegion pTailPartTextureRegion, final VertexBufferObjectManager pVertexBufferObjectManager) {
super(0, 0);
this.mTailPartTextureRegion = pTailPartTextureRegion;
this.mHead = new SnakeHead(pCellX, pCellY, pHeadTextureRegion, pVertexBufferObjectManager);
this.attachChild(this.mHead);
this.setDirection(pInitialDirection);
}
// ===========================================================
// Getter & Setter
// ===========================================================
public Direction getDirection() {
return this.mDirection;
}
public void setDirection(final Direction pDirection) {
if(this.mLastMoveDirection != Direction.opposite(pDirection)) {
this.mDirection = pDirection;
this.mHead.setRotation(pDirection);
}
}
public int getTailLength() {
return this.mTail.size();
}
public SnakeHead getHead() {
return this.mHead;
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public void grow() {
this.mGrow = true;
}
public int getNextX() {
return Direction.addToX(this.mDirection, this.mHead.getCellX());
}
public int getNextY() {
return Direction.addToY(this.mDirection, this.mHead.getCellY());
}
public void move() throws SnakeSuicideException {
this.mLastMoveDirection = this.mDirection;
if(this.mGrow) {
this.mGrow = false;
/* If the snake should grow,
* simply add a new part in the front of the tail,
* where the head currently is. */
final SnakeTailPart newTailPart = new SnakeTailPart(this.mHead, this.mTailPartTextureRegion, this.mHead.getVertexBufferObjectManager());
this.attachChild(newTailPart);
this.mTail.addFirst(newTailPart);
} else {
if(this.mTail.isEmpty() == false) {
/* First move the end of the tail to where the head currently is. */
final SnakeTailPart tailEnd = this.mTail.removeLast();
tailEnd.setCell(this.mHead);
this.mTail.addFirst(tailEnd);
}
}
/* The move the head into the direction of the snake. */
this.mHead.setCell(this.getNextX(), this.getNextY());
/* Check if head collides with tail. */
for(int i = this.mTail.size() - 1; i >= 0; i--) {
if(this.mHead.isInSameCell(this.mTail.get(i))) {
throw new SnakeSuicideException();
}
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}