I'm working on a simple game for android using openGL es 2.0. Game will be in 2D, something like old supermario, where player can move left-right/up-down but no depth.
Level will be larger than screen, so graphics will have to scroll. Here is where the problem comes. I don't know where/when to stop scrolling.
Example. Lets say that background is 100x100 sized square with texture. Lets say that on screen there is only 1/4 of the background visible at any time. When I then move screen to the right, I would like it to stop scrolling when right edge of background comes at the edge of the screen.
The best I can do now, is to stop scrolling when center of "view" is at the edge of background. But this isn't good, because 3/4 of the screen are than blank.
How can I calculate this "offset" from center of view to edge of screen?
Note: I don't want to use orthographic projection.
Here is code of renderer.
package com.huntedseas;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.Matrix;
import android.util.Log;
public class GameRenderer implements Renderer {
protected LevelGenerator generator;
protected SquareGL squareGL;
protected static float angleX;
protected static float angleY;
protected static float angleZ;
protected static float viewX = 0;
protected static float viewY = 0;
//private float viewZ = 0;
private float[] mProjectionMatrix = new float[16]; //Projekcijska matrika
private float[] mVMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig conunused) {
GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
GLES20.glDisable(GLES20.GL_CULL_FACE); //No culling of back faces \\ To nevem al je treba da je uklopljeno al ne
GLES20.glDisable(GLES20.GL_DEPTH_TEST); //No depth testing \\ --||--
GLES20.glEnable(GLES20.GL_BLEND); //Blending
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,GLES20.GL_ONE_MINUS_SRC_ALPHA); //Interpolated blending
generator = new LevelGenerator();
}
@Override
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
moveView();
Matrix.setLookAtM(mVMatrix, 0, viewY, viewX, -10, viewY, viewX, 0, 0.0f, 1.0f, 0.0f); //set view
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mVMatrix, 0); //calculate view transformation
generator.draw(mMVPMatrix);
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width/height;
float left =-ratio;
float right = ratio;
float bottom = -1.0f;
float top = 1.0f;
float near = 1.0f;
float far = 20.0f;
Log.d("ratio","ratio: "+left+" r: "+right+" w: "+width+" h: "+height);
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
long lastTime = System.currentTimeMillis();
public void moveView(){
if((System.currentTimeMillis()-lastTime) >= 33){
lastTime = System.currentTimeMillis();
Log.d("viewX","viewX: "+viewX + "viewY:"+viewY);
if( (viewX - angleX/10) < Level1.viewXP && (viewX - angleX/10) > Level1.viewXM) viewX -= angleX/10;
if( (viewY - angleY/10) < Level1.viewYP && (viewY - angleY/10) > Level1.viewYM) viewY -= angleY/10;
//if(Math.abs(viewX - angleX/10) < 10) viewX-=angleX/10;
//if(Math.abs(viewY - angleY/10) < 10) viewY-=angleY/10;
//if(Math.abs(viewZ - (angleZ-5)/10) < 10) viewZ+=(angleZ-5)/10;
}
}
}
I've solved this by modifying parameters for Matrix.frustumM so they represent FOV. Than when you know angle from middle to side, you can calculate offset with tangens function.
You can also use Matrix.perspectivM(), but it is only avaliable for api 14+.