Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly scale a game on Android

for the sake of simplicity let's assume that I'm making a simple Pong clone game for Android. Let's assume that it would only be playable in the landscape mode. (ignore square phones for now).

I'd like the game to look in the same scale on each phone, to the extent that if you took a screenshot of the game on QVGA phone, and resized the screenshot to WVGA size, it would look almost the same as would the game look on WVGA phone. In other words, the paddle's width should always be 1/32 of the screen width, the ball's diameter should always be 1/16 of the screen width.

What would be the proper way to paint the application? It would run in standard SurfaceView that would be drawn onto a Canvas.

Let's say that I have a high-resolution PNGs for the paddle, ball and for the game font (scoreboard, main menu).

Do I find out the physical resolution, then scale the Canvas via scale(float sx, float sy) to make all my Canvases (on QVGA and WVGA) have the same virtual resolution, and then draw exactly the same primitives on each position on each screen size?

Or can I use density-independent pixels (dip) somehow in the Canvas?

like image 204
Axarydax Avatar asked Nov 15 '10 10:11

Axarydax


People also ask

How do I adjust the games screen size Android?

Let me show you. Open up Settings and then tap on Display. Scroll down and tap on Display size. In this new screen, drag the slider to left to shrink the display size or the right to enlarge it.

How do I make my game fit my screen?

Under the main menu of the game, select Options, and un-check Full Screen mode. In some games, Windowed Mode may appear in place of the Full screen option. You can also try manually adjusting your computer monitor. By tuning the horizontal and vertical holds, you may be able to improve the picture quality.

What size should a mobile game be?

According to research from SensorTower, the average file size of mobile games increased by 76% in the US since 2016. Based on an assessment of the top 100 revenue generating mobile games in the US App Store, the experts found that the average game file size was 264MB in 2016 compared to 465MB in 2020.


1 Answers

I only played once with the draw canvas functions and then switched all to opengl but the logic stays the same (I think).

first issue you'll want to keep a ratio constant form one phone to the other. in my app I add a " black band" effect on each side. in onSurfaceChanged, you'll want to calculate a ratio, this ratio will allow you to determine how much space you have to remove on each side to keep a consistent aspect to your drawing. this will give you a delta X or Y to apply to all your draws the following code is something I adapted from the ogl version so it might need to be tweeked a bit

@Override
   public void onSurfaceChanged(int w, int h){
   float ratioPhysicScreen = nativeScreenResoltionW/nativeScreenResoltionH;
   float ratioWanted = GameView.getWidth()/GameView.getHeight();
   if(ratioWanted>ratioPhysicScreen){
      newHeight = (int) (w*GameView.getHeight()/GameView.getWidth());
      newWidth = w;
      deltaY = (int) ((h-newHeight)/2);
     deltaX = 0;
   }else{
      newWidth = (int) (h/GameView.getHeight()*GameView.getWidth());
      newHeight = h;
      deltaX = (int) ((w-newWidth)/2);
      deltaY = 0;       
}

then you'll also want to be able to draw your pictures on the canvas by knowing there size as well on the canvas than there real size and that where the difference in between image.getWidth() (actual size of the picture) and a image.getScaledWidth(canvas) which give you the size of the element in dp which means how big it will appear on the screen) is important. look at the example underneath.

public class MainMenuView extends PixelRainView{
private Bitmap bmpPlay = null;
private float playLeft = 0;
private float playRight = 0;
private float playBottom = 0;
private float playTop = 0;

public MainMenuView(Context context, AttributeSet attrs) {
    super(context,attrs);
}



@Override
public void unLoadBitmaps() {
    super.unLoadBitmaps();
    if(bmpPlay != null){
        bmpPlay.recycle();
        bmpPlay = null;
    }
}



@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if(bmpPlay == null){
        bmpPlay = getBitmapFromRessourceID(R.drawable.play_bt);
        playLeft = (this.getWidth()-bmpPlay.getScaledWidth(canvas))/2; 
        playRight = playLeft + bmpPlay.getScaledWidth(canvas);
        playTop = (this.getHeight()-bmpPlay.getScaledHeight(canvas))/2;
        playBottom = playTop+bmpPlay.getScaledHeight(canvas);
    }
    canvas.drawBitmap(bmpPlay,playLeft, playTop, null);

    }       
}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
}



@Override
public boolean onTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        float x = event.getX();
        float y = event.getY();
        //test central button
        if(x>playLeft && x<playRight && y<playBottom && y>playTop){
            Log.e("jason", "touched play");
            PixelRainView.changeView(R.layout.composedlayoutgroup);
        }
    return super.onTouchEvent(event);
}
}

This should solve all your ratio problem cross plateforms I would suggest opengl because it will simplify your need for keeping a constant aspect but I guess its not an option ^^

Hope this helps you enough

like image 102
Jason Rogers Avatar answered Nov 12 '22 05:11

Jason Rogers