如何在Android上正确缩放游戏
为了简单起见,让我们假设我正在为Android制作一个简单的乒乓球克隆游戏。让我们假设它只能在横向模式下播放。(暂时忽略方形电话) 我希望游戏在每部手机上都能以相同的比例显示,如果你在QVGA手机上拍摄游戏的屏幕截图,并将屏幕截图调整为WVGA大小,它看起来几乎与WVGA手机上的游戏一样。换句话说,桨叶的宽度应始终为屏幕宽度的1/32,球的直径应始终为屏幕宽度的1/16 什么是正确的涂漆方法?它将在标准SurfaceView中运行,该视图将绘制到如何在Android上正确缩放游戏,android,resolution,android-canvas,Android,Resolution,Android Canvas,为了简单起见,让我们假设我正在为Android制作一个简单的乒乓球克隆游戏。让我们假设它只能在横向模式下播放。(暂时忽略方形电话) 我希望游戏在每部手机上都能以相同的比例显示,如果你在QVGA手机上拍摄游戏的屏幕截图,并将屏幕截图调整为WVGA大小,它看起来几乎与WVGA手机上的游戏一样。换句话说,桨叶的宽度应始终为屏幕宽度的1/32,球的直径应始终为屏幕宽度的1/16 什么是正确的涂漆方法?它将在标准SurfaceView中运行,该视图将绘制到画布上 假设我有一个高分辨率的PNG,用于划桨、球
画布上
假设我有一个高分辨率的PNG,用于划桨、球和游戏字体(记分板、主菜单)
我是否要找出物理分辨率,然后通过scale(float sx,float sy)
缩放Canvas
以使我的所有画布(在QVGA和WVGA上)具有相同的虚拟分辨率,然后在每个屏幕大小的每个位置上绘制完全相同的原语
或者我可以在画布中使用与密度无关的像素(dip)吗?使用dip并绘制挡板,而不是使用PNG我认为只有3种标准分辨率可用(ldip、mdip、hdip),您应该为每种分辨率设置一个资源文件夹
如果您手动缩放PNG以适应3种可用分辨率中的每一种,手机应该以透明的方式加载特定的资源文件夹我只使用绘制画布功能玩了一次,然后切换到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);
}
}
public类MainMenuView扩展了PixelRainView{
私有位图bmpPlay=null;
私有浮动playLeft=0;
私有浮动playRight=0;
私有浮动播放底部=0;
私有浮动playTop=0;
公共主菜单视图(上下文、属性集属性){
超级(上下文,attrs);
}
@凌驾
公共位图(){
super.unload位图();
if(bmpPlay!=null){
bmpPlay.recycle();
bmpPlay=null;
}
}
@凌驾
受保护的void onDraw(画布){
super.onDraw(帆布);
if(bmpPlay==null){
bmpPlay=GetBitMapFromResourceId(R.drawable.play_bt);
playLeft=(this.getWidth()-bmpPlay.getScaledWidth(canvas))/2;
playRight=playLeft+bmpPlay.getScaledWidth(画布);
playTop=(this.getHeight()-bmpPlay.getscaledeheight(canvas))/2;
playboottom=playTop+bmpPlay.getScaledHeight(画布);
}
drawBitmap(bmpPlay、playLeft、playTop、null);
}
}
@凌驾
已更改尺寸的受保护空心(整数w、整数h、整数oldw、整数oldh){
super.onSizeChanged(w,h,oldw,oldh);
}
@凌驾
公共布尔onTouchEvent(运动事件){
if(event.getAction()==MotionEvent.ACTION\u向下){
float x=event.getX();
float y=event.getY();
//测试中央按钮
如果(x>playLeft&&x我如何在画布中使用drawLine()之类的dips方法呢?好吧,让我们先忘掉Pong clone,再谈谈Pac man或SimCity之类的基于磁贴的游戏。所以有一些磁贴存储在PNG中,Pong可能太简单了。