碰撞算法
圆形与矩形碰撞算法分析
https://blog.csdn.net/arv002/article/details/118501407
2D游戏中的碰撞检测:圆形与矩形碰撞检测
https://www.cnblogs.com/jiangxiaobo/p/5949904.html
点和矩形碰撞
/**
*
* @param x1 点
* @param y1 点
* @param x2 矩形view x
* @param y2 矩形view y
* @param w 矩形view 宽
* @param h 矩形view 高
* @return
*/
public static boolean isCollision(int x1, int y1, int x2, int y2, int w, int h) {
if (x1 >= x2 && x1 <= x2 + w && y1 >= y2 && y1 <= y2 + h) {
return true;
}
return false;
}
矩形碰撞
/**
* 检测两个矩形是否碰撞
* @return
*/
public boolean isCollisionWithRect(int x1, int y1, int w1, int h1,
int x2,int y2, int w2, int h2) {
if (x1 >= x2 && x1 >= x2 + w2) {
return false;
} else if (x1 <= x2 && x1 + w1 <= x2) {
return false;
} else if (y1 >= y2 && y1 >= y2 + h2) {
return false;
} else if (y1 <= y2 && y1 + h1 <= y2) {
return false;
}
return true;
}
点(x1,x2) , 圆心(x2,y2) ,半径r
if (Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) <= r) {
// 如果点和圆心距离小于或等于半径则认为发生碰撞
return true;
}
圆和圆
/**
* 圆形碰撞
*
* @param x1
* 圆形1的圆心X坐标
* @param y1
* 圆形2的圆心X坐标
* @param x2
* 圆形1的圆心Y坐标
* @param y2
* 圆形2的圆心Y坐标
* @param r1
* 圆形1的半径
* @param r2
* 圆形2的半径
* @return
*/
private boolean isCollisionWithCircle(int x1, int y1, int x2, int y2,
int r1, int r2) {
// Math.sqrt:开平方
// Math.pow(double x, double y): X的Y次方
//直角坐标系,依点1和点2做平行线,|x1-x2|为横向直角边,|y1-y2|为纵向直角边 依勾股定理 c^2=a^2+b^2
if (Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) <= r1 + r2) {
// 如果两圆的圆心距小于或等于两圆半径和则认为发生碰撞
return true;
}
return false;
}
算法笔记
案例:跟随鼠标碰撞变色
import React, { Component } from 'react';
class App2 extends Component {
state = {
list: [
{ x: 200, y: 100, w: 100, h: 100, c: "red" },
{ x: 400, y: 200, w: 100, h: 100, c: "blue" },
]
}
changeMove = (e) => {
// 获取状态
let temp = this.state.list
// 0跟随鼠标
temp[1].x = e.clientX - temp[1].w / 2
temp[1].y = e.clientY - temp[1].h / 2
// 方框 碰到 方框 就变色 算法一
// if (this.box_in_box_way1(temp[0], temp[1])) {
// temp[0].c = 'red'
// } else (temp[0].c = 'blue')
// 方框 碰到 方框 就变色 算法二
// if (this.box_in_box_way2(temp[0], temp[1])) {
// temp[0].c = 'red'
// } else (temp[0].c = 'blue')
// 点是否在圆里
// let dot = { x: temp[1].x, y: temp[1].y }
// let circle = {
// x: temp[0].x + temp[0].w / 2,
// y: temp[0].y + temp[0].w / 2,
// r: temp[0].w / 2,
// }
// if (this.dot_in_circle(dot, circle)) {
// temp[0].c = 'blue'
// } else (temp[0].c = 'red')
// 方框 碰撞 园 ---未完成
if (this.box_in_circle(temp[1], temp[0])) {
temp[0].c = 'blue'
} else (temp[0].c = 'red')
// 更新状态
this.setState({ list: temp })
}
// 方框 是否 碰到 方框 算法一
box_in_box_way1 = (box1, box) => {
let dot_1 = { x: box1.x, y: box1.y, }
let dot_2 = { x: box1.x + box1.w, y: box1.y, }
let dot_3 = { x: box1.x, y: box1.y + box1.h, }
let dot_4 = { x: box1.x + box1.w, y: box1.y + box1.h, }
if (this.dot_in_box(dot_1, box) || this.dot_in_box(dot_2, box) || this.dot_in_box(dot_3, box) || this.dot_in_box(dot_4, box)) {
return true
} else {
return false
}
}
// 方框 是否碰到 方框 算法二
box_in_box_way2 = (box, obj) => {
if (obj.x + obj.w < box.x || obj.x > box.x + box.w || obj.y + obj.h < box.y || obj.y > box.y + box.h) {
return false
} else {
return true
}
}
// 点是否在方框里
dot_in_box = (dot, box) => {
if (box.x < dot.x && dot.x < (box.x + box.w) && box.y < dot.y && dot.y < (box.y + box.h)) {
return true
} else {
return false
}
}
// 方框 是否碰到 圆 -----未完成
box_in_circle = (box, circle) => {
let temp_circle = {
x: circle.x + circle.w / 2,
y: circle.y + circle.w / 2,
r: circle.w / 2,
}
let dot_list = [
{ x: box.x, y: box.y, },
{ x: box.x + box.w, y: box.y, },
{ x: box.x, y: box.y + box.h, },
{ x: box.x + box.w, y: box.y + box.h, },
]
let a = 0
if (this.box_in_box_way2(box, circle)) {
for (let i in dot_list) {
a += this.dot_in_box(dot_list[i], temp_circle)
}
}
return a
}
// 点是否在圆里
dot_in_circle = (dot, circle) => {
if (Math.sqrt(Math.pow((circle.x - dot.x), 2) + Math.pow((circle.y - dot.y), 2)) < circle.r) {
return true
}
else { return false }
}
// 组件加载完成时
componentDidMount() {
window.addEventListener('mousemove', this.changeMove)
}
// 组件渲染
render() {
return (
<div>
<div style={{
position: 'absolute',
left: `${this.state.list[0].x}px`,
top: `${this.state.list[0].y}px`,
width: `${this.state.list[0].w}px`,
height: `${this.state.list[0].h}px`,
backgroundColor: this.state.list[0].c,
borderRadius: '50%',
}}></div>
<div style={{
position: 'absolute',
left: `${this.state.list[1].x}px`,
top: `${this.state.list[1].y}px`,
width: `${this.state.list[1].w}px`,
height: `${this.state.list[1].h}px`,
backgroundColor: this.state.list[1].c,
}}></div>
</div>
);
}
}
export default App2;