最近用python写小游戏用到碰撞检测,矩形碰撞检测不够用了,简单加一个多边形碰撞检测,不好接物理引擎。自己写一个。
参考:https://blog.csdn.net/you_lan_hai/article/details/108429268
function satTest(shape1, shape2) return satTestHalf(shape1, shape2) and satTestHalf(shape2, shape1) end function satTestHalf(shape1, shape2) for edge in shape1的所有边 do axis = 获得edge的垂线 range1 = 将 shape1 的所有顶点投影到axis上,得到最大和最小值 range2 = 将 shape2 的所有顶点投影到axis上,得到最大和最小值 if range1 与 range2 无交集 then return 不相交 end end return 相交 end
伪代码写得好,直接翻译就行。原理也看得明白。
效果如下:
代码:
package {
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.TextField;
public class Main extends MovieClip {
public var tf: TextField;
public var p00: MovieClip;
public var p01: MovieClip;
public var p02: MovieClip;
public var p03: MovieClip;
public var p10: MovieClip;
public var p11: MovieClip;
public var p12: MovieClip;
public var p13: MovieClip;
public var pArr0: Array = [];
public var pArr1: Array = [];
public function Main() {
// constructor code
pArr0 = [p00, p01, p02, p03];
pArr1 = [p10, p11, p12, p13];
for (var i: int = 0; i < 4; i++ ) {
drag(pArr0[i]);
drag(pArr1[i]);
pArr0[i].tf.text = i;
pArr1[i].tf.text = i;
pArr0[i].mouseChildren = false;
pArr1[i].mouseChildren = false;
}
refresh();
addEventListener(Event.ENTER_FRAME, enterframeHandler);
}
private function enterframeHandler(e:Event):void
{
if (!draged) {
return;
}
refresh();
tf.text = checkCollision() ? "碰撞了" : "";
draged = false;
}
private function checkCollision(): Boolean {
return satTest(toPoints(pArr0), toPoints(pArr1));
}
private function toPoints(arr: Array): Array {
var result: Array = [];
for (var i: int = 0; i < arr.length; i++) {
result[i] = new Point(arr[i].x, arr[i].y);
}
return result;
}
private function drawAxis(axis: Array, color: uint): void {
var p0: Point = axis[0];
var p1: Point = getAxisPoint(axis, -1000);
var p2: Point = getAxisPoint(axis, 1000);
drawSeg(p1, p2, color, 0.5);
//drawPoint(p0, color);
//drawPoint(p1, color);
//drawPoint(p2, color);
}
private function drawSeg(p0: Point, p1: Point, color: uint, alpha: Number = 1.0): void {
graphics.lineStyle(1, color, alpha);
graphics.moveTo(p0.x, p0.y);
graphics.lineTo(p1.x, p1.y);
}
private function drawPoint(p: Point, color: uint): void {
graphics.lineStyle(1, color);
graphics.drawCircle(p.x, p.y, 5);
}
private function getAxisPoint(axis: Array, n: Number): Point {
var p0: Point = axis[0];
var p1: Point = axis[1];
return new Point(p0.x + (p1.x - p0.x) * n, p0.y + (p1.y - p0.y) * n);
}
private function drawAxisPoint(axis: Array, n: Number, color: uint): void {
var p2: Point = getAxisPoint(axis, n);
drawPoint(p2, color);
}
private function drawRange(axis: Array, range: Array, color: uint): void {
drawAxisPoint(axis, range[0], color);
drawAxisPoint(axis, range[1], color);
}
// https://blog.csdn.net/you_lan_hai/article/details/108429268
private function satTest(points0: Array, points1: Array): Boolean {
return satTestHalf(points0, points1) && satTestHalf(points1, points0);
}
private function satTestHalf(points0: Array, points1: Array): Boolean {
var n: Number = points0.length;
for (var i: int = 0; i < n; i++) {
var axis: Array = getAxis(points0[i], points0[(i + 1) % n]);
var range1 = getRange(axis[0], axis[1], points0);
var range2 = getRange(axis[0], axis[1], points1);
drawAxis(axis, 0x0000ff);
drawRange(axis, range1, 0x00ff00);
drawRange(axis, range1, 0xff0000);
if (!intersection(range1[0], range1[1], range2[0], range2[1])) {
return false;
}
}
return true;
}
private function getAxis(p0: Point, p1: Point): Array {
var p2: Point = new Point((p0.x + p1.x) / 2, (p0.y + p1.y) / 2);
var p3: Point = new Point(-(p0.y - p1.y), p0.x - p1.x);
p3.normalize(1);
return [p2, add(p2, p3)];
}
private function middle(p0: Point, p1: Point): Point {
return new Point((p0.x + p1.x) / 2, (p0.y + p1.y) / 2);
}
private function add(p0: Point, p1: Point): Point {
return new Point(p0.x + p1.x, p0.y + p1.y);
}
private function subtract(p0: Point, p1: Point): Point {
return new Point(p0.x - p1.x, p0.y - p1.y);
}
private function getRange(p0: Point, p1: Point, points: Array): Array {
var max: Number = -Infinity;
var min: Number = Infinity;
var v: Point = subtract(p1, p0);
for (var i: int = 0; i < points.length; i++ ) {
var p: Point = points[i];
var n: Number = dot(v, subtract(p, p0));
if (n < min) {
min = n;
}
if (n > max) {
max = n;
}
}
return [min, max];
}
private function dot(p0: Point, p1: Point): Number {
return p0.x * p1.x + p0.y * p1.y;
}
private function intersection(n0: Number, n1: Number, n2: Number, n3: Number): Boolean {
if (n1 < n2 || n3 < n0) {
return false;
}
return true;
}
private function refresh(): void {
graphics.clear();
draw(graphics, pArr0, 0x00ff00);
draw(graphics, pArr1, 0xff0000);
}
private function draw(gra: Graphics, arr: Array, co: uint): void {
gra.lineStyle(1, co);
gra.moveTo(arr[0].x, arr[0].y);
for (var i: int = 1; i < arr.length; i++ ) {
gra.lineTo(arr[i].x, arr[i].y);
}
gra.lineTo(arr[0].x, arr[0].y);
}
//-----------------------------
private var curSp:Sprite;
private var draged:Boolean = false;
private function drag(sp:Sprite):void
{
sp.buttonMode = true;
sp.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
private function mouseDownHandler(e:MouseEvent):void
{
curSp = e.currentTarget as Sprite;
curSp.startDrag();
addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
addEventListener(Event.MOUSE_LEAVE, mouseUpHandler);
}
private function mouseUpHandler(e:MouseEvent):void
{
curSp.stopDrag();
curSp = null;
removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
removeEventListener(Event.MOUSE_LEAVE, mouseUpHandler);
}
private function mouseMoveHandler(e:MouseEvent):void
{
//
draged = true;
}
}
}
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。