初学者的漫步拾忆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
阅读全文
0 0
- 初学者的漫步拾忆SurfaceView
- 【tyvj1033】悠闲的漫步
- 【SurfaceView】SurfaceView的初步学习
- 漫步在致富的路上
- Tyvj P1033 悠闲的漫步
- SurfaceView--扩展SurfaceView的基础模版代码
- android的surfaceView介绍
- SurfaceView的学习
- SurfaceView的基本使用
- Android的SurfaceView使用
- SurfaceView的基本使用
- 初学Android的surfaceView
- SurfaceView的简单使用
- 关于SurfaceView的问题
- SurfaceView的基本使用
- SurfaceView的时间
- SurfaceView的学习01
- surfaceView的简单介绍
- css背景
- malloc、calloc、realloc的区别
- No python interpreter configured for the project
- #6029. 「雅礼集训 2017 Day1」市场--线段树区间更新
- ios-关于懒加载
- 初学者的漫步拾忆SurfaceView
- git初学
- aliyun阿里云Maven仓库地址——加速你的maven构建
- 关于The absolute uri: http://java.sun.com/jstl/core_rt cannot be resolved in either web.xml or the jar
- opencv人脸识别(c++)
- Zookeeper安装
- APUE第二章 Unix标准及实现
- bzoj 1064 假面舞会 图论??+dfs
- hibernate_核心配置和映射配置