1、概述
最近开发一个智能项目,项目对象是某智能早教机器人,这个产品主要定位是儿童益智玩的游戏,并且可以从中学习到相关历史知识等相关知识,其中有个游戏关卡就是去到不同国家,可以玩不同的游戏。领导说要用Android原生做游戏,卧槽,我当时就懵逼,原生做游戏,我就试试开撸吧。
好吧,先上个效果图
思路分析
1、水果
2、背景
3、水果篮子
4、分数
5、时间
6、水果刀
7、当用户touch屏幕时,水果刀跟着移动,水果刀碰到水果,被切成两半
3、SurfaceView模板
我先创建一个类为FruitGameSurfaceView 继承SurfaceView,上代码。
/**
* @author Tim
*/
@SuppressWarnings("ALL")
public class FruitGameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mHolder;
private final Surface surface;
public Thread getT() {
return t;
}
public void setT(Thread t) {
this.t = t;
}
public Canvas getCanvas() {
return canvas;
}
public void setCanvas(Canvas canvas) {
this.canvas = canvas;
}
public SurfaceHolder getmHolder() {
return mHolder;
}
public void setmHolder(SurfaceHolder mHolder) {
this.mHolder = mHolder;
}
public boolean isRunning() {
return isRunning;
}
public void setRunning(boolean running) {
isRunning = running;
}
/**
* 线程控制开关
*/
private boolean isRunning;
private Thread t;
private Canvas canvas;
public FruitGameSurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mHolder = getHolder();
mHolder.addCallback(this);
//可获得焦点
setFocusable(true);
setFocusableInTouchMode(true);
//设置常亮
setKeepScreenOn(true);
surface = mHolder.getSurface();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isRunning = true;
t = new Thread(this);
t.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
isRunning=false;
}
protected void myDraw(Canvas canvas) {
}
@Override
public void run() {
//不断绘制
while (isRunning){
long start = System.currentTimeMillis();
draw();
long end = System.currentTimeMillis();
try
{
if (end - start < 50)
{
Thread.sleep(50 - (end - start));
}
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
private void draw() {
if(mHolder != null) {
canvas = mHolder.lockCanvas();
}
try {
if (canvas != null && mHolder != null &&surface != null && surface.isValid()) {
myDraw(canvas);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (canvas!=null){
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
这个模板类,在HongYang前辈哪里已经学习过来的,可以直接拷贝,在此类基础上编写。
4、绘制相关
我再创建一个类继承我的FruitGameSurfaceView,这个类叫MyGameView专注于刷新绘制。
//专用于绘制屏幕
@Override
protected void myDraw(Canvas canvas) {
super.myDraw(canvas);
//用户画背景
drawBg(canvas);
//画水果篮子
drawFruitBox(canvas);
//画刀光
drawBlade(canvas);
if (isOpen) {
//到了计算好的时间就生成精灵
if (mNextTime < System.currentTimeMillis()) {
generateSpirit();
// mSoundPool.play(mExplodeSoundId, 1, 1, 1, 0, 1);
nextGenTime();
}
}
// if(mNextTimeBoom<System.currentTimeMillis()){
// //画炸弹
// drawBoom();
// nextGenTimeBoom();
// }
//绘制时间
drawTime(canvas);
//检查精灵是否还在屏幕内,不在屏幕内则移除
checkSpirites();
//画水果
drawSpirites(canvas);
//初始化切到水果
isHit();
// //初始化撞击炸弹
// isHitBomb();
// //绘制分数
drawGrades(canvas);
}
1、绘制相关代码
/**
* 绘制背景
*/
private void drawBg(Canvas canvas) {
//初始化图片
canvas.drawBitmap(mBg, null, mGamePanelRect, null);
}
/**
* 画水果篮子
*
* @param canvas
*/
private void drawFruitBox(Canvas canvas) {
canvas.drawBitmap(mIcon_fruit_all, null, mRectFFruitAll, null);
}
/**
* 画刀光到画布上,可以扩展
*
* @param canvas
*/
private void drawBlade(Canvas canvas) {
synchronized (mTrack) {
Path path = new Path();
Float startX, startY;
Float controlX, controlY;
Float endX, endY;
int strokeWidth = 1;
if (mTrack.size() > 1) {
endX = mTrack.get(0).x;
endY = mTrack.get(0).y;
for (int i = 0; i < mTrack.size() - 1; i++) {
startX = endX;
startY = endY;
controlX = mTrack.get(i).x;
controlY = mTrack.get(i).y;
endX = (controlX + mTrack.get(i + 1).x) / 2;
endY = (controlY + mTrack.get(i + 1).y) / 2;
path.moveTo(startX, startY);
path.quadTo(controlX, controlY, endX, endY);
paintBlade.setColor(mBladeColor);
paintBlade.setStrokeWidth(strokeWidth++);
canvas.drawPath(path, paintBlade);
path.reset();
}
startX = endX;
startY = endY;
endX = mTrack.get(mTrack.size() - 1).x;
endY = mTrack.get(mTrack.size() - 1).y;
path.moveTo(startX, startY);
path.lineTo(endX, endY);
paintBlade.setStrokeWidth(strokeWidth++);
paintBlade.setColor(mBladeColor);
canvas.drawPath(path, paintBlade);
mTrack.remove(0);
}
}
}
/**
* 倒计时,右上角时间和页面判断跳转
*
* @param canvas
*/
private void drawTime(Canvas canvas) {
if (System.currentTimeMillis() - mTimeCount > 1000) {
mTimeCount = System.currentTimeMillis();
count--;
if (count == 0) {
isOpen = false;
// Intent intent = new Intent(mContext, GameStopActivity.class);
// intent.putExtra("Score", ""+ scroe);
// mContext.startActivity(intent);
} else {
}
}
if (count <= 0) {
canvas.drawText("Time:" + 0, width - 250, 130, timePaint);
} else {
canvas.drawText("Time:" + count, width - 250, 120, timePaint);
}
}
/**
* 画精灵到画布上
*
* @param canvas
*/
private void drawSpirites(Canvas canvas) {
for (int i = 0; i < mSpirits.size(); i++) {
mSpirits.get(i).draw(canvas);
}
// for(int i=0;i<mBooms.size();i++){
// mBooms.get(i).draw(canvas);
// }
}
/**
* 初始化切到水果的时候
*/
private void isHit() {
synchronized (mTrack) {
for (int i = 0; i < mTrack.size(); i++) {
for (int z = 0; z < mSpirits.size(); z++) {
if (mTrack.get(i).x > mSpirits.get(z).mCoord.x && mTrack.get(i).x < mSpirits.get(z).mCoord.x + mSpirits.get(z).mDimention.x) {
if (mTrack.get(i).y > mSpirits.get(z).