三、实现界面,兼容多分辨率
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:文中如有不对之处,敬请指出!谢谢~