初学者的漫步拾忆SurfaceView

来源:互联网 发布:p2p交易量数据分析 编辑:程序博客网 时间:2024/03/29 02:41

学习编程两年了.
我却始终在和switch语句,界面UI做斗争.
学过不少东西,不过还是毛都不懂.
或者说我已经从入门到放弃了吧.

可笑啊.
不甘堕落却又不思进取.
懒惰却总像是潜藏在身体的瘾,稍有怠慢便上了瘾.
惶恐,不安,百无聊赖.

好了,梳理了下心情,开始干正事.

分享学习到的基础小案例,涉及到SurfaceView ,SurfaceHolder,Surface,Thread方面的知识.
想学习的同学可以滑动页面到最底部.

这里写图片描述

这里写图片描述

MainActivity

package com.example.luokexi.gameuidayone;import android.app.Activity;import android.os.Bundle;import android.view.MotionEvent;public class MainActivity extends Activity {    private GameUI gameUI;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //no title        //requestWindowFeature(Window.FEATURE_NO_TITLE);        //no bar        //getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,               // WindowManager.LayoutParams.FLAG_FULLSCREEN);        gameUI = new GameUI(this);        setContentView(gameUI);//底部支持一个view对象    }    /**     *     * @param event 响应触摸事件 发射炸弹     * @return     */    @Override    public boolean onTouchEvent(MotionEvent event) {        gameUI.handleTouch(event);        return true;    }}

AndroidMainfest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.luokexi.gameuidayone">    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

GameUI

package com.example.luokexi.gameuidayone;import android.content.Context;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.util.Log;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import com.example.luokexi.gameuidayone.domain.Bomb;import com.example.luokexi.gameuidayone.domain.Boy;import com.example.luokexi.gameuidayone.domain.MyButton;import java.util.ArrayList;import java.util.concurrent.CopyOnWriteArrayList;import static android.R.attr.button;/** * Created by Luokexi on 2017/7/1. */public class GameUI extends SurfaceView implements SurfaceHolder.Callback{    private boolean isRender ; // 标记是否开启线程    private MyButton mButton;    //private Bomb bomb;    private Boy boy;//    private ArrayList<Bomb> bombList = new ArrayList<Bomb>();    private CopyOnWriteArrayList<Bomb> bombList = new CopyOnWriteArrayList<Bomb>();    public GameUI(Context context) {        super(context);        SurfaceHolder holder  = getHolder();//获取放映机        holder.addCallback(this);//添加会调    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        isRender = true;        boy = new Boy(BitmapFactory.decodeResource(getResources(),                R.drawable.boy),new Point(0,0));//        bomb = new Bomb(BitmapFactory.decodeResource(getResources(),//                R.drawable.ic_bomb),new Point(0,0),new Point(200,200));        mButton = new MyButton(BitmapFactory.decodeResource(getResources(),                R.drawable.bottom),BitmapFactory.decodeResource(getResources(),                R.drawable.bottom_pass),new Point(30,getHeight()-400));        mButton.setClickListener(new MyButton.ClickListener() {            @Override            public void click() {                Log.d("TAG","被点击");                //boy.move(Boy.MOVE_DOWN);                int y =  getHeight() -  boy.mDefaultBitmap.getHeight();                if(boy.mPoint.y < y){                    boy.move(Boy.MOVE_DOWN);                }            }        });        RenderThread renderThread = new RenderThread();        renderThread.start();//开启绘制线程    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        isRender = false;    }    /**     *     * @param event 响应触摸事件 发射炸弹     * @return     */    public void handleTouch(MotionEvent event) {        int x = (int) event.getX();        int y = (int) event.getY();        Point point = new Point(x,y);        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                if (!mButton.isClick(point)) {                    Bomb bomb = boy.createBomb(getContext(), point);                    bombList.add(bomb);                }else {                    System.out.println("按钮被点击");                }                break;            case MotionEvent.ACTION_UP:                    mButton.setClick(false);//抬起时需要将图片设为默认            default:                break;        }    }    /**     * 开启子线程 绘制界面     */    class RenderThread extends Thread{        @Override        public void run() {            // while不断循环 保证界面不断发生变化 从而实现动画效果            while (isRender){                    drawUI();            }        }    }    private void drawUI(){            //绘制界面        Canvas canvas = getHolder().lockCanvas();//获取画布对象        if(canvas != null){        Paint paint = new Paint();        paint.setColor(Color.WHITE);        canvas.drawRect(0,0,getWidth(),getHeight(),paint); //画矩形            boy.drawSelf(canvas);//绘制男孩对象            mButton.drawSelf(canvas);//绘制按钮//        if (bomb != null) {//            bomb.drawSelf(canvas);//绘制炸弹对象//            bomb.move();//炸弹移动//        }            //遍历炸弹集合画出所有炸弹//            for (int i = 0;i<bombList.size();i++){//                Bomb bomb = bombList.get(i);//                bomb.drawSelf(canvas);//绘制炸弹对象//                bomb.move();//炸弹移动//                //判断炸弹是否移除屏幕//                Point point = bomb.getPoint();//                if(point.x>getWidth()||point.x<0//                        ||point.y>getHeight()||point.y<0){//                        bombList.remove(i);//                }   这里用for循环会出现并发修改异常//            ArrayList<Bomb> list = new ArrayList<Bomb>();//            list.addAll(bombList);            for (Bomb bomb : bombList) {                bomb.drawSelf(canvas);                bomb.move();                //判断炸弹是否移除屏幕                Point point = bomb.getPoint();                if (point.x > getWidth() || point.x < 0                        || point.y > getHeight() || point.y < 0) {                    bombList.remove(bomb);                }            }        getHolder().unlockCanvasAndPost(canvas);//提交画布        }    }}

接下来是三个Sprite基类

Bomb

package com.example.luokexi.gameuidayone.domain;import android.graphics.Bitmap;import android.graphics.Point;/** * Created by Luokexi on 2017/7/1. */public class Bomb extends Sprite {    private int speed =200;//移动速度    private int dx;//移动时x的偏移量    private int dy;//移动时y的偏移量    public Bomb(Bitmap mDefaultBitmap, Point point,Point targetPoint) {        super(mDefaultBitmap, point); // 当前坐标点 point(从父类里得到的坐标点) 目标坐标点 targetPoint        int x = targetPoint.x - point.x;        int y = targetPoint.y - point.y;        int d = (int) Math.sqrt(x*x + y*y);//获取炸弹移动距离        dx = x * speed /d;        dy = y * speed /d;    }    /**     * move 炸弹移动     */    public void move(){          mPoint.x += dx;          mPoint.y += dy;    }    /**     * 获取炸弹坐标点     * @return     */    public Point getPoint(){        return  mPoint;    }}

Boy

package com.example.luokexi.gameuidayone.domain;import android.content.Context;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Point;import com.example.luokexi.gameuidayone.R;/** * Created by Luokexi on 2017/7/1. */public class Boy extends Sprite {    public static final int MOVE_DOWN= 0;    public static final int MOVE_UP = 1;    public static final int MOVE_LEFT = 2;    public static final int MOVE_RIGHT = 3;    private Bomb bomb;    private int speed = 5;//男孩移动的速度    public Boy(Bitmap mDefaultBitmap, Point mPoint) {        super(mDefaultBitmap, mPoint);    }    /**     * 产生炸弹     * @return     * 目标点 targetPoint     */    public Bomb createBomb(Context cxt,Point targetPoint){        bomb = new Bomb(BitmapFactory.decodeResource(cxt.getResources(),                R.drawable.ic_bomb1),new Point(mPoint.x+100,mPoint.y+225),targetPoint);        return bomb;    }    /**     * 男孩移动     * @param direction     */    public void move(int direction){        switch (direction){            case MOVE_DOWN:                mPoint.y += speed;                break;            default:                break;        }    }}

MyButton

package com.example.luokexi.gameuidayone.domain;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Point;import android.graphics.Rect;import java.util.Timer;import java.util.TimerTask;/** * Created by Luokexi on 2017/7/1. */public class MyButton extends Sprite {    private boolean isClick;//标记按钮是否被点击    private Bitmap mPressBitMap;//被点击后的图片    private Timer timer;//定时器一点一点走    public MyButton(Bitmap mDefaultBitmap, Bitmap mPressBitMap,Point mPoint) {        super(mDefaultBitmap, mPoint);        this.mPressBitMap = mPressBitMap;    }    /**     * 判断按钮是否被点击     * @param point     * @return     */    public boolean isClick(Point point){        //获取按钮所在的矩形区域        Rect rect = new Rect(mPoint.x,mPoint.y,mPoint.x                + mDefaultBitmap.getWidth(), mPoint.y                + mDefaultBitmap.getHeight());         isClick = rect.contains(point.x,point.y);                if (isClick){                    if (clickListener != null){                        //启动一个定时器,当按住按钮不放时小人可以一直持续移动                        timer = new Timer();                        timer.schedule(new TimerTask() {                            @Override                            public void run() {                                clickListener.click();                            }                        },0,200);                    }                }        return isClick;    }    private ClickListener clickListener;    //设置按钮点击监听    public void setClickListener(ClickListener clickListener){        this.clickListener = clickListener;    }    /**     *   按钮点击的回调接口     */    public interface ClickListener{            public void click();    }    public void setClick(boolean isClick){        this.isClick = isClick;        if (!isClick){            if (timer != null){                timer.cancel();//停止定时器            }        }    }    @Override    public void drawSelf(Canvas canvas) {        if(!isClick){            super.drawSelf(canvas);        }else {            //mPressBitMap 按钮被点击后的图片            canvas.drawBitmap(mPressBitMap,mPoint.x,mPoint.y,null);//绘制图片        }    }}

Sprite

package com.example.luokexi.gameuidayone.domain;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Point;/** * 精灵基类 * */public class Sprite {    public Bitmap mDefaultBitmap;    public Point mPoint;    public Sprite(Bitmap mDefaultBitmap, Point mPoint) {        this.mDefaultBitmap = mDefaultBitmap;        this.mPoint = mPoint;    }    public void drawSelf(Canvas canvas){        if (mDefaultBitmap != null) {            canvas.drawBitmap(mDefaultBitmap, mPoint.x, mPoint.y, null);//绘制图片        }    }}

res/drawable文件夹下的图片
boy.png
这里写图片描述

ic_bomb1.png

这里写图片描述

botttom.png

这里写图片描述

botttom_pass.png

这里写图片描述

案例实现

这里写图片描述

以上案例讲解请见 http://pan.baidu.com/s/1qYRqzpE

原创粉丝点击