AndeEngine Parallax / Sprite Depth?

Lo que bash hacer es crear un juego en el que una nave espacial explore una gran área de espacio. Estoy generando aleatoriamente la location de planetas, estaciones espaciales, etc. Quiero usar ParallaxBackground (en realidad tuve que encontrar una implementación personalizada que sea compatible con los valores de paralaje xey).

Cuando se genera un planeta, creo un sprite y agrego una nueva entidad de paralaje al background.

Mi problema es que cuando coloco el sprite, no se coloca correctamente (debido al cálculo de paralaje que asumo). A medida que el jugador navega más lejos del origen (0,0 en el espacio mundial), el desplazamiento desde la position en que se supone que el object aparece en el background y la position en la que realmente aparece se hace cada vez más grande.

Aquí está el código para el dibujo personalizado de ParallaxEntity2D:

public void onDraw(final GLState pGLState, final Camera pCamera, final float pParallaxValueX, final float pParallaxValueY) { pGLState.pushModelViewGLMatrix(); { final float cameraWidth = pCamera.getWidth(); final float cameraHeight = pCamera.getHeight(); final float shapeWidthScaled = this.mAreaShape.getWidthScaled(); final float shapeHeightScaled = this.mAreaShape.getHeightScaled(); //reposition float baseOffsetX = (pParallaxValueX * this.mParallaxFactor); if (this.mRepeatX) { baseOffsetX = baseOffsetX % shapeWidthScaled; while(baseOffsetX > 0) { baseOffsetX -= shapeWidthScaled; } } float baseOffsetY = (pParallaxValueY * this.mParallaxFactor); if (this.mRepeatY) { baseOffsetY = baseOffsetY % shapeHeightScaled; while(baseOffsetY > 0) { baseOffsetY -= shapeHeightScaled; } } //draw pGLState.translateModelViewGLMatrixf(baseOffsetX, baseOffsetY, 0); float currentMaxX = baseOffsetX; float currentMaxY = baseOffsetY; do { this.mAreaShape.onDraw(pGLState, pCamera); if (this.mRepeatY) { currentMaxY = baseOffsetY; do { pGLState.translateModelViewGLMatrixf(0, shapeHeightScaled, 0); currentMaxY += shapeHeightScaled; this.mAreaShape.onDraw(pGLState, pCamera); } while(currentMaxY < cameraHeight); pGLState.translateModelViewGLMatrixf(0, -currentMaxY + baseOffsetY, 0); } pGLState.translateModelViewGLMatrixf(shapeWidthScaled, 0, 0); currentMaxX += shapeWidthScaled; } while (this.mRepeatX && currentMaxX < cameraWidth); } pGLState.popModelViewGLMatrix(); } 

Esto está más allá de mi capacidad de comprensión en términos del cálculo requerido para averiguar en qué espacio de la pantalla debe colocarse el sprite para que se muestre correctamente en el background. Me he acercado al hackear algunas matemáticas simples, pero quiero que esto sea perfecto.

Creo que primero necesito entender lo que está haciendo exactamente el código onDraw anterior. Tal vez hay otro enfoque que funcionaría mejor para esta instancia? Exploré que podía usar el componente z en un sprite, pero no pude hacer que esto funcionara con GLES2 (el ejemplo de GLES1 está aquí ).

Creo que ya habrás estado pensando demasiado en la técnica de desplazamiento de paralaje. Todo lo que hace es hacer que los sprites que están "más lejos" se muevan más despacio que aquellos que están cerca y todas las variables que necesitamos es una velocidad y un desplazamiento. El código anterior parece hacer mucho más que eso, veamos el núcleo de la técnica de desplazamiento paralaje. Verás que lo que intentas hacer es bastante fácil:

Consideremos solo el eje X por ahora.

Digamos que queremos hacer un planeta que esté bastante lejos, le damos una velocidad paralaje de 0.9. Ahora di que nos gustaría que el planeta sea visible cuando la camera esté en X = 30. Entonces tenemos que pensar en algún desplazamiento para que esto suceda: 30 * 0.9 = 27, por lo que el desplazamiento debe ser 3.

Vamos a ver si esto funciona:

 X=25 gives us 25.5, the planet is still a bit to the right of the screen X=30 gives us 30, the planet is in the center of the screen X=35 gives us 34.5, the planet is a bit to the left of the screen 

Esto es lo que esperaríamos de un planeta bastante lejano. Ahora necesitamos encontrar un desplazamiento para que offset + velocidad * cameraPosition = X. Esto es fácil: es la diferencia entre la position deseada y la position dada por la fórmula sin un desplazamiento. Entonces el método general es:

 SetAtPosition(planet, float parallaxSpeed, vector2 position) { planet.OffsetX = position.X - (position.X * parallaxSpeed); planet.OffsetY = position.Y - (position.Y * parallaxSpeed); planet.parallaxSpeed = parallaxSpeed; } 

Y el método para dibujar es:

 Draw(planet, cameraPosition) { Sprite sprite; sprite.X = planet.OffsetX + planet.parallaxSpeed * cameraPosition.X; sprite.Y = planet.OffsetY + planet.parallaxSpeed * cameraPosition.Y; sprite.Draw(); } 

EDITAR: El código real que usé para lograr esto con el AndEngine:

 import org.andengine.engine.camera.Camera; import org.andengine.entity.sprite.Sprite; import org.andengine.opengl.texture.region.ITextureRegion; import org.andengine.opengl.util.GLState; import org.andengine.opengl.vbo.VertexBufferObjectManager; public class ParallaxSprite extends Sprite { private float parallaxSpeed; private float offsetX = 0; private float offsetY = 0; /** * Creates an instance of {@link ParallaxSprite} * @param pX * @param pY * @param parallaxSpeed * @param pTextureRegion * @param pVertexBufferObjectManager */ public ParallaxSprite(float pX, float pY, float parallaxSpeed, ITextureRegion pTextureRegion, VertexBufferObjectManager pVertexBufferObjectManager) { super(pX, pY, pTextureRegion, pVertexBufferObjectManager); this.parallaxSpeed = parallaxSpeed; this.offsetX = pX - (pX * parallaxSpeed); this.offsetY = pY - (pY * parallaxSpeed); } @Override protected void onManagedDraw(GLState pGLState, Camera pCamera) { pGLState.pushModelViewGLMatrix(); { final float x = this.offsetX + this.parallaxSpeed * pCamera.getXMin(); final float y = this.offsetY + this.parallaxSpeed * pCamera.getYMin(); pGLState.translateModelViewGLMatrixf(x, y, 0); /* Draw only self. */ this.preDraw(pGLState, pCamera); this.draw(pGLState, pCamera); this.postDraw(pGLState, pCamera); } pGLState.popModelViewGLMatrix(); } }