public static void PutBallToThePoint(PoolBall ball, ref Vector3 p) { float r = ball.GetRadius(); while (Physics.OverlapSphere(p, r, 1 << LayerMask.NameToLayer("Ball") | 1 << LayerMask.NameToLayer("WhiteBall")).Length != 0) { p.x -= r; } SupportTools.SetPosition(ball.gameObject, p, SupportTools.AxisIgnore.IgnoreY, true); p.x -= r; }
private float GetPlacedSpace(PoolBall ball, Vector3 dir) { ball.collider.enabled = false; ball.rigidbody.isKinematic = true; RaycastHit hit; float space = 0; if (Physics.SphereCast(ball.transform.position, ball.GetRadius(), dir, out hit, ConstantData.OulineAndBallLayer)) { space = (hit.transform.position - ball.transform.position).magnitude * .5f; } ball.collider.enabled = true; ball.rigidbody.isKinematic = false; return(space); }
private bool CheckObastacleBetweenBallAndPocket(PoolBall originBall, PocketTrigger pocket) { Vector3 dir = pocket.pointerPosition - originBall.transform.position; RaycastHit[] hit = Physics.SphereCastAll(originBall.transform.position, originBall.GetRadius(), dir, dir.magnitude, ConstantData.OulineAndBallLayer); foreach (RaycastHit h in hit) { //Debug.Log("Obastacle between " + originBall.name + " and " + pocket.name + " : " + h.transform.name); if (h.collider.name.CompareTo(originBall.name) != 0) { return(true); } } return(false); }
private float GetPlacedSpace(PoolBall ball, Vector3 dir) { ball.collider.enabled = false; ball.rigidbody.isKinematic = true; RaycastHit hit; float space = 0; if (Physics.SphereCast(ball.transform.position, ball.GetRadius(), dir, out hit, ConstantData.OulineAndBallLayer)) { space = (hit.transform.position - ball.transform.position).magnitude * .5f; } ball.collider.enabled = true; ball.rigidbody.isKinematic = false; return space; }
private Vector3 ConsiderHitPointWithDrag(Dictionary<PoolBall, List<PocketTrigger>> considerBalls, out Vector3 cueBallPosition, out PoolBall targetBall, out PocketTrigger targetTrigger) { Dictionary<PoolBall, PocketTrigger> optimalBalls = FilterTheBestPocketForEachBall(considerBalls); cueBallPosition = Vector3.zero; targetTrigger = null; targetBall = null; if(optimalBalls.Count == 0) { return Vector3.zero; } else { foreach (KeyValuePair<PoolBall, PocketTrigger> kvp in optimalBalls) { targetBall = kvp.Key; targetTrigger = kvp.Value; if (!targetTrigger) continue; Vector3 dir = targetBall.transform.position - targetTrigger.pointerPosition; //白球摆成和目标球和袋口一条直线 cueBallPosition = targetBall.transform.position + (dir.normalized * Mathf.Min(GetPlacedSpace(targetBall, targetBall.transform.position - targetTrigger.pointerPosition), 5 * targetBall.GetRadius())); //这里随机会跳出循环,代表随机取一个球的意思, optimalBalls.count 为了使概率平均 if (Random.Range(1, optimalBalls.Count) == 1) break; } if (!targetTrigger) { return Vector3.zero; } return ConsiderHitPoint(targetBall, targetTrigger); } }
private Vector3 ConsiderHitPoint(PoolBall ball, PocketTrigger trigger) { Vector3 vec = ball.transform.position - trigger.pointerPosition; return ball.transform.position + vec.normalized * ball.GetRadius() * 2; }
private bool CheckObastacleBetweenBallAndPocket(PoolBall originBall, PocketTrigger pocket) { Vector3 dir = pocket.pointerPosition - originBall.transform.position; RaycastHit[] hit = Physics.SphereCastAll(originBall.transform.position, originBall.GetRadius(), dir, dir.magnitude, ConstantData.OulineAndBallLayer); foreach (RaycastHit h in hit) { //Debug.Log("Obastacle between " + originBall.name + " and " + pocket.name + " : " + h.transform.name); if (h.collider.name.CompareTo(originBall.name) != 0) return true; } return false; }
private List <KeyValuePair <PoolBall, Vector3> > GetShootableBalls() { List <KeyValuePair <PoolBall, Vector3> > shootableBalls = new List <KeyValuePair <PoolBall, Vector3> >(); Vector3 cueBallPosition = Pools.CueBall.GetPosition(); for (int i = 0; i < cMsg.ballList.Count; i++) { PoolBall ball = cMsg.ballList[i]; Vector3 hitPoint = Vector3.zero; if (ball.BallState != PoolBall.State.IDLE) { continue; } //求出dir的2条Y坐标为0的垂直向量, 得到目标球正对于白球的左侧和右侧的击球点,判断白球是否能击中 2个点或者白球中心的点的其中一个 Vector3 dir = ball.transform.position - cueBallPosition; Vector2[] perpendicularVectors = MathTools.PerpendicularVector2D(new Vector2(dir.x, dir.z)); Vector3[] point3 = new Vector3[] { ball.transform.position, ball.transform.position + new Vector3(perpendicularVectors[0].x, 0, perpendicularVectors[0].y) * ball.GetRadius(), ball.transform.position + new Vector3(perpendicularVectors[1].x, 0, perpendicularVectors[1].y) * ball.GetRadius() }; for (int j = 0; j < point3.Length; j++) { hitPoint = point3[j]; if (!CheckObastacleBetweenTargetPositionAndCueball(ball, hitPoint, cueBallPosition)) { shootableBalls.Add(new KeyValuePair <PoolBall, Vector3>(ball, hitPoint)); break; } } } return(shootableBalls); }
private Vector3 ConsiderHitPoint(PoolBall ball, PocketTrigger trigger) { Vector3 vec = ball.transform.position - trigger.pointerPosition; return(ball.transform.position + vec.normalized * ball.GetRadius() * 2); }
private Dictionary <PoolBall, PocketTrigger> FilterTheBestPocketForEachBall(Dictionary <PoolBall, List <PocketTrigger> > considerBalls) { Dictionary <PoolBall, PocketTrigger> optimalBalls = new Dictionary <PoolBall, PocketTrigger>(); foreach (var v in considerBalls) { PoolBall ball = v.Key; float bestDistance = float.MaxValue; PocketTrigger bestPocket = null; for (int i = 0, count = v.Value.Count; i < count; i++) { PocketTrigger pocket = v.Value[i]; if (GetPlacedSpace(ball, ball.transform.position - pocket.pointerPosition) < ball.GetRadius() * 2) { continue; } float distance = Vector3.Distance(ball.transform.position, pocket.pointerPosition); if (distance < bestDistance) { bestPocket = pocket; bestDistance = distance; } } optimalBalls.Add(ball, bestPocket); } return(optimalBalls); }
private Vector3 ConsiderHitPointWithDrag(Dictionary <PoolBall, List <PocketTrigger> > considerBalls, out Vector3 cueBallPosition, out PoolBall targetBall, out PocketTrigger targetTrigger) { Dictionary <PoolBall, PocketTrigger> optimalBalls = FilterTheBestPocketForEachBall(considerBalls); cueBallPosition = Vector3.zero; targetTrigger = null; targetBall = null; if (optimalBalls.Count == 0) { return(Vector3.zero); } else { foreach (KeyValuePair <PoolBall, PocketTrigger> kvp in optimalBalls) { targetBall = kvp.Key; targetTrigger = kvp.Value; if (!targetTrigger) { continue; } Vector3 dir = targetBall.transform.position - targetTrigger.pointerPosition; //白球摆成和目标球和袋口一条直线 cueBallPosition = targetBall.transform.position + (dir.normalized * Mathf.Min(GetPlacedSpace(targetBall, targetBall.transform.position - targetTrigger.pointerPosition), 5 * targetBall.GetRadius())); //这里随机会跳出循环,代表随机取一个球的意思, optimalBalls.count 为了使概率平均 if (Random.Range(1, optimalBalls.Count) == 1) { break; } } if (!targetTrigger) { return(Vector3.zero); } return(ConsiderHitPoint(targetBall, targetTrigger)); } }