0

For some time I've been making Android game based on canvas library. I decided to make an endless runner. I tested it on several devices.

On my old Sony M4 Aqua, also Huawei Y6, and Samsung S8 everything seems to be alright, but when I tested it on Huawei P20 Lite it was only loading splash screen and then crushing.

I realised that it was problem with setting landscape mode and I had to put it in manifest.xml to work. Now it's working, but it has very few FPS. I checked and problem was in Background class, but only on that phone.

package turtle.app;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;

import java.io.IOException;
import java.io.InputStream;

public class Background {

    private Bitmap background, background2;
    private Rect backSrc, backDes, backSrc2;

    private int speed;

    public Background(String path, int speed){
        this.speed = speed;
        background = getBackground(path);
        backSrc = new Rect(0, 0, Constants.SCREEN_WIDTH, background.getHeight());
        backDes = new Rect(0, 0, Constants.SCREEN_WIDTH, Constants.SCREEN_HEIGHT);
        background2 = Bitmap.createBitmap(background, background.getWidth() - Constants.SCREEN_WIDTH, 0, Constants.SCREEN_WIDTH, background.getHeight());
        backSrc2 = new Rect(Constants.SCREEN_WIDTH, 0, Constants.SCREEN_WIDTH * 2, background.getHeight());
    }

    private static Bitmap getBackground(String strName) {
        AssetManager assetManager = Constants.context.getAssets();
        InputStream istr;
        Bitmap bitmap = null;
        try {
            istr = assetManager.open(strName);
            bitmap = BitmapFactory.decodeStream(istr);
        } catch (IOException e) {
            return null;
        }
        return bitmap;
    }

    public void changeSpeed(int newSpeed){
        speed = newSpeed;
    }

    public void update() {

        backSrc.left += speed;
        backSrc.right += speed;
        backSrc2.left += speed;
        backSrc2.right += speed;

        if(backSrc.right >= background.getWidth()) {
            backSrc2.left = 0;
            backSrc2.right = Constants.SCREEN_WIDTH;
            backSrc.left = - Constants.SCREEN_WIDTH;
            backSrc.right = 0;
        }
    }

    public void draw(Canvas canvas) {
        canvas.drawBitmap(background, backSrc, backDes, null);
        canvas.drawBitmap(background2, backSrc2, backDes, null);
    }
}

And here is my game loop just for sure.

package turtle.app;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class MainThread extends Thread {
    private SurfaceHolder surfaceHolder;
    private GamePanel gamePanel;
    private boolean running;
    public static Canvas canvas;

    public void setRunning(boolean running) {
        this.running = running;
    }

    public MainThread(SurfaceHolder surfaceHolder, GamePanel gamePanel) {
        super();
        this.surfaceHolder = surfaceHolder;
        this.gamePanel = gamePanel;
    }

    public void run() {
        long lastTime = System.nanoTime();
        double amountOfTicks = 100.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        long timer = System.currentTimeMillis();
        int frames = 0;
        while (running) {
            canvas = null;
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while (delta >= 1) {
                this.gamePanel.update();
                delta--;
            }
            try {
                canvas = this.surfaceHolder.lockCanvas();
                synchronized (surfaceHolder) {
                    this.gamePanel.draw(canvas);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (canvas != null) {
                    try {
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            frames++;
            if (System.currentTimeMillis() - timer > 1000) {
                timer += 1000;
                System.out.println("FPS: " + frames);
                frames = 0;
            }
        }
    }
}

Is it something in new Huawei phones or I did something wrong?

Zoe
  • 27,060
  • 21
  • 118
  • 148
Tricky
  • 1
  • 2

1 Answers1

0

This is a sign of using too many resources. Maybe your game is not expected to run in low CPU devices.

There's still some hope:

  • When developing in Android Studio, you can check what's processes your CPU is running. To do this, click in Profiler (or press Cmd+Shift+A in Mac and type Profile)

enter image description here

  • Add a session of your device:

enter image description here

  • Now your app is running. Click in CPU and Record a timeframe (let's say 10 seconds) where your app struggles.

  • Stop recording and you'll have something like this:

enter image description here

Do you see the small bits at the bottom? Those are the functions are are being called, for example, when you update a list, you set some text, you change a colour, etcetera. You might identify what's going wrong in your app, for example, you're changing a text and it's taking 300ms when you know it should take 5ms or 6ms.

Good luck.

Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92