You are here

Chapter 38: Scaling in GameStatus

One last touch in the code (hopefully).

I noticed that on devices with very small screens, such as Sony Ericsson X10 Mini Pro, the text "GAME OVER" does not fit.

On very large screen, on the other hand, a few text fields are squeezed together even though there are plenty of space around.

So let's change the hard coded text sizes 25, 30 and 50 and the hard coded y-positions in GameStatus.draw()  to scaled values instead.

In order to do that, we must add a call to GameStatus from GameEngine when we get the surface dimensions from Android. So, add one line in GameEngine.setSurfaceDimensions:

public void setSurfaceDimensions(int width, int height) {
    screenWidth = width;
    screenHeight = height;
        
    gameStatus.updateSurfaceDimensions(width, height);

    if (mode == WAITING_FOR_SURFACE) {
        setLevel(1);
    }

}

Unfortunately the required changes in GameStatus are spread out all through the class:

package com.ajomannen.justroids;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

public class GameStatus {
    private Paint textPaint;
    private int level;
    private int thrusts;
    private int thrustsLastLevel;
    private int firedMissiles;
    private int firedMissilesLastLevel;
    private long levelStartTime;
    private long passedLevelTime;
    private long passedLevelTimeLastLevel;
    private float smallTextSize = 25;
    private float mediumTextSize = 30;
    private float largeTextSize = 50;

    private static final long GRACE_PERIOD = 5000000000L;

    public GameStatus() {
        textPaint = new Paint();
        textPaint.setColor(Color.LTGRAY);
        // textPaint.setTextSize(25);
    }

    public void updateSurfaceDimensions(int width, int height) {
        // 25, 30 and 50 are perfect sizes on a 320 points wide screen
        smallTextSize = width / (320 / 25);
        mediumTextSize = width / (320 / 30);
        largeTextSize = width / (320 / 50);
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;

        thrustsLastLevel = thrusts;
        firedMissilesLastLevel = firedMissiles;
        passedLevelTimeLastLevel = passedLevelTime;

        thrusts = 0;
        firedMissiles = 0;
        levelStartTime = System.nanoTime() + GRACE_PERIOD;
    }

    public long getPassedLevelTime() {
        return passedLevelTime;
    }

    public void increaseThrusts() {
        thrusts++;
    }

    public void increaseFiredMissiles() {
        firedMissiles++;
    }

    public void update() {
        passedLevelTime = (System.nanoTime() - levelStartTime) / 1000000000L;
    }

    public void draw(Canvas canvas, float screenHeight, float screenWidth) {
        textPaint.setTextSize(smallTextSize);
        if (passedLevelTime > 0) {
            textPaint.setTextAlign(Paint.Align.LEFT);
            canvas.drawText("Level: " + level, 1, smallTextSize, textPaint);
            canvas.drawText("Thrusts: " + thrusts, 1, screenHeight - 2,
                    textPaint);

            textPaint.setTextAlign(Paint.Align.RIGHT);
            canvas.drawText("Time: " + passedLevelTime + "s", screenWidth - 1,
                    19, textPaint);
            canvas.drawText("Missiles: " + firedMissiles, screenWidth - 1,
                    screenHeight - 2, textPaint);
        } else {
            textPaint.setTextAlign(Paint.Align.CENTER);
            if (level > 1) {
                canvas.drawText("Level " + (level - 1) + " completed! ",
                        screenWidth / 2, mediumTextSize, textPaint);
                canvas.drawText(" Time: " + passedLevelTimeLastLevel + "s",
                        screenWidth / 2, mediumTextSize * 2, textPaint);
                canvas.drawText("Thrusts: " + thrustsLastLevel,
                        screenWidth / 2, mediumTextSize * 3, textPaint);
                canvas.drawText("Missiles: " + firedMissilesLastLevel,
                        screenWidth / 2, mediumTextSize * 4, textPaint);
            }
            textPaint.setTextSize(mediumTextSize);
            canvas.drawText("Level " + level + " starts in "
                    + (-passedLevelTime) + "s", screenWidth / 2,
                    (float) (screenHeight * 0.75), textPaint);
            // textPaint.setTextSize(25);
        }
    }

    public void drawGameOverScreen(Canvas canvas, float screenHeight,
            float screenWidth) {
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(largeTextSize);
        canvas.drawText("GAME OVER", screenWidth / 2,
                (float) (screenHeight * 0.50), textPaint);
        textPaint.setTextSize(smallTextSize);
        canvas.drawText("You reached level " + level, screenWidth / 2,
                (float) (screenHeight * 0.60), textPaint);
        canvas.drawText("Press 'Back' for Main Menu", screenWidth / 2,
                (float) (screenHeight * 0.85), textPaint);
    }

}

Now the text also fits on really tiny screens:

(I will not include a screenshot from a very large screen, but I can assure you that the text is better aligned ;-) )

 

Note: I used an online Java syntax highllighter in this chapter, instead of performing a lot of manual steps when including source code. The look and feel is a bit different than in previous chapters, but I think it's to the better.

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer