生活随笔
收集整理的這篇文章主要介紹了
android随机小球碰撞(一)边界检测
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
android隨機小球碰撞
- 1. 通過自定義View繪制小球
- 2. 定時更新小球位置,讓小球運動
- 3. 邊界檢測,小球碰撞到布局邊界時更改小球運動方向
- 4. GitHubDemo
- 5. 相關(guān)鏈接
1. 通過自定義View繪制小球
創(chuàng)建Ball類,封裝與小球有關(guān)的屬性元素
在構(gòu)造方法中隨機生成0-360的方向值
package com
.pcf
.randomball
.bean
;import java
.util
.HashMap
;
import java
.util
.Random
;public class Ball {int radius
;int color
;int alpha
;int x
;int y
;int degree
;int speed
int axisX
;int axisY
;public Ball() {this.degree
= new Random().nextInt(360);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
;this.degree
= new Random().nextInt(360);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類
實現(xiàn)構(gòu)造方法與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
;
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);canvas
.drawCircle(ball
.getX(), ball
.getY(), ball
.getRadius(), paint
);}
}
2. 定時更新小球位置,讓小球運動
在Ball類的構(gòu)造方法里面,通過生成隨機數(shù)0-360賦值運動方向
在直角坐標系中把0-360°分成四等份,均分在四個象限中
通過角度判斷小球的運動方向,每個角限都是90°
無法直接對View進行斜線的移動
把斜線的移動分解成豎向與橫向的移動
沿X軸的,Y軸的進行分解
把90°分成了10等份,并分解到X軸與Y軸
開啟線程定時更新小球位置并重新繪制小球位置
PS:后面會把小球運動的方案改為以速度為基礎(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));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);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();if (degree
>= 0 && degree
< 90) {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();postInvalidate(); try {sleep(10);} catch (Exception e
) {e
.printStackTrace();}}}}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if(thread
!=null
)thread
.stop();}
}
3. 邊界檢測,小球碰撞到布局邊界時更改小球運動方向
根據(jù)入射角與反射角與平面夾角大小相等的原理
可以計算出在不同象限與邊界碰撞后的運動方向
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);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();if (degree
>= 0 && degree
< 90) {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();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随机小球碰撞(一)边界检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。