android随机小球碰撞

  • 1. 通过自定义View绘制小球
  • 2. 定时更新小球位置,让小球运动
  • 3. 边界检测,小球碰撞到布局边界时更改小球运动方向
  • 4. GitHubDemo
  • 5. 相关链接

1. 通过自定义View绘制小球

创建Ball类,封装与小球有关的属性元素
在构造方法中随机生成0-360的方向值

package com.pcf.randomball.bean;import java.util.HashMap;
import java.util.Random;public class Ball {int radius;//半径大小  单位pxint color;//色值int alpha;//透明度int x;//圆心x坐标int y;//圆心y坐标int degree;//方向int speed//速度 1-3int axisX;//X轴矢量方向值int axisY;//Y轴矢量方向值public Ball() {//生成一个在0-360范围内的随机数 为小球的方向this.degree = new Random().nextInt(360);//生成一个在1-3范围内的随机数 为小球的速度this.speed = new Random().nextInt(3)+1;}public Ball(int radius, int color, int alpha, int x, int y) {this.radius = radius;this.color = color;this.alpha = alpha;this.x = x;this.y = y;//生成一个在0-360范围内的随机数 为小球的方向this.degree = new Random().nextInt(360);//生成一个在1-3范围内的随机数 为小球的速度this.speed = new Random().nextInt(3)+1;if (degree == 0) {axisX = 0;axisY = 1;} else if (degree == 90) {axisX = 1;axisY = 0;} else if (degree == 180) {axisX = 0;axisY = -1;} else if (degree == 270) {axisX = -1;axisY = 0;} else if (degree > 0 && degree < 90) {axisX = 1;axisY = 1;} else if (degree > 90 && degree < 180) {axisX = 1;axisY = -1;} else if (degree > 180 && degree < 270) {axisX = -1;axisY = -1;} else if (degree > 270 && degree < 360) {axisX = -1;axisY = 1;}}public int getRadius() {return radius;}public void setRadius(int radius) {this.radius = radius;}public int getColor() {return color;}public void setColor(int color) {this.color = color;}public int getAlpha() {return alpha;}public void setAlpha(int alpha) {this.alpha = alpha;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public int getDegree() {return degree;}public void setDegree(int degree) {this.degree = degree;}public long getSpeed() {return speed;}public void setSpeed(long speed) {this.speed = speed;}public int getAxisX() {return axisX;}public void setAxisX(int axisX) {this.axisX = axisX;}public int getAxisY() {return axisY;}public void setAxisY(int axisY) {this.axisY = axisY;}
}

创建自定义RandomView类继承自View类
实现构造方法与OnDraw OnLayout OnMeasure方法
在OnLayout方法中获取控件实际宽高
在OnDraw方法里绘制圆形小球

package com.pcf.randomball.bean;import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
/*** 随机小球View* */
public class RandomView extends View {public RandomView(Context context) {super(context);}public RandomView(Context context, AttributeSet attrs) {super(context, attrs);}public RandomView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public RandomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Ball ball = new Ball(50, Color.BLUE, 600, width / 2, height / 2)//实例化画笔对象Paint paint = new Paint();//给画笔设置颜色paint.setColor(ball.getColor());paint.setAlpha(ball.getAlpha());//设置画笔属性paint.setStyle(Paint.Style.FILL);//画笔属性是实心paint.setStrokeWidth(1);//设置画笔粗细/**四个参数:* 参数一:圆心的x坐标* 参数二:圆心的y坐标* 参数三:圆的半径* 参数四:定义好的画笔**/canvas.drawCircle(ball.getX(), ball.getY(), ball.getRadius(), paint);}
}

2. 定时更新小球位置,让小球运动

在Ball类的构造方法里面,通过生成随机数0-360赋值运动方向


在直角坐标系中把0-360°分成四等份,均分在四个象限中
通过角度判断小球的运动方向,每个角限都是90°
无法直接对View进行斜线的移动
把斜线的移动分解成竖向与横向的移动
沿X轴的,Y轴的进行分解
把90°分成了10等份,并分解到X轴与Y轴
开启线程定时更新小球位置并重新绘制小球位置

PS:后面会把小球运动的方案改为以速度为基础

package com.pcf.randomball.view;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;import com.pcf.randomball.bean.Ball;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;public class RandomView extends View {private int height;private int width;private long maxBallNumber = -1;private List<Ball> ballList = new ArrayList();private String TAG = "RandomLayout";private MyThread thread;public RandomView(Context context) {super(context);}public RandomView(Context context, AttributeSet attrs) {super(context, attrs);}public RandomView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public RandomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);Log.d(TAG, "onMeasure ");width = getMeasuredWidth();height = getMeasuredHeight();Log.d(TAG, "width " + width);Log.d(TAG, "height " + height);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {Log.d(TAG, "onLayout ");ballList.add(new Ball(50, Color.BLUE, 600, width / 2, height / 2));//避免重复创建线程if (thread == null) {thread = new MyThread();}thread.start();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d(TAG, "onDraw ");for (int i = 0; i < ballList.size(); i++) {Ball ball = ballList.get(i);//实例化画笔对象Paint paint = new Paint();//给画笔设置颜色paint.setColor(ball.getColor());paint.setAlpha(ball.getAlpha());//设置画笔属性paint.setStyle(Paint.Style.FILL);//画笔属性是实心paint.setStrokeWidth(1);//设置画笔粗细/*四个参数:参数一:圆心的x坐标参数二:圆心的y坐标参数三:圆的半径参数四:定义好的画笔*/canvas.drawCircle(ball.getX(), ball.getY(), ball.getRadius(), paint);}}public long getMaxBallNumber() {return maxBallNumber;}public void setMaxBallNumber(long maxBallNumber) {this.maxBallNumber = maxBallNumber;}/*** 往布局添加小球*/public void addBall(Ball ball) {if (ball != null && ballList.size()<maxBallNumber) {ballList.add(ball);}}/*** 从布局移除小球*/public void removeBall(Ball ball) {if (ball != null)ballList.remove(ball);}public void actionBall() {for (int i = 0; i < ballList.size(); i++) {Ball ball1 = ballList.get(i);int x1 = ball1.getX();int y1 = ball1.getY();int degree = ball1.getDegree();//按照0-360度划分四个象限if (degree >= 0 && degree < 90) {//按10等份去分配X轴与Y轴的位移值int xL = degree / 9;int yL = 10 - degree / 9;//第一象限ball1.setX(x1 + xL);ball1.setY(y1 + yL);} else if (degree >= 90 && degree < 180) {//第二象限 碰撞到布局边界int xL = 10 - (degree / 9 - 10);int yL = (degree / 9 - 10);ball1.setX(x1 + xL);ball1.setY(y1 + yL);} else if (degree >= 180 && degree < 270) {//第三象限 碰撞到布局边界int xL = (degree / 9 - 20);int yL = 10 - (degree / 9 - 20);ball1.setX(x1 - xL);ball1.setY(y1 + yL);} else if (degree >= 270 && degree < 360) {//第四象限  碰撞到布局边界int xL = 10 - (degree / 9 - 30);int yL = (degree / 9 - 30);ball1.setX(x1 - xL);ball1.setY(y1 - yL);}}}private class MyThread extends Thread {@Overridepublic void run() {while (true) {actionBall();//通知更新界面,会重新调用onDraw()函数postInvalidate(); try {sleep(10);} catch (Exception e) {e.printStackTrace();}}}}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if(thread!=null)thread.stop();}
}

3. 边界检测,小球碰撞到布局边界时更改小球运动方向

根据入射角与反射角与平面夹角大小相等的原理
可以计算出在不同象限与边界碰撞后的运动方向

package com.pcf.randomball.view;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;import com.pcf.randomball.bean.Ball;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;public class RandomView extends View {private int height;private int width;private long maxBallNumber = -1;private List<Ball> ballList = new ArrayList();private String TAG = "RandomLayout";private MyThread thread;public RandomView(Context context) {super(context);}public RandomView(Context context, AttributeSet attrs) {super(context, attrs);}public RandomView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public RandomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);Log.d(TAG, "onMeasure ");width = getMeasuredWidth();height = getMeasuredHeight();Log.d(TAG, "width " + width);Log.d(TAG, "height " + height);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {Log.d(TAG, "onLayout ");ballList.add(new Ball(50, Color.BLUE, 600, width / 2, height / 2));//避免重复创建线程if (thread == null) {thread = new MyThread();}thread.start();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Log.d(TAG, "onDraw ");for (int i = 0; i < ballList.size(); i++) {Ball ball = ballList.get(i);//实例化画笔对象Paint paint = new Paint();//给画笔设置颜色paint.setColor(ball.getColor());paint.setAlpha(ball.getAlpha());//设置画笔属性paint.setStyle(Paint.Style.FILL);//画笔属性是实心paint.setStrokeWidth(1);//设置画笔粗细/*四个参数:参数一:圆心的x坐标参数二:圆心的y坐标参数三:圆的半径参数四:定义好的画笔*/canvas.drawCircle(ball.getX(), ball.getY(), ball.getRadius(), paint);}}public long getMaxBallNumber() {return maxBallNumber;}public void setMaxBallNumber(long maxBallNumber) {this.maxBallNumber = maxBallNumber;}/*** 往布局添加小球*/public void addBall(Ball ball) {if (ball != null && ballList.size()<maxBallNumber) {ballList.add(ball);}}/*** 从布局移除小球*/public void removeBall(Ball ball) {if (ball != null)ballList.remove(ball);}public void actionBall() {for (int i = 0; i < ballList.size(); i++) {Ball ball1 = ballList.get(i);int x1 = ball1.getX();int y1 = ball1.getY();int degree = ball1.getDegree();//按照0-360度划分四个象限if (degree >= 0 && degree < 90) {//按10等份去分配X轴与Y轴的位移值int xL = degree / 9;int yL = 10 - degree / 9;//第一象限 碰撞到布局右边界if (ball1.getX() + ball1.getRadius() >= width) {ball1.setDegree(360 - degree);ball1.setX(x1 - ball1.getRadius());} else {if (x1 + ball1.getRadius() + 1 + xL >= width) {ball1.setX(width - ball1.getRadius());} else {ball1.setX(x1 + 1 + xL);}}//碰撞到布局上边界if (ball1.getY() - ball1.getRadius() <= 0) {ball1.setDegree(180 - degree);ball1.setY(y1 + 1 + yL);} else {if (y1 - ball1.getRadius() - 1 - yL <= 0) {ball1.setY(ball1.getRadius());} else {ball1.setY(y1 - 1 - yL);}}} else if (degree >= 90 && degree < 180) {//第二象限 碰撞到布局边界int xL = 10 - (degree / 9 - 10);int yL = (degree / 9 - 10);if (ball1.getX() + ball1.getRadius() >= width) {ball1.setDegree(180 - degree + 180);ball1.setX(x1 - ball1.getRadius());} else {if (x1 + ball1.getRadius() + 1 + xL >= width) {ball1.setX(width - ball1.getRadius());} else {ball1.setX(x1 + 1 + xL);}}//碰撞到布局边界if (ball1.getY() + ball1.getRadius() >= height) {ball1.setDegree(90 - degree + 90);ball1.setY(y1 - 1 - yL);} else {if (y1 + ball1.getRadius() + 1 + yL >= height) {ball1.setY(height - ball1.getRadius());} else {ball1.setY(y1 + 1 + yL);}}} else if (degree >= 180 && degree < 270) {//第三象限 碰撞到布局边界int xL = (degree / 9 - 20);int yL = 10 - (degree / 9 - 20);if (ball1.getX() - ball1.getRadius() <= 0) {ball1.setDegree(360 - degree);ball1.setX(x1 + 1 + xL);} else {if (x1 - ball1.getRadius() - 1 - xL <= 0) {ball1.setX(ball1.getRadius());} else {ball1.setX(x1 - 1 - xL);}}//碰撞到布局边界if (ball1.getY() + ball1.getRadius() >= height) {ball1.setDegree(270 + 270 - degree);ball1.setY(y1 - 1 - yL);} else {if (x1 + ball1.getRadius() + 1 + yL >= height) {ball1.setY(height - ball1.getRadius());} else {ball1.setY(y1 + 1 + yL);}}} else if (degree >= 270 && degree < 360) {//第四象限  碰撞到布局边界int xL = 10 - (degree / 9 - 30);int yL = (degree / 9 - 30);if (ball1.getX() - ball1.getRadius() <= 0) {ball1.setDegree(360 - degree);ball1.setX(x1 + 1 + xL);} else {if (x1 - ball1.getRadius() - 1 - xL <= 0) {ball1.setX(ball1.getRadius());} else {ball1.setX(x1 - 1 - xL);}}//碰撞到布局边界if (ball1.getY() - ball1.getRadius() <= 0) {ball1.setDegree(360 - degree + 180);ball1.setY(y1 + 1 + yL);} else {if (y1 - ball1.getRadius() - 1 - yL <= 0) {ball1.setY(ball1.getRadius());} else {ball1.setY(y1 - 1 - yL);}}}}}private class MyThread extends Thread {@Overridepublic void run() {while (true) {actionBall();//通知更新界面,会重新调用onDraw()函数postInvalidate(); try {sleep(10);} catch (Exception e) {e.printStackTrace();}}}}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if(thread!=null)thread.stop();}
}

4. GitHubDemo

GitHubDemo
https://github.com/pengchengfuGit/randomball

5. 相关链接

https://www.cnblogs.com/xieyuan/archive/2012/11/27/3787450.html

android随机小球碰撞(一)边界检测相关推荐

  1. JS实现小球碰撞边界反弹-点击消失(详细解析实现思路)

    本篇文章给大家带来的是原生JS实现小球碰到边界就反弹,点击小球时小球被会销毁,并重新创建一个小球,让小球的数量一直保持在初始的数量,按照思路按步骤进行讲解,只需要源码的小伙伴可以定位到文本末尾直接复制 ...

  2. js 小球碰壁反弹and小球碰撞

    好像好几天没有更博了呢,最近有点变懒了,这样不好,不好~~我们要做热爱学习的好孩子,嘻嘻,今天下午补上... 我们在学习js的时候,一个很经典的案例就是小球的碰壁反弹效果啦~简单的小球碰壁效果可以慢慢 ...

  3. js小球碰撞js特效

    下载地址 小球碰撞特效.引用test.js文件.我目前做的是10个小球同时出现,你也可以根据你的需要进行修改.如果你想要小球随机出现的话,你只需要把58行的代码解注,然后57行的注释就行了.这个写法还 ...

  4. js实现多个小球碰撞

    实现思路:小球的移动,是通过改变小球的left和top值来改变,坐标分别为(x,y)当x/y值加到最大,即加到父级的宽度或者高度时,使x值或者y值减小,同理当x值或者y值减到最小时,同样的使x值或者y ...

  5. 用Xamarin 实现园友的 :Android浮动小球与开机自启动

    原文:用Xamarin 实现园友的 :Android浮动小球与开机自启动 前两天看园子里有筒子写了个 Android浮动小球与开机自启动  , 感觉这种被 360 玩烂的功能原来是如此的简单啊... ...

  6. android落下动画,Android应用开发android 购物车小球掉落动画

    本文将带你了解Android应用开发android 购物车小球掉落动画,希望本文对大家学Android有所帮助. 先贴效果图 对自定义View小红球的绘制 public class BallView ...

  7. pygame动画演示小球碰撞

    使用pygame实现动量定理的小球碰撞演示动画 动量定理我们在高中的时候就已经接触过了,是十分重要的物理定理.其中的完全弹性碰撞(机械能守恒)是十分典型的例子,机械能守恒和动量定理两个公式就可以推出小 ...

  8. 一个与小球碰撞有关的有趣问题

    -一个与小球碰撞有关的问题 -本人学号:16340300 -本人学院:数据科学与计算机学院 目录 看看这个问题 如何解决 解法 看看这个问题 如图,在光滑水平面上,有一个球A向墙运动,速度垂直于墙面, ...

  9. Canvas+Js制作动量守恒的小球碰撞

    目的:通过js实现小球碰撞并实现动量守恒 canvas我们就不多说了,有用着呢. 我们可以通过canvas画2D图形(圆.方块.三角形等等)3D图形(球体.正方体等待). 当然这只是基础的皮毛而已,c ...

  10. Java反弹球两球相撞_java实现小球碰撞反弹

    java实现小球碰撞反弹 java实现小球碰撞反弹 首先我们要在一个窗口里面显示这个功能,因此引入JFrame类然后创建一个窗口代码如下: JFrame win=new JFrame();//新建窗口 ...

最新文章

  1. Brian Kelly:比特币现金发展基金是大利好,现在正是买入时机
  2. wpf 加载html页面,使用MVVM在WPF中显示HTML
  3. dfs时间复杂度_一文吃透时间复杂度和空间复杂度
  4. Hibernate持久化对象的状态:瞬时状态、持久化状态、托管状态
  5. 用C#实现对Oracle 存储过程/函数/包的调试(附源代码)
  6. Sequelize小记
  7. 耐克为何不接受加密货币付款?
  8. 读完《Effective Java》后我淦了 50 条开发技巧
  9. 四层与七层负载均衡的比较
  10. 五个转义气符html,【转】前端开发攻城师绝对不可忽视的五个HTML5新特性
  11. Spring Security:自动登录(降低安全风险)
  12. 哪个表示经度?哪个表示纬度?是X是经度?还是Y表示经度?
  13. ue4 rpc php,UE4 Run On owing Client解析(RPC测试)
  14. 量化投资学习——对于中性化的理解
  15. css3 呼吸的莲花_CSS3 莲花盛开动画
  16. 关于C/C++读写64位内存的实例笔记
  17. rtl8811au黑苹果10.15_黑苹果macOS系统外接显示器也能在系统上调节亮度
  18. 线控加速踏板安全设计
  19. 最好用的ssh连接工具 - mobaxterm
  20. SIT1040T,芯力特CAN接口芯片,参数描述,完美替代TJA1040

热门文章

  1. 桌面小工具天气连接不到服务器,为什么Windows 7的系统里的天气小工具显示没法连接到服务?...
  2. DLL注入——使用远程线程
  3. 小规模零申报完整报税流程
  4. 各大市场应用上架整理
  5. div+js写弹出框
  6. FGSM攻击机器学习模型
  7. 基于DWM1000的stm32f103c8测距调试(一)
  8. Norton Ghost V12
  9. java设计模式(创建型)之生成器模式
  10. webuploader java版本