最近用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; } } }
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。