代码之家  ›  专栏  ›  技术社区  ›  Axarydax

如何在Android上正确地扩展游戏

  •  9
  • Axarydax  · 技术社区  · 14 年前

    为了简单起见,让我们假设我正在为Android制作一个简单的Pong克隆游戏。假设它只能在横向模式下播放。(暂时忽略方形电话)。

    我希望游戏在每部手机上看起来都是相同的比例,如果你在QVGA手机上拍摄了游戏的屏幕截图,并将屏幕大小调整为WVGA大小,它看起来几乎与WVGA手机上的游戏一样。换言之,桨叶的宽度应始终为屏幕宽度的1/32,球的直径应始终为屏幕宽度的1/16。

    什么是正确的方法来绘制应用程序?它将在标准的SurfaceView中运行,该SurfaceView将被绘制到 Canvas .

    假设我有一个高分辨率的png用于划桨、球和游戏字体(记分板、主菜单)。

    我找到物理分辨率,然后缩放 帆布 通过 scale(float sx, float sy) 使我的所有画布(在QVGA和WVGA上)具有相同的 事实上的 分辨率,然后在每个屏幕大小的每个位置上绘制完全相同的基本体?

    或者我可以在画布上使用密度无关像素(dip)吗?

    3 回复  |  直到 12 年前
        1
  •  4
  •   Gergely Fehérvári    11 年前

    我只玩了一次绘图画布函数,然后全部切换到opengl,但逻辑保持不变(我想)。

    第一个问题,你要保持一个比例恒定从一个电话到另一个。 在我的应用程序中,我在每一边添加了一个“黑带”效果。 在onSurfaceChanged中,您将需要计算一个比率,该比率将允许您确定需要在每一侧移除多少空间才能保持图形的一致性。这将为您提供一个delta X或Y以应用于所有绘图 下面的代码是我从ogl版本中改编的,所以可能需要花点时间

    @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;       
    }
    

    然后,您还希望能够通过知道画布上的实际大小以及image.getWidth()(图片的实际大小)和image.getScaledWidth(画布)之间的差异(后者提供dp中元素的大小,这意味着元素将在屏幕)很重要。看看下面的例子。

    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);
    }
    }
    

    这应该能解决你所有的比率问题 我建议使用opengl,因为它将简化您保持不变方面的需求,但我想这不是一个选项^^

    希望这对你有帮助

        2
  •  2
  •   Fred Grott    14 年前

    使用浸渍和油漆桨叶,而不是使用PNG

        3
  •  -1
  •   dcarneiro    14 年前

    我认为只有3种标准分辨率可用(ldip、mdip、hdip),您应该为每个分辨率都有一个资源文件夹。

    http://developer.android.com/guide/practices/screens_support.html

    如果您手动缩放PNG以适应3种可用分辨率中的每一种,则手机应以透明的方式加载特定的资源文件夹