Android SurfaceView实现游戏2048[三]

三、实现界面,兼容多分辨率

1.效果图在文章[一]中可看到。这里首先附上layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFBBADA1"
    android:orientation="vertical" >
    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="#b2000000"
        android:padding="5dip"
        >
        <TextView 
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:text="@string/app_name"
            android:layout_gravity="center_vertical"
            android:paddingLeft="5dip"
            android:textSize="20sp"
            android:textColor="@android:color/white"
            android:layout_weight="1.0"
            />
        <ImageView 
            android:id="@+id/refresh_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_refresh"
            android:paddingRight="5dip"
            android:contentDescription="@null"
            />
    </LinearLayout>
    
    <com.walk.game2048.GameView 
        android:id="@+id/game_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
    

</LinearLayout>
其中,refresh_btn用来重置/刷新,GameView就是游戏的SurfaceView了。

2.实现游戏部分界面

从之前的文章知道,每个滑块是一个Block对象。每个滑块是圆角矩形,宽是屏幕宽/4,高等于宽。当然,每个滑块在画的时候要加上Padding,不然就贴在一起了。这样 主要考虑下多分辨率了。解决适配问题,可基于一个分辨率定坐标,然后取当前屏幕大小,与基准分辨率比较获取到缩放比例。这里就不再赘述。

画圆角矩形,可用Canvas.drawRoundRect(RectF rectF, float dx, float dy, Paint paint)。

好了,下面附上画滑块的简单代码:

for (int row = 0; row < mBlocks.length; row++) {
				for (int column = 0; column < mBlocks[row].length; column++) {
					if (!mDraw[row * mBlocks[row].length + column]) {
						continue;
					}
					RectF rectF = new RectF();
					rectF.set(column * rectWidth + mScreenAdapter.getRectPadding(), 
							row * rectHeight + mScreenAdapter.getRectPadding(), 
							(column + 1) * rectWidth - mScreenAdapter.getRectPadding(), 
							(row + 1) * rectHeight - mScreenAdapter.getRectPadding());
					paint.setColor(mBlocks[row][column].getColor());
					mScreenAdapter.drawRoundRect(rectF, canvas, paint);
					paint.setTextSize(40.0f);
					paint.setColor(Color.BLACK);
					if (mBlocks[row][column] != mBlockObjArray.get(0)) {
						mScreenAdapter.drawText(String.valueOf(mBlocks[row][column].getNumber()), 
								column * rectWidth, row * rectHeight, 
								mScreenAdapter.getRectWidth(), mScreenAdapter.getRectHeight(), 
								canvas, paint);
					}
				}
			}

其中mDraw是一个一维数组,保存的是当前滑块是否可画,用来配合生成新滑块时的动画效果。mScreenAdapter是自己实现的一个适配分辨率的类。drawRoundRect实现上就是调用canvas的drawRoundRect。最后判断是不是空块,空块的话就不画数字。

最后附上GameView代码:

package com.walk.game2048;

import java.util.Date;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * 游戏View
 * @author walk
 *
 */
public class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
	
	private boolean isRun = false;
	private Thread mThread = null;
	private SurfaceHolder mHolder;
	private Canvas mCanvas;
	private Paint mPaint;
	
	private GameActivity mContext;
	
	private static final int REFRESH_FRAME = 30;

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		mContext = (GameActivity) context;
		mHolder = getHolder();
		mHolder.addCallback(this);
		mHolder.setFormat(PixelFormat.TRANSLUCENT);
		mPaint = new Paint();
		mPaint.setAntiAlias(true);
		setZOrderOnTop(true);
	}

	@Override
	public void run() {
		Date date = null;
		while (isRun) {
			date = new Date();
			if (mContext.isClose()) {
				isRun = false;
			} else {
				mContext.getLogic().run();
				draw();
			}
			try {
				Thread.sleep(Math.max(0, REFRESH_FRAME - (new Date().getTime() - date.getTime())));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		isRun = true;
		mThread = new Thread(this);
		mThread.start();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		isRun = false;
	}
	
	private void draw () {
		try {
			if (mHolder != null) {
				mCanvas = mHolder.lockCanvas();
				mCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
				mContext.getLogic().paint(mCanvas, mPaint);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (mCanvas != null) {
				mHolder.unlockCanvasAndPost(mCanvas);
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return mContext.getLogic().onTouchEvent(event);
	}
	

}

由于时间关系,界面部分就到这了。做饭...

PS:文中如有不对之处,敬请指出!谢谢~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值