日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android随机小球碰撞(一)边界检测

發(fā)布時(shí)間:2024/8/1 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android随机小球碰撞(一)边界检测 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

android隨機(jī)小球碰撞

    • 1. 通過自定義View繪制小球
    • 2. 定時(shí)更新小球位置,讓小球運(yùn)動(dòng)
    • 3. 邊界檢測(cè),小球碰撞到布局邊界時(shí)更改小球運(yùn)動(dòng)方向
    • 4. GitHubDemo
    • 5. 相關(guān)鏈接

1. 通過自定義View繪制小球

創(chuàng)建Ball類,封裝與小球有關(guān)的屬性元素
在構(gòu)造方法中隨機(jī)生成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坐標(biāo)int y;//圓心y坐標(biāo)int degree;//方向int speed//速度 1-3int axisX;//X軸矢量方向值int axisY;//Y軸矢量方向值public Ball() {//生成一個(gè)在0-360范圍內(nèi)的隨機(jī)數(shù) 為小球的方向this.degree = new Random().nextInt(360);//生成一個(gè)在1-3范圍內(nèi)的隨機(jī)數(shù) 為小球的速度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;//生成一個(gè)在0-360范圍內(nèi)的隨機(jī)數(shù) 為小球的方向this.degree = new Random().nextInt(360);//生成一個(gè)在1-3范圍內(nèi)的隨機(jī)數(shù) 為小球的速度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;} }

創(chuàng)建自定義RandomView類繼承自View類
實(shí)現(xiàn)構(gòu)造方法與OnDraw OnLayout OnMeasure方法
在OnLayout方法中獲取控件實(shí)際寬高
在OnDraw方法里繪制圓形小球

package com.pcf.randomball.bean;import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; /*** 隨機(jī)小球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)//實(shí)例化畫筆對(duì)象Paint paint = new Paint();//給畫筆設(shè)置顏色paint.setColor(ball.getColor());paint.setAlpha(ball.getAlpha());//設(shè)置畫筆屬性paint.setStyle(Paint.Style.FILL);//畫筆屬性是實(shí)心paint.setStrokeWidth(1);//設(shè)置畫筆粗細(xì)/**四個(gè)參數(shù):* 參數(shù)一:圓心的x坐標(biāo)* 參數(shù)二:圓心的y坐標(biāo)* 參數(shù)三:圓的半徑* 參數(shù)四:定義好的畫筆**/canvas.drawCircle(ball.getX(), ball.getY(), ball.getRadius(), paint);} }

2. 定時(shí)更新小球位置,讓小球運(yùn)動(dòng)

在Ball類的構(gòu)造方法里面,通過生成隨機(jī)數(shù)0-360賦值運(yùn)動(dòng)方向


在直角坐標(biāo)系中把0-360°分成四等份,均分在四個(gè)象限中
通過角度判斷小球的運(yùn)動(dòng)方向,每個(gè)角限都是90°
無法直接對(duì)View進(jìn)行斜線的移動(dòng)
把斜線的移動(dòng)分解成豎向與橫向的移動(dòng)
沿X軸的,Y軸的進(jìn)行分解
把90°分成了10等份,并分解到X軸與Y軸
開啟線程定時(shí)更新小球位置并重新繪制小球位置

PS:后面會(huì)把小球運(yùn)動(dòng)的方案改為以速度為基礎(chǔ)

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));//避免重復(fù)創(chuàng)建線程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);//實(shí)例化畫筆對(duì)象Paint paint = new Paint();//給畫筆設(shè)置顏色paint.setColor(ball.getColor());paint.setAlpha(ball.getAlpha());//設(shè)置畫筆屬性paint.setStyle(Paint.Style.FILL);//畫筆屬性是實(shí)心paint.setStrokeWidth(1);//設(shè)置畫筆粗細(xì)/*四個(gè)參數(shù):參數(shù)一:圓心的x坐標(biāo)參數(shù)二:圓心的y坐標(biāo)參數(shù)三:圓的半徑參數(shù)四:定義好的畫筆*/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度劃分四個(gè)象限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();//通知更新界面,會(huì)重新調(diào)用onDraw()函數(shù)postInvalidate(); try {sleep(10);} catch (Exception e) {e.printStackTrace();}}}}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if(thread!=null)thread.stop();} }

3. 邊界檢測(cè),小球碰撞到布局邊界時(shí)更改小球運(yùn)動(dòng)方向

根據(jù)入射角與反射角與平面夾角大小相等的原理
可以計(jì)算出在不同象限與邊界碰撞后的運(yùn)動(dòng)方向

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));//避免重復(fù)創(chuàng)建線程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);//實(shí)例化畫筆對(duì)象Paint paint = new Paint();//給畫筆設(shè)置顏色paint.setColor(ball.getColor());paint.setAlpha(ball.getAlpha());//設(shè)置畫筆屬性paint.setStyle(Paint.Style.FILL);//畫筆屬性是實(shí)心paint.setStrokeWidth(1);//設(shè)置畫筆粗細(xì)/*四個(gè)參數(shù):參數(shù)一:圓心的x坐標(biāo)參數(shù)二:圓心的y坐標(biāo)參數(shù)三:圓的半徑參數(shù)四:定義好的畫筆*/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度劃分四個(gè)象限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();//通知更新界面,會(huì)重新調(diào)用onDraw()函數(shù)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. 相關(guān)鏈接

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

總結(jié)

以上是生活随笔為你收集整理的android随机小球碰撞(一)边界检测的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。