public class FirstActivity extends Activity {
    private static final String TAG = FirstActivity.class.getSimpleName(); /* define log tag*/
    private static Bundle Instance;

    public static Point size = new Point();
    public static double screenInches;
    public static double density;
    public static DisplayMetrics metrics;
    public static Context context;

    private FragmentManager fragmentManager;

    private static ImageView imageView1;

    private static int currentFragmentID = R.id.FirstFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        Instance = savedInstanceState;

        metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getSize(size);
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        screenInches = Math.sqrt(Math.pow((double)metrics.widthPixels/(double)metrics.densityDpi,2)+
                Math.pow((double)metrics.heightPixels/(double)metrics.densityDpi,2));
        density = metrics.densityDpi;

        fullscreen();

        setContentView(R.layout.first_activity);

        context = getApplicationContext();
        new Data(getApplicationContext());
        fragmentManager = getFragmentManager();

        if (Build.VERSION.SDK_INT >= 21){
            Settings.sound = false;
        }

        SwitchFragment(getCurrentFragment());

        imageView1 = (ImageView) findViewById(R.id.close);
        imageView1.setVisibility(View.VISIBLE);
        imageView1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                close();
                imageView1.setVisibility(View.VISIBLE);
            }
        });

        imageView1.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if(motionEvent.getAction() == MotionEvent.ACTION_DOWN)
                    imageView1.setVisibility(View.INVISIBLE);
                if(motionEvent.getAction() == MotionEvent.ACTION_UP)
                    imageView1.setVisibility(View.VISIBLE);
                return false;
            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
        imageView1.setVisibility(View.VISIBLE);
        fragmentManager.findFragmentById(currentFragmentID).onResume();
        fullscreen();
    }

    @Override
    protected void onPause() {
        super.onPause();
        imageView1.setVisibility(View.VISIBLE);
        fragmentManager.findFragmentById(currentFragmentID).onPause();
    }

    @Override
    public void onBackPressed() {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        finish();
    }

    public void close(){
        if(!fragmentManager.findFragmentById(R.id.FirstFragment).isHidden()){
            onBackPressed();
        }else {
            FirstFragment();
        }
        imageView1.setVisibility(View.VISIBLE);
    }

    public void SwitchFragment(int oldFrag, int newFrag){
        fragmentManager.beginTransaction()
                .hide(fragmentManager.findFragmentById(oldFrag))
                .show(fragmentManager.findFragmentById(newFrag))
                .commit();
        setCurrentFragment(newFrag);
    }

    public void SwitchFragment(int newFrag){
        if (newFrag == R.id.FirstFragment){
            SwitchFragment (R.id.ChooseFragment, newFrag);
        }else if(newFrag == R.id.ChooseFragment){
            SwitchFragment (R.id.FirstFragment, newFrag);
        }
    }

    public void ChooseFragment(){
        SwitchFragment(R.id.FirstFragment, R.id.ChooseFragment);
    }

    public void FirstFragment(){
        SwitchFragment(R.id.ChooseFragment, R.id.FirstFragment);
    }

    public void setCurrentFragment(int fragment){
        this.currentFragmentID = fragment;
    }

    public int getCurrentFragment(){
        return this.currentFragmentID;
    }

    public void fullscreen(){
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        if (Build.VERSION.SDK_INT >= 19){
            getWindow().getDecorView()
                    .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                            | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                            | View.SYSTEM_UI_FLAG_IMMERSIVE);
        }else {
            getWindow().getDecorView()
                    .setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
        }
    }
} public class Data {
    private Context context;
    public static SharedPreferences highScore;
    public static SharedPreferences death;
    public static SharedPreferences unlock;
    public static SharedPreferences config;

    public Data(Context context){
        this.context = context;
        highScore = context.getSharedPreferences(context.getString(R.string.shared_highscore), this.context.MODE_PRIVATE);
        death = context.getSharedPreferences(context.getString(R.string.shared_death), this.context.MODE_PRIVATE);
        unlock = context.getSharedPreferences(context.getString(R.string.shared_unlock), this.context.MODE_PRIVATE);
        config = context.getSharedPreferences(context.getString(R.string.shared_config), this.context.MODE_PRIVATE);
    }

    public static void setHighScore(int id, int score){
        if (score > getHighScore(id)){
            SharedPreferences.Editor editor = highScore.edit();
            editor.putInt(String.valueOf(id), score);
            editor.apply();
        }
    }

    public static void setDeath(int id){
        SharedPreferences.Editor editor = death.edit();
        editor.putInt(String.valueOf(id), getDeath(id) + 1);
        editor.apply();
    }

    public static void setUnlock(int id, boolean unlock){
        SharedPreferences.Editor editor = Data.unlock.edit();
        editor.putBoolean(String.valueOf(id), unlock);
        editor.apply();
    }

    public static void setConfig(String key, boolean value){
        SharedPreferences.Editor editor = Data.config.edit();
        editor.putBoolean(key, value);
        editor.apply();
    }

    public static int getHighScore(int id){
       return highScore.getInt(String.valueOf(id), 0);
    }

    public static int getDeath(int id){
        return death.getInt(String.valueOf(id), 0);
    }

    public static boolean getUnlock(int id){
        return unlock.getBoolean(String.valueOf(id), false);
    }

    public static boolean getConfig(String key){ return config.getBoolean(key, true); }
} public class Shape {
    private static final String TAG = Shape.class.getSimpleName();

    public Triangle triangle = new Triangle();
    public Rect rect = new Rect();
    public Circle circle = new Circle();
    public Square square = new Square();
    public CustomPolygon customPolygon = new CustomPolygon();

    public void draw(float[] mtrxProjectionAndView){
        if (triangle.exist) {
            triangle.draw(mtrxProjectionAndView);
        } else if (rect.exist) {
            rect.draw(mtrxProjectionAndView);
        } else if (circle.exist) {
            circle.draw(mtrxProjectionAndView);
        } else if (square.exist) {
            square.draw(mtrxProjectionAndView);
        } else if (customPolygon.exist) {
            customPolygon.draw(mtrxProjectionAndView);
        }
    }

    public float[] getVertices() {
        if (triangle.exist) {
            return triangle.getVertices();
        } else if (rect.exist) {
            return rect.getVertices();
        } else if (circle.exist) {
            return circle.getVertices();
        } else if (square.exist) {
            return square.getVertices();
        } else if (customPolygon.exist) {
            return customPolygon.getVertices();
        }else {
            return null;
        }
    }

    public short[] getIndices() {
        if (triangle.exist) {
            return triangle.indices;
        } else if (rect.exist) {
            return rect.indices;
        } else if (circle.exist) {
            return circle.indices;
        } else if (square.exist) {
            return square.indices;
        }else if (customPolygon.exist) {
            return customPolygon.indices;
        } else {
            return null;
        }
    }

    public float[] getColor() {
        if (triangle.exist) {
            return triangle.color;
        }  else if (rect.exist) {
            return rect.color;
        } else if (circle.exist) {
            return circle.color;
        } else if (square.exist) {
            return square.color;
        }else if (customPolygon.exist) {
            return customPolygon.color;
        } else {
            return null;
        }
    }

    public int drawingType() {
        if (triangle.exist) {
            return triangle.drawingType;
        }  else if (rect.exist) {
            return rect.drawingType;
        } else if (circle.exist) {
            return circle.drawingType;
        } else if (square.exist) {
            return square.drawingType;
        }else if (customPolygon.exist) {
            return customPolygon.drawingType;
        } else {
            return 0;
        }
    }

    public BufferHelper getBuffer() {
        if (triangle.exist) {
            return triangle.getBuffer();
        }  else if (rect.exist) {
            return rect.getBuffer();
        } else if (circle.exist) {
            return circle.getBuffer();
        } else if (square.exist) {
            return square.getBuffer();
        }else if (customPolygon.exist) {
            return customPolygon.getBuffer();
        } else {
            return null;
        }
    }


    public int getGLTex() {
        if (rect.exist) {
            return rect.getGLTEX();
        }else if (customPolygon.exist){
            return customPolygon.getGLTex();
        } if (circle.exist){
            return circle.getGLTex();
        } else {
            return 0;
        }
    }

    public float[] getUvs() {
        if (rect.exist) {
            return rect.getUvs();
        }else if (customPolygon.exist){
            return customPolygon.getUvs();
        } if (circle.exist){
            return circle.getUvs();
        }else {
            return null;
        }
    }

} public class GraphicHelper {

    // Program variables
    private final static String TAG = GraphicHelper.class.getSimpleName();
    public static int shaderProgram = -1;
    private static final int COORDS_PER_VERTEX = 3;
    private static int vertexShader;
    private static int fragmentShader;

    private static String vertexShaderString;
    private static String fragmentShaderString;
    //////////////////////////////////////////////////////
    private static int positionHandle;
    private static int colorHandle;
    private static int mvpMatrixHandle;
    private static int fragColor;
    private static int texCoordLoc;
    private static int samplerLoc;
    private static int colorOld;
    private static int colorNew;

    public static int loadShader(int type, String shaderCode) {
        // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
        // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
        int shader = GLES20.glCreateShader(type);
        // add the source code to the shader and compile it
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
        // return the shader
        return shader;
    }

    public static void createPrograms(String fileVs, String fileFs) {
        try {
            vertexShaderString = Tools.convertStreamToString(
                    GLRenderer.context.getAssets().open(fileVs));
            fragmentShaderString = Tools.convertStreamToString(
                    GLRenderer.context.getAssets().open(fileFs));
        } catch (Exception e) {
            e.printStackTrace();
        }


        // prepare shaders and OpenGL program SOLID
        vertexShader = loadShader(
                GLES20.GL_VERTEX_SHADER, vertexShaderString);
        fragmentShader = loadShader(
                GLES20.GL_FRAGMENT_SHADER, fragmentShaderString);

        shaderProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(shaderProgram, vertexShader);   // add the vertex shader to program
        GLES20.glAttachShader(shaderProgram, fragmentShader); // add the fragment shader to program
        GLES20.glLinkProgram(shaderProgram);                  // create OpenGL program executables

        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

        //Vertex Shader
        positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition");
        mvpMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix");
        texCoordLoc = GLES20.glGetAttribLocation(shaderProgram, "a_texCoord");
        //Fragment Shader
        samplerLoc = GLES20.glGetUniformLocation(shaderProgram, "s_texture");
        colorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor");
        fragColor = GLES20.glGetUniformLocation(shaderProgram, "FragColor");
        colorOld = GLES20.glGetUniformLocation(shaderProgram, "colorOld");
        colorNew = GLES20.glGetUniformLocation(shaderProgram, "colorNew");
    }

    public static void clean(){
        if (shaderProgram != -1 ){
            GLES20.glDeleteProgram(shaderProgram);
        }
        GLES20.glDisable(GLES20.GL_BLEND);
    }

    public static void drawSolid(float[] mvpMatrix, Shape shape, BufferHelper buffer){
        drawSolid(mvpMatrix, shape.getVertices(), shape.getIndices(), shape.getColor(), shape.drawingType(), buffer);
    }

    public static void drawSolid(float[] mvpMatrix, float[] vertices, short[] indices,
                                 float[] color, int drawingType, BufferHelper buffer){
        GLES20.glUseProgram(shaderProgram);
        drawCommon(mvpMatrix, buffer, 0);
        GLES20.glUniform4fv(colorHandle, 1, color, 0);
        GLES20.glDrawElements(drawingType, indices.length,
                GLES20.GL_UNSIGNED_SHORT, buffer.indicesBuffer);
        GLES20.glDisableVertexAttribArray(positionHandle);
    }

    public static void drawTexture(float[] mvpMatrix, Shape shape, BufferHelper buffer){
        drawTexture(mvpMatrix, shape.getVertices(), shape.getIndices(),
                shape.getUvs(), shape.getGLTex(), shape.drawingType(), buffer);
    }
    public static void drawTexture(float[] mvpMatrix, float[] vertices, short[] indices,
                                   float[] uvs, int GLTex, int drawingType, BufferHelper buffer){

        GLES20.glUseProgram(shaderProgram);
        drawCommon(mvpMatrix, buffer, 1);
        GLES20.glEnableVertexAttribArray(texCoordLoc);
        GLES20.glVertexAttribPointer(texCoordLoc, 2, GLES20.GL_FLOAT,
                false,
                0, buffer.uvsBuffer);
        GLES20.glUniform1i(samplerLoc, GLTex - GLES20.GL_TEXTURE0);
        GLES20.glDrawElements(drawingType, indices.length,
                GLES20.GL_UNSIGNED_SHORT, buffer.indicesBuffer);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(texCoordLoc);
    }

    public static void drawTexture(float[] mvpMatrix, Shape shape, BufferHelper buffer, float[] colorOld, float[] colorNew){
        drawTexture(mvpMatrix, shape.getVertices(), shape.getIndices(),
                shape.getUvs(), shape.getGLTex(),
                shape.drawingType(), buffer, colorOld, colorNew);
    }

    public static void drawTexture(float[] mvpMatrix, float[] vertices, short[] indices,
                                   float[] uvs, int GLTex, int drawingType, BufferHelper buffer, float[] colorOld, float[] colorNew){

        GLES20.glUseProgram(shaderProgram);
        GLES20.glUniform4fv(GraphicHelper.colorOld, 1, colorOld, 0);
        GLES20.glUniform4fv(GraphicHelper.colorNew, 1, colorNew, 0);
        drawCommon(mvpMatrix, buffer, 2);
        GLES20.glEnableVertexAttribArray(texCoordLoc);
        GLES20.glVertexAttribPointer(texCoordLoc, 2, GLES20.GL_FLOAT,
                false,
                0, buffer.uvsBuffer);
        GLES20.glUniform1i(samplerLoc, GLTex - GLES20.GL_TEXTURE0);
        GLES20.glDrawElements(drawingType, indices.length,
                GLES20.GL_UNSIGNED_SHORT, buffer.indicesBuffer);
        GLES20.glDisableVertexAttribArray(positionHandle);
        GLES20.glDisableVertexAttribArray(texCoordLoc);
    }

    public static void drawCommon(float[] mvpMatrix, BufferHelper buffer, int fragColor){
        GLES20.glUniform1i(GraphicHelper.fragColor, fragColor);
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(
                positionHandle, COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                0, buffer.verticesBuffer);
        GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
    }
} public class BitmapHelper {
    private final static String TAG = BitmapHelper.class.getSimpleName();
    private static ArrayList<BitmapObject> bitmaps = new ArrayList<>();

    private static BitmapObject checkBitmapObject(String filename){
        for (int i = 0; i < bitmaps.size(); i++){
            if (bitmaps.get(i).filename.equals(filename)){
                if (!bitmaps.get(i).bitmap.isRecycled()){
                    return bitmaps.get(i);
                }else {
                    recycle(bitmaps.get(i).bitmap);
                }
            }
        }
        return null;
    }

    public static Bitmap getAssetsBitmap(AssetManager assetManager, String filename, int imageMaxSize) {
        if (checkBitmapObject(filename) != null){
            return checkBitmapObject(filename).bitmap;
        }

        try {
            Bitmap bitmap;
            //Decode image size
            BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
            bitmapOptions.inJustDecodeBounds = true;
            InputStream fileStream = assetManager.open(filename);
            BitmapFactory.decodeStream(fileStream, null, bitmapOptions);
            fileStream.close();

            int scale = 1;
            if (bitmapOptions.outWidth > imageMaxSize) {
                scale = (int) Math.ceil((double)bitmapOptions.outWidth/(double)imageMaxSize);
            }

            //Decode with inSampleSize
            bitmapOptions = new BitmapFactory.Options();
            bitmapOptions.inSampleSize = scale;
            fileStream = assetManager.open(filename);
            bitmap = BitmapFactory.decodeStream(fileStream, null, bitmapOptions);
            fileStream.close();

            BitmapObject bitmapObject = new BitmapObject();
            bitmapObject.filename = filename;
            bitmapObject.bitmap = bitmap;
            bitmaps.add(bitmapObject);

            return bitmap;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Bitmap getAssetsBitmap(AssetManager assetManager, String filename) {
        if (checkBitmapObject(filename) != null){
            return checkBitmapObject(filename).bitmap;
        }

        try {
            InputStream fileStream = assetManager.open(filename);
            Bitmap bitmap = BitmapFactory.decodeStream(fileStream, null, null);
            fileStream.close();

            BitmapObject bitmapObject = new BitmapObject();
            bitmapObject.filename = filename;
            bitmapObject.bitmap = bitmap;
            bitmaps.add(bitmapObject);

            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Bitmap mirrorBitmap(Bitmap bitmap){
        Matrix matrix = new Matrix();
        matrix.preScale(-1.0f, 1.0f);
        Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
        return newBitmap;
    }


    public static Bitmap cropBitmap(Bitmap bitmap, float ratio){
        float bitmapRatio = (float)bitmap.getWidth()/(float)bitmap.getHeight();
        if (bitmapRatio != ratio){
            float finalHeight = bitmap.getWidth()/ratio;
            return cropBitmap(bitmap, bitmap.getWidth(), (int) finalHeight);
        }else {
            return bitmap;
        }
    }

    public static Bitmap cropBitmap(Bitmap bitmap, int width, int height){
        try {
            Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0,0, width, height);
            return newBitmap;
        }catch (Exception ex){
            ex.printStackTrace();
            return bitmap;
        }
    }

    public static Bitmap cropBitmap(Bitmap bitmap,  int x, int y, int width, int height){
        try {
            Bitmap newBitmap = Bitmap.createBitmap(bitmap, x, y, width, height);
            return newBitmap;
        }catch (Exception ex){
            Log.d(TAG, ex.getMessage());
            return bitmap;
        }
    }

    public static Bitmap scaleBitmap(Bitmap bitmap, int width, int height){
        Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
        return newBitmap;
    }

    public static Bitmap scaleBitmapWidth(Bitmap bitmap, int width){
        float ratio = bitmap.getWidth()/bitmap.getHeight();
        return scaleBitmap(bitmap, width, (width*bitmap.getHeight())/bitmap.getWidth());
    }

    public static Bitmap scaleBitmapHeight(Bitmap bitmap, int height){
        float ratio = bitmap.getWidth()/bitmap.getHeight();
        return scaleBitmap(bitmap, height, (height*bitmap.getWidth())/bitmap.getHeight());
    }

    public static Bitmap onlyColors(Bitmap bitmap, int[] colors) {
        if (bitmap == null) {
            return bitmap;
        }
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] pixels = new int[width * height];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        boolean change;
        for (int x = 0; x < pixels.length; ++x) {
            change = true;
            for (int color : colors) {
                if (pixels[x] == color) {
                    change = false;
                }
            }
            if (change) {
                pixels[x] = Color.TRANSPARENT;
            }
        }
        Bitmap newBitmap = Bitmap.createBitmap(width, height, bitmap.getConfig());
        newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return newBitmap;
    }

    public static Bitmap changeColor(Bitmap bitmap, int oldColor, int newColor) {
        if (bitmap == null) {
            return bitmap;
        }

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] pixels = new int[width * height];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int x = 0; x < pixels.length; ++x) {
            pixels[x] = (pixels[x] == oldColor) ? newColor : pixels[x];
        }
        Bitmap newBitmap = Bitmap.createBitmap(width, height, bitmap.getConfig());
        newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return newBitmap;
    }

    public static void recycle(Bitmap bitmap){
        for (int i = 0; i < bitmaps.size(); i++){
            if (bitmaps.get(i).bitmap.getGenerationId() == bitmap.getGenerationId()){
                bitmaps.get(i).bitmap.recycle();
                bitmaps.remove(i);
            }
        }
    }

    public static void recycle(){
        for (int i = 0; i < bitmaps.size(); i++){
            recycle(bitmaps.get(i).bitmap);
        }
    }
} public class GLRenderer implements Renderer {

    private static final String TAG = GLRenderer.class.getSimpleName();

    private final float[] mtrxProjection = new float[16];
    private final float[] mtrxView = new float[16];
    public final float[] mtrxProjectionAndView = new float[16];

    public int screenWidth;
    public int screenHeight;
    public float screenRatio;

    public static Context context;
    public GLSurfaceView glSurfaceView;
    public long lastTime;
    public long deltaTime;
    public long upTime = 0;
    private long eventTime = 51;

    long now;
    long FPSLimit = Tools.fps(60);
    public GameWorld gameWorld;


    public boolean Drawing = false;

    public GLRenderer(Context context, GLSurfaceView glSurfaceView) {
        this.context = context;
        this.glSurfaceView = glSurfaceView;
        this.lastTime = System.currentTimeMillis();
    }


    public void onPause() {
        Drawing = false;
        Tools.sleep(200);
        LoadTexture.clean();
        GraphicHelper.clean();
        System.gc();
    }

    public void onResume() {
        Drawing = true;
        lastTime = System.currentTimeMillis();
    }


    public void Return() {
        onPause();
        Intent i = new Intent(context, FirstActivity.class);
        context.startActivity(i);
    }

    public void processTouchEvent(MotionEvent event) {
        gameWorld.touchEvent(event);
    }

    @Override
    public void onDrawFrame(GL10 unused) {
        now = System.currentTimeMillis();
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        if (Drawing) {
            try {
                gameWorld.drawmove(mtrxProjectionAndView);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            //gameWorld.drawmove(mtrxProjectionAndView);
        }
        deltaTime = System.currentTimeMillis() - now;
        Tools.sleep(FPSLimit - (deltaTime));
        deltaTime = System.currentTimeMillis() - now;
        upTime += deltaTime;
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        screenWidth = width;
        screenHeight = height;
        screenRatio = (float) width / (float) height;

        GLES20.glViewport(0, 0, screenWidth, screenHeight);

        for (int i = 0; i < 16; i++) {
            mtrxProjection[i] = 0.0f;
            mtrxView[i] = 0.0f;
            mtrxProjectionAndView[i] = 0.0f;
        }

        Matrix.orthoM(mtrxProjection, 0, 0f, screenWidth, 0.0f, screenHeight, 0, 50);
        Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);

        GraphicHelper.createPrograms(SettingsGraphic.fileVs, SettingsGraphic.fileFs);
        gameWorld = new GameWorld(this);
        Drawing = true;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0.0f,0.0f,0.0f, 0.0f);
    }

    public void SetMaxFPS(long Frame) {
        try {
            FPSLimit = 1000 / Frame;
        } catch (Exception ex) {
            FPSLimit = 1000;
        }
    }

    public void touchSimpleTap(MotionEvent event) {
        MotionEvent CustomEvent = MotionEvent.obtain(System.currentTimeMillis(), System.currentTimeMillis(),
                MotionEvent.ACTION_DOWN, event.getX(), (glSurfaceView.getHeight() - event.getY()), 0);
        try {
            if ((System.currentTimeMillis() - eventTime) > 50) {
                processTouchEvent(CustomEvent);
            }
        } catch (Exception e) {
            Log.d(TAG, e.getMessage());
        } finally {
            eventTime = System.currentTimeMillis();
        }
        if ((System.currentTimeMillis() - eventTime) > 50) {
            processTouchEvent(CustomEvent);
        }
        eventTime = System.currentTimeMillis();
    }

    public void touchFollow(MotionEvent event) {
        MotionEvent CustomEvent = MotionEvent.obtain(System.currentTimeMillis(), System.currentTimeMillis(),
                MotionEvent.ACTION_DOWN, event.getX(), (glSurfaceView.getHeight() - event.getY()), 0);
        try {
            processTouchEvent(CustomEvent);
        } catch (Exception e) {
            Log.d(TAG, e.getMessage());
        }
    }

    public static void checkGlError(String glOperation) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            throw new RuntimeException(glOperation + ": glError " + error);
        }
    }
} public interface GameObject {
    public void draw(float[] mtrxProjectionAndView);
    public void draw2(float[] mtrxProjectionAndView);
    public void init();
    public void create();
    public void reset();
    public void gameOver();
    public void touchEvent(MotionEvent event);
    public void move();
} public class LoadTexture {
    private static final String TAG = LoadTexture.class.getSimpleName();
    public static int numberTexture =0;
    private Texture texture = null;
    private float[] uvs;
    private int GLTex;
    private int textureWidth;
    private int textureHeight;
    public Bitmap bitmapTexture = null;
    public int[] textureNames = new int[1];
    boolean replace = false;
    private GLRenderer glRenderer;

    public LoadTexture(GLRenderer glRenderer){
        this.glRenderer = glRenderer;
        numberTexture +=1;
        GLTex = GLES20.GL_TEXTURE0+ numberTexture;

    }

    public Texture texture(){
        return texture;
    }

    public void createTexture(Bitmap bitmap, float[] uvCoord){
        bitmapTexture = bitmap;
        textureHeight = bitmap.getHeight();
        textureWidth = bitmap.getWidth();

        // create our UV coordinates.
        uvs = uvCoord;

        texture = new Texture(uvs, GLTex, textureWidth, textureHeight);

        // Generate Textures, if more needed, alter these numbers.
        if (!replace){
            GLES20.glGenTextures(1, textureNames, 0);
        }
        //Log.d(TAG, String.valueOf(textureNames[0]) + ";" + numberTexture + ";" +  bitmap.getHeight() + ";" + bitmap.getWidth());
        // Bind texture to texturename
        GLES20.glActiveTexture(GLTex);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureNames[0]);
        // Set filtering
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
                GLES20.GL_NEAREST);
        // Set wrapping mode
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                GLES20.GL_CLAMP_TO_EDGE);
        // Load the bitmap into the bound texture.
        if (replace){
            GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0 ,0 ,bitmap);
            //Log.d(TAG, "texSubImage2D");
        }else {
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
            //Log.d(TAG, "texImage2D");
        }
        replace = true;
        
    }

    public void png(AssetManager assetManager, float[] uvCoord, String filename) {
        createTexture(BitmapHelper.getAssetsBitmap(assetManager, filename), uvCoord);
    }

    public void png(AssetManager assetManager, String filename) {
            createTexture(BitmapHelper.getAssetsBitmap(assetManager, filename), new float[]{
                    0.0f, 1.0f,
                    0.0f, 0.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f});
    }

    public void bitmap(float[] uvCoord, Bitmap bitmap) {
        createTexture(bitmap, uvCoord);
    }

    public void bitmap(Bitmap bitmap) {
        createTexture(bitmap, new float[]{
                0.0f, 1.0f,
                0.0f, 0.0f,
                1.0f, 0.0f,
                1.0f, 1.0f});
    }

    public void recycle(){
        try {
            BitmapHelper.recycle(bitmapTexture);
        }catch (Exception ex){
            Log.d(TAG, ex.getMessage());
        }
    }

    public static void clean(){
        /*
        if (numberTexture != 0){
            int[] textureIds = new int[numberTexture];
            int i =0;
            while (i == numberTexture) {
                textureIds[i] = i;
                i++;
            }
            GLES20.glDeleteTextures(numberTexture, textureIds, 0);
         }*/
        numberTexture = 0;
    }
} public class Message {
    private static final String TAG = Message.class.getSimpleName();

    //--Constants--//
    public final static int CHAR_START = 32;           // First Character (ASCII Code)
    public final static int CHAR_END = 126;            // Last Character (ASCII Code)
    public final static int CHAR_CNT = ( ( ( CHAR_END - CHAR_START ) + 1 ) + 1 );  // Character Count (Including Character to use for Unknown)

    public final static int CHAR_NONE = 32;            // Character to Use for Unknown (ASCII Code)
    public final static int CHAR_UNKNOWN = ( CHAR_CNT - 1 );  // Index of the Unknown Character

    public final static int FONT_SIZE_MIN = 6;         // Minumum font Size (Pixels)
    public final static int FONT_SIZE_MAX = 180;       // Maximum font Size (Pixels)


    //--Members--//
    AssetManager assets;                               // Asset Manager
    GLRenderer glRenderer;
    int fontPadX, fontPadY;                            // font Padding (Pixels; On Each Side, ie. Doubled on Both x+y Axis)
    float fontHeight;                                  // font getHeight (Actual; Pixels)
    float fontAscent;                                  // font Ascent (Above Baseline; Pixels)
    float fontDescent;                                 // font Descent (Below Baseline; Pixels)
    LoadTexture fontTexture;
    int textureSize;                                   // texture Size for font (square) [NOTE: Public for Testing Purposes Only!]
    float charWidthMax;                                // Character getWidth (Maximum; Pixels)
    float charHeight;                                  // Character getHeight (Maximum; Pixels)
    final float[] charWidths;                          // getWidth of Each Character (Actual; Pixels)
    TextureRegion[] charRgn;                           // Region of Each Character (texture Coordinates)
    public int cellWidth, cellHeight;                         // Character Cell getWidth/getHeight
    int rowCnt, colCnt;                                // Number of Rows/columns
    float scaleX, scaleY;                              // font Scale (x,y Axis)
    float spaceX;                                      // Additional (x,y Axis) Spacing (Unscaled)

    int color;
    int size, scalesize;
    final int limitsize = 156;


    //--Drawing--//
    String text;
    Shape[] Letters;
    float[] mvpMatrix;
    float x;
    float y;

    //--Constructor--//
    // D: save program + asset manager, create arrays, and initialize the members
    public Message(GLRenderer glRenderer, AssetManager assets, String file, int size, int padX, int padY, int color) {
        this.glRenderer = glRenderer;
        this.assets = assets;                           // Save the Asset Manager Instance
        this.fontTexture = new LoadTexture(this.glRenderer);
        charWidths = new float[CHAR_CNT];               // create the Array of Character Widths
        charRgn = new TextureRegion[CHAR_CNT];          // create the Array of Character Regions

        // initialize remaining members
        fontPadX = 0;
        fontPadY = 0;

        fontHeight = 0.0f;
        fontAscent = 0.0f;
        fontDescent = 0.0f;

        textureSize = 0;

        charWidthMax = 0;
        charHeight = 0;

        cellWidth = 0;
        cellHeight = 0;
        rowCnt = 0;
        colCnt = 0;

        scaleX = 1.0f;                                  // Default Scale = 1 (Unscaled)
        scaleY = 1.0f;                                  // Default Scale = 1 (Unscaled)
        spaceX = 0.0f;
        this.color = color;
        this.size = (size >= this.limitsize)?this.limitsize:size ;
        load(file, this.size, padX, padY, color);
    }

    //--Load font--//
    // description
    //    this will load the specified font file, create a texture for the defined
    //    character range, and setup all required values used to render with it.
    // arguments:
    //    file - Filename of the font (.ttf, .otf) to use. In 'Assets' folder.
    //    size - Requested pixel size of font (height)
    //    padX, padY - Extra padding per character (x+y Axis); to prevent overlapping characters.
    private boolean load(String file, int size, int padX, int padY, int color) {
        // setup requested values
        fontPadX = padX;                                // Set Requested x Axis Padding
        fontPadY = padY;                                // Set Requested y Axis Padding

        // load the font and setup paint instance for drawing
        Typeface tf = Typeface.createFromAsset( assets, file );  // create the Typeface from font File
        Paint paint = new Paint();                      // create Android Paint Instance
        paint.setAntiAlias( true );                     // Enable Anti Alias
        paint.setTextSize( size );                      // Set Text Size
        paint.setColor( color);                   // Set ARGB (White, Opaque)
        paint.setTypeface( tf );                        // Set Typeface

        // get font metrics
        Paint.FontMetrics fm = paint.getFontMetrics();  // Get font Metrics
        fontHeight = (float)Math.ceil( Math.abs( fm.bottom ) + Math.abs( fm.top ) );  // Calculate font getHeight
        fontAscent = (float)Math.ceil( Math.abs( fm.ascent ) );  // Save font Ascent
        fontDescent = (float)Math.ceil( Math.abs( fm.descent ) );  // Save font Descent

        // determine the width of each character (including unknown character)
        // also determine the maximum character width
        char[] s = new char[2];                         // create Character Array
        charWidthMax = charHeight = 0;                  // reset Character getWidth/getHeight Maximums
        float[] w = new float[2];                       // Working getWidth Value
        int cnt = 0;                                    // Array Counter
        for ( char c = CHAR_START; c <= CHAR_END; c++ )  {  // FOR Each Character
            s[0] = c;                                    // Set Character
            paint.getTextWidths( s, 0, 1, w );           // Get Character Bounds
            charWidths[cnt] = w[0];                      // Get getWidth
            if ( charWidths[cnt] > charWidthMax )        // IF getWidth Larger Than Max getWidth
                charWidthMax = charWidths[cnt];           // Save New Max getWidth
            cnt++;                                       // Advance Array Counter
        }
        s[0] = CHAR_NONE;                               // Set Unknown Character
        paint.getTextWidths( s, 0, 1, w );              // Get Character Bounds
        charWidths[cnt] = w[0];                         // Get getWidth
        if ( charWidths[cnt] > charWidthMax )           // IF getWidth Larger Than Max getWidth
            charWidthMax = charWidths[cnt];              // Save New Max getWidth
        cnt++;                                          // Advance Array Counter

        // set character height to font height
        charHeight = fontHeight;                        // Set Character getHeight

        // find the maximum size, validate, and setup cell sizes
        cellWidth = (int)charWidthMax + ( 2 * fontPadX );  // Set Cell getWidth
        cellHeight = (int)charHeight + ( 2 * fontPadY );  // Set Cell getHeight
        int maxSize = cellWidth > cellHeight ? cellWidth : cellHeight;  // Save Max Size (getWidth/getHeight)
        if ( maxSize < FONT_SIZE_MIN || maxSize > FONT_SIZE_MAX )  // IF Maximum Size Outside Valid Bounds
            return false;                                // Return Error

        // set texture size based on max font size (width or height)
        // NOTE: these values are fixed, based on the defined characters. when
        // changing start/end characters (CHAR_START/CHAR_END) this will need adjustment too!
        if ( maxSize <= 24 )                            // IF Max Size is 18 or Less
            textureSize = 256;                           // Set 256 texture Size
        else if ( maxSize <= 40 )                       // ELSE IF Max Size is 40 or Less
            textureSize = 512;                           // Set 512 texture Size
        else if ( maxSize <= 80 )                       // ELSE IF Max Size is 80 or Less
            textureSize = 1024;                          // Set 1024 texture Size
        else                                            // ELSE IF Max Size is Larger Than 80 (and Less than FONT_SIZE_MAX)
            textureSize = 2048;                          // Set 2048 texture Size

        // create an empty bitmap (alpha only)
        Bitmap bitmap = Bitmap.createBitmap( textureSize, textureSize, Bitmap.Config.ARGB_8888 );  // create Bitmap
        bitmap.eraseColor( 0x00000000 );                // Set Transparent background (ARGB)
        Canvas canvas = new Canvas( bitmap );           // create Canvas for Rendering to Bitmap


        // calculate rows/columns
        // NOTE: while not required for anything, these may be useful to have :)
        colCnt = textureSize / cellWidth;               // Calculate Number of columns
        rowCnt = (int)Math.ceil( (float)CHAR_CNT / (float)colCnt );  // Calculate Number of Rows

        // render each of the characters to the canvas (ie. build the font map)
        float x = fontPadX;                             // Set Start Position (x)
        float y = ( cellHeight - 1 ) - fontDescent - fontPadY;  // Set Start Position (y)
        for ( char c = CHAR_START; c <= CHAR_END; c++ )  {  // FOR Each Character
            s[0] = c;                                    // Set Character to draw
            canvas.drawText( s, 0, 1, x, y, paint );     // draw Character
            x += cellWidth;                              // move to Next Character
            if ( ( x + cellWidth - fontPadX ) > textureSize )  {  // IF end of Line Reached
                x = fontPadX;                             // Set x for New Row
                y += cellHeight;                          // move Down a Row
            }
        }
        s[0] = CHAR_NONE;                               // Set Character to Use for NONE
        canvas.drawText( s, 0, 1, x, y, paint );        // draw Character

        // save the bitmap in a texture
        fontTexture.bitmap(bitmap);
        fontTexture.recycle();

        // setup the array of character texture regions
        x = 0;                                          // Initialize x
        y = 0;                                          // Initialize y
        for ( int c = 0; c < CHAR_CNT; c++ )  {         // FOR Each Character (On texture)
            charRgn[c] = new TextureRegion(fontTexture, x, y, cellWidth-1, cellHeight-1 );  // create Region for Character
            x += cellWidth;                              // move to Next Char (Cell)
            if ( x + cellWidth > textureSize )  {
                x = 0;                                    // reset x Position to Start
                y += cellHeight;                          // move to Next Row (Cell)
            }
        }

        return true;                                    // Return Success
    }

    public void draw(float[] mvpMatrix, String text, float x, float y, int scalesize)  {
        SpriteBatch.begin();

        if ((this.mvpMatrix == mvpMatrix
                && this.text.equals(text)
                && this.x == x
                && this.y == y
                && this.scalesize == scalesize)
                && Letters != null){
            SpriteBatch.addShape(mvpMatrix, Letters);
            SpriteBatch.end();
            return;
        }

        this.mvpMatrix = mvpMatrix;
        this.text = text;
        this.x = x;
        this.y = y;
        this.scalesize = scalesize;

        this.scaleX = (float)((cellHeight*scalesize)/size) / cellHeight;
        this.scaleY = (float)((cellWidth*scalesize)/size) / cellWidth;

        //Log.d(TAG, cellHeight + ";" + cellWidth);

        float chrHeight = cellHeight * scaleY;          // Calculate Scaled Character getHeight
        float chrWidth = cellWidth * scaleX;            // Calculate Scaled Character getWidth

        //Log.d(TAG, chrHeight + ";" + chrWidth);

        float letterX = x;
        float letterY = y;
        Letters = new Shape[text.length()];
        for (int i = 0; i < text.length(); i++)  {              // FOR Each Character in String
            int c = (int)text.charAt(i) - CHAR_START;  // Calculate Character Index (Offset by First Char in font)
            if (c < 0 || c >= CHAR_CNT)                // IF Character Not In font
                c = CHAR_UNKNOWN;                         // Set to Unknown Character Index
            Letters[i] = new Shape();
            Letters[i].rect.create(letterX + chrWidth / 4.5f, letterY, chrWidth, chrHeight, charRgn[c].texture());
            SpriteBatch.addShape(mvpMatrix, Letters[i]);
            letterX += (charWidths[c] + spaceX ) * scaleX;    // Advance x Position by Scaled Character getWidth
        }
        SpriteBatch.end();
    }

    public void draw(float[] mvpMatrix, String text, float x, float y)  {
        SpriteBatch.begin();

        if ((this.mvpMatrix == mvpMatrix
                && this.text.equals(text)
                && this.x == x
                && this.y == y)
                && Letters != null){
            SpriteBatch.addShape(mvpMatrix, Letters);
            SpriteBatch.end();
            return;
        }

        this.mvpMatrix = mvpMatrix;
        this.text = text;
        this.x = x;
        this.y = y;
        this.scaleX = 1.0f;
        this.scaleY = 1.0f;

        float chrHeight = (cellHeight * scaleY);          // Calculate Scaled Character getHeight
        float chrWidth = (cellWidth * scaleX);            // Calculate Scaled Character getWidth

        float letterX = x;
        float letterY = y;
        Letters = new Shape[text.length()];
        for (int i = 0; i < text.length(); i++)  {              // FOR Each Character in String
            int c = (int)text.charAt(i) - CHAR_START;  // Calculate Character Index (Offset by First Char in font)
            if (c < 0 || c >= CHAR_CNT)                // IF Character Not In font
                c = CHAR_UNKNOWN;                         // Set to Unknown Character Index
            Letters[i] = new Shape();
            Letters[i].rect.create(letterX + chrWidth / 4.5f, letterY, chrWidth, chrHeight, charRgn[c].texture());
            SpriteBatch.addShape(mvpMatrix, Letters[i]);
            letterX += (charWidths[c] + spaceX ) * scaleX;    // Advance x Position by Scaled Character getWidth
        }
        SpriteBatch.end();
    }


} public class Tools {
    private static String TAG = Tools.class.getSimpleName();
    private static Random rand = new Random();
    private static double degrees;


    public static float getAngle(float p1X, float p1Y, float p2X, float p2Y) {
        degrees = Math.toDegrees((Math.atan2(p1X - p2X, p1Y - p2Y)));
        degrees = ((degrees < 0) ? -(degrees - 180) : degrees) + 90;
        return (float) ((degrees > 360) ? degrees -= 360 : degrees);
    }

    public static float getDistance(float p1X, float p1Y, float p2X, float p2Y) {
        return (float) Math.sqrt((p2X - p1X) * (p2X - p1X) + (p2Y - p1Y) * (p2Y - p1Y));
    }

    public static float getRandFloat(float min, float max) {
        return min + rand.nextFloat() * (max - min);
    }

    public static int getRandInt(int min, int max) {
        return rand.nextInt((max - min) + 1) + min;
    }

    public static void sleep(long time) {
        try {
            Thread.sleep(time);
        } catch (Exception e) {
            e.getMessage();
        }
    }

    public static int ptToPixel(int pt, DisplayMetrics metrics){
        return (int) ( (pt * metrics.densityDpi) / 72 );
    }

    public static int dpToPixel(int dp, DisplayMetrics metrics){
        return (int) ( dp * (metrics.densityDpi / 160.0f) );
    }
    public static int getIntFromColor(float[] color) {
        return 0xFF000000 | ((Math.round(255 * color[0]) << 16) & 0x00FF0000)
                | ((Math.round(255 * color[1]) << 8) & 0x0000FF00)
                | (Math.round(255 * color[2]) & 0x000000FF);
    }

    public static int fps(int fps) {
        return (1000 / fps);
    }

    public static String convertStreamToString(InputStream is) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }
        reader.close();
        return sb.toString();
    }

    public static float[] randomColor(){
        switch (Tools.getRandInt(0, 10)){
            case 0:
                return new float[]{52.0f/255.0f, 152.0f/255.0f, 219.0f/255.0f,1.0f};
            case 1:
                return new float[]{39.0f/255.0f, 174.0f/255.0f, 96.0f/255.0f,1.0f};
            case 2:
                return new float[]{155.0f/255.0f, 89/255.0f, 182/255.0f,1.0f};
            case 3:
                return new float[]{52.0f/255.0f, 73/255.0f, 94/255.0f,1.0f};
            case 4:
                return new float[]{241/255.0f, 196/255.0f, 15/255.0f,1.0f};
            case 5:
                return new float[]{231/255.0f, 76/255.0f, 60/255.0f,1.0f};
            case 6:
                return new float[]{230/255.0f, 126/255.0f, 34/255.0f,1.0f};
            case 7:
                return new float[]{26/255.0f, 188/255.0f, 156/255.0f,1.0f};
            case 8:
                return new float[]{155/255.0f, 89/255.0f, 182/255.0f,1.0f};
            case 9:
                return new float[]{135/255.0f, 211/255.0f, 124/255.0f,1.0f};
            case 10:
                return new float[]{211/255.0f, 84/255.0f, 0/255.0f,1.0f};
            default:
                return new float[]{100.0f / 255.0f, 128.0f / 255.0f, 185.0f / 255.0f, 1.0f};
        }
    }


} public class GameScene1 implements GameScene{
    private final static String TAG = GameScene1.class.getSimpleName();
    GLRenderer glRenderer;
    public GameWorld gameWorld;
    public BackgroundGS1 background;
    public ColumnsGS1 columns;
    public BirdGS1 bird;
    public UIPauseGS1 uiPause;
    public UIRunGS1 uiRun;
    public String STATE = SceneState.PAUSE;
    public CollisionGS1 collision;
    public Message messageLato;
    public int score = 0;
    public boolean invinsible = false;

    public GameScene1(GLRenderer glRenderer, GameWorld gameWorld) {
        this.gameWorld = gameWorld;
        this.glRenderer = glRenderer;
    }

    @Override
    public void init() {
        new MediaPlayerHelper(glRenderer.context, R.raw.coin);
        new MediaPlayerHelper(glRenderer.context, R.raw.gameover);
        background = new BackgroundGS1(glRenderer, this);
        columns = new ColumnsGS1(glRenderer, this);
        bird = new BirdGS1(glRenderer, this);
        collision = new CollisionGS1(glRenderer, this);
        uiPause = new UIPauseGS1(glRenderer, this);
        uiRun = new UIRunGS1(glRenderer, this);
        messageLato =  new Message(glRenderer, GLRenderer.context.getAssets(), "fonts/Lato/Lato-Regular.ttf",
                Tools.dpToPixel(78, FirstActivity.metrics), 2, 2, Tools.getIntFromColor(Settings.colorWhite));
        background.init();
        columns.init();
        bird.init();
        uiPause.init();
        uiRun.init();

        STATE = SceneState.PAUSE;
    }

    @Override
    public void drawStatic(float[] mtrxProjectionAndView) {
        background.draw(mtrxProjectionAndView);
        columns.draw(mtrxProjectionAndView);
        bird.draw(mtrxProjectionAndView);
        background.draw2(mtrxProjectionAndView);
        uiRun.draw(mtrxProjectionAndView);
    }

    @Override
    public void drawMove(float[] mtrxProjectionAndView) {
        move();
        //TODO : check collision
        collision();
        if (!STATE.equals(SceneState.STOPDRAW)){
            background.draw(mtrxProjectionAndView);
            columns.draw(mtrxProjectionAndView);
            bird.draw(mtrxProjectionAndView);
            background.draw2(mtrxProjectionAndView);
        }
        if (!STATE.equals(SceneState.STOP)){
            uiRun.draw(mtrxProjectionAndView);
        }else if (STATE.equals(SceneState.STOP)){
            uiPause.draw(mtrxProjectionAndView);
        }
    }

    @Override
    public void touchEvent(MotionEvent event) {
        bird.touchEvent(event);
        if (collision.collisionCloseTouch(event)){
            glRenderer.Return();
        }

        if (STATE.equals(SceneState.STOP)){
            if (collision.collisionRestartTouch(event)){
                STATE = SceneState.STOPDRAW;
                reset();
                return;
            }
        }else if (STATE.equals(SceneState.PAUSE)
                && !STATE.equals(SceneState.STOPDRAW)) {
            STATE = SceneState.MOVE;
        }
    }

    @Override
    public void move() {
        if (STATE.equals(SceneState.MOVE)) {
            bird.move();
            columns.move();
        }else if (STATE.equals(SceneState.STOP)){
            uiPause.move();
        }
    }

    @Override
    public void collision() {
        if (STATE.equals(SceneState.MOVE)){
            if (collision.collisionBirdColumns()  && !invinsible){
                gameOver();
            }
            if (collision.collisionScore()){
                score += 1;
                if (Settings.sound)
                    MediaPlayerHelper.playSound(glRenderer.context, R.raw.coin);
                if (score >= GameMode.getGameMode(Settings.currentGameMode+1).scoreToUnlock){
                    Data.setUnlock(Settings.currentGameMode+1, true);
                }
            }
        }
    }

    @Override
    public void gameOver() {
        if (Settings.sound)
            MediaPlayerHelper.playSound(glRenderer.context, R.raw.gameover);
        Data.setHighScore(Settings.currentGameMode, score);
        Data.setDeath(Settings.currentGameMode);
        STATE = SceneState.STOP;
        background.gameOver();
        columns.gameOver();
        bird.gameOver();
        uiRun.gameOver();
        score = 0;
        collision = new CollisionGS1(glRenderer, this);
    }

    @Override
    public void reset(){
        bird.reset();
        columns.reset();
        background.reset();
        STATE = SceneState.PAUSE;
    }
} public class Settings {
    public static float height;
    public static float width;
    public static long fpslimit = 80;
    public static float[] gameOverColor = new float[]{130.0f / 255.0f, 130.0f / 255.0f, 130.0f / 255.0f, 1.0f};
    public static float[] originalColorBird = new float[]{0.0f, 0.0f,180.0f/255.0f, 1.0f};
    public static float[] originalColorRestart = originalColorBird;
    public static float[] colorWhite = new float[]{1.0f, 1.0f, 1.0f, 1.0f};
    public static float[] colorBlack = new float[]{0.0f, 0.0f, 0.0f, 1.0f};
    public static float[] colorStartLine = new float[]{0.0f, 0.0f, 0.0f, 0.1f};
    public static String font = "fonts/Lato/Lato-Black.ttf";
    public static boolean sound = true;
    public static boolean ads = true;
    public static boolean unlock = true;


    public static float[] color = Tools.randomColor();

    public static float bigCircleRadius = 3.4f;
    public static float littleCircleRadius = 18;
    public static float sizeCloseButton = 9;
    public static float sizeBird = 40;
    public static float touchGravity = 235.0f;
    public static float fallGravity = -2000.0f;
    public static float speedBird = -1.0f;
    public static float speedColumns = 0.2f;
    public static float speedColumnsWay = 0.2f;
    public static float sizeColumnsWay = 4.5f;
    public static float sizeColumns = 40;
    public static int numberColumns = 4;
    public static int gameScene = 1;
    public static String background = "background/background1.png";
    public static String bird = "bird/texture_manon_256x256.png";

    public static int currentGameMode;
    public static int scoreToUnlock;


    public Settings(float width, float height, GameMode gameMode) {
        sound = Data.getConfig(FirstActivity.context.getString(R.string.key_sound));
        ads = Data.getConfig(FirstActivity.context.getString(R.string.key_ads));
        unlock = Data.getConfig(FirstActivity.context.getString(R.string.key_unlock));

        currentGameMode = gameMode.id;
        scoreToUnlock = gameMode.scoreToUnlock;

        Settings.width = width;
        Settings.height = height;

        color = gameMode.color;

        speedBird = gameMode.speedBird;
        speedColumns = gameMode.speedColumns;
        speedColumnsWay = Settings.width / gameMode.speedColumnsWay;

        bigCircleRadius = Settings.width / gameMode.bigCircleRadius;
        littleCircleRadius = Settings.width / gameMode.littleCircleRadius;

        sizeBird = Settings.width / gameMode.sizeBird;
        touchGravity = Settings.width / gameMode.touchGravity;
        fallGravity = Settings.width / gameMode.fallGravity;

        sizeColumns = Settings.width / gameMode.sizeColumns;
        sizeColumnsWay = (bigCircleRadius + littleCircleRadius)/gameMode.sizeColumnsWay;
        numberColumns = gameMode.numberColumns;

        gameScene = gameMode.gameScene;
        background = gameMode.background;
        bird = gameMode.bird;

        sizeCloseButton = Settings.width / gameMode.sizeCloseButton;
    }
}
import android.view.MotionEvent;
import com.remijouannet.get10.activity.FirstActivity;
import com.remijouannet.get10.Data;
import com.remijouannet.get10.graphic2D.shape.Shape;
import com.remijouannet.get10.graphic2D.helper.GraphicHelper;
import com.remijouannet.get10.graphic2D.helper.BitmapHelper;
import com.remijouannet.get10.graphic2D.GLRenderer;
import com.remijouannet.get10.graphic2D.GameObject;
import com.remijouannet.get10.graphic2D.texture.LoadTexture;
import com.remijouannet.get10.graphic2D.texture.Message;
import com.remijouannet.get10.graphic2D.Tools;
import com.remijouannet.get10.R;
import com.remijouannet.get10.scenes.gameScene.GameScene1;
import com.remijouannet.get10.Settings;
/*
    Copyright (C) 2015 Rémi Jouannet <remijouannet@gmail.com>
    This file is part of get10.
    get10 is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */

package com.remijouannet.get10.scenes.gameObjects.gameScene1;




public class UIPauseGS1 implements GameObject{
    private final static String TAG = UIPauseGS1.class.getSimpleName();
    public Shape restart;
    LoadTexture restartTexture;

    public Shape close;
    LoadTexture closeTexture;

    public Message highScore;

    GLRenderer glRenderer;
    GameScene1 gameScene1;

    public UIPauseGS1(GLRenderer glRenderer, GameScene1 gameScene1) {
        this.gameScene1 = gameScene1;
        this.glRenderer = glRenderer;
    }

    @Override
    public void draw(float[] mtrxProjectionAndView) {
        GraphicHelper.drawTexture(mtrxProjectionAndView, restart, restart.getBuffer());
        GraphicHelper.drawTexture(mtrxProjectionAndView, close, close.getBuffer());
        highScore.draw(mtrxProjectionAndView,
                glRenderer.context.getResources().getString(R.string.highscore) + " : " +Data.getHighScore(Settings.currentGameMode),
                glRenderer.screenWidth /9.0f, glRenderer.screenHeight /1.1f, Tools.dpToPixel(40, FirstActivity.metrics));