目录

1.假设当前市场价一只鸡10元,一只鸭12元5角。请写一个函数ShowPrice,输入参数分别为鸡和鸭的个数(非负整型),功能为显示出总价钱,精确到分。例如调用ShowPrice(5,10)后输出175.00。请注意程序的可读性和易于维护性。2.判断点与线的位置关系3.计算点在直线上的投影(向量投影)4.判断多边形是否为凸多边形5.判断线段与线段是否共线6.判断线段与线段是否重合(非相交)7.线段与线段是否相交8.计算直线与直线的交点9.射线与线段是否相交,以及交点10.点围绕另一点旋转指定角度11.点是否在任意多变内12.写一个计时器工具,从整点开始计时,格式为:00:00:0013.用鼠标实现在场景中拖动物体,用鼠标滚轮实现缩放14.写一个角色控制器,鼠标控制屏幕晃动,鼠标控制开枪。15.3D空间有三个cube当做点,有一条鱼的模型,要求在三点之间游动,要16.设计一款计时器(Timer)功能,拥有基础事件:开始计时、暂停计时,停止计时【计时器事件】

1.假设当前市场价一只鸡10元,一只鸭12元5角。请写一个函数ShowPrice,输入参数分别为鸡和鸭的个数(非负整型),功能为显示出总价钱,精确到分。例如调用ShowPrice(5,10)后输出175.00。请注意程序的可读性和易于维护性。

static void ShowPrice(int num_chicken, int num_duck) { float totalPrice = 0.00f; float price_chicken = 10f; float price_duck = 12.5f; totalPrice = num_chicken * price_chicken + num_duck * price_duck; Console.WriteLine(“总价钱为:{0:0.00}”, totalPrice); }

2.判断点与线的位置关系

已知点P(x,y),与直线上A(x1,y1),B(x2,y2)两点,通过向量AP与BP的叉乘返回的结果,即可确定点在直线的位置关系。 判断依据:1)等于0:点在直线上;2)小于0:点在直线的左侧;3)大于0:点在直线的右侧

///

/// 2D叉乘

///

public static float CrossProduct2D(Vector2 v1, Vector2 v2)

{

//叉乘运算公式 x1*y2 - x2*y1

return v1.x * v2.y - v2.x * v1.y;

}

///

/// 点与线的位置关系

///

/// ==0:点在线上 <0:点在线的左侧 >0:点在线的右侧

public static int IsPointToLinePosition(Vector2 point, Vector2 lineStart, Vector2 lineEnd)

{

float crossValue = CrossProduct2D(point - lineStart, lineEnd - lineStart);

if (crossValue < 0) return -1;

if (crossValue > 0) return 1;

return 0;

}

3.计算点在直线上的投影(向量投影)

已知点P(x,y),与直线上两点A(x1,y1),B(x2,2),求P点在直线AB上的投影 知识点:通过向量投影公式(点乘),即可获得点P在直线AB投影点。

///

/// 2D叉乘

///

public static float CrossProduct2D(Vector2 v1, Vector2 v2)

{

//叉乘运算公式 x1*y2 - x2*y1

return v1.x * v2.y - v2.x * v1.y;

}

///

/// 点是否在直线上

///

public static bool IsPointOnLine(Vector2 point, Vector2 lineStart, Vector2 lineEnd)

{

float value = CrossProduct2D(point - lineStart, lineEnd - lineStart);

return Mathf.Abs(value) < 0.0003 /* 使用 Mathf.Approximately(value,0) 方式,在斜线上好像无法趋近为0*/;

}

///

/// 点到直线上的投影坐标

///

public static Vector2 Point2LineProject(Vector2 point, Vector2 lineStart, Vector2 lineEnd)

{

if (IsPointOnLine(point, lineStart, lineEnd))

return point;

Vector2 v = point - lineStart;

Vector2 u = lineEnd - lineStart;

//求出长度

float u1Length = Vector2.Dot(u, v) / u.magnitude;

return u1Length * u.normalized + lineStart;

}

4.判断多边形是否为凸多边形

已知多边形的逆时针顶点序列,依次判断相邻两个线段走向是否一致即可。 (点与线段位置关系,因为规定为逆时针顶点序列,所以只要两个相邻线段的叉乘都小于0则该多边形为凸多边形)

///

/// 2D叉乘

///

public static float CrossProduct2D(Vector2 v1, Vector2 v2)

{

//叉乘运算公式 x1*y2 - x2*y1

return v1.x * v2.y - v2.x * v1.y;

}

///

/// 点与线的位置关系

///

/// ==0:点在线上 <0:点在线的左侧 >0:点在线的右侧

public static int IsPointToLinePosition(Vector2 point, Vector2 lineStart, Vector2 lineEnd)

{

float crossValue = CrossProduct2D(point - lineStart, lineEnd - lineStart);

if (crossValue < 0) return -1;

if (crossValue > 0) return 1;

return 0;

}

///

/// 是否为凸多边形

///

/// 逆时针点序列

public static bool IsConvexPolygon(List points)

{

//计算每个顶点的转向,如果有不一致的转向,则表示该多边形不是凸多边形

if (points.Count < 3) return false;

bool isConvex = true;

for (int i = 1; i < points.Count; i++)

{

Vector2 point = points[i];

//上一个点

Vector2 point1 = points[i - 1];

//下一个点,如果超出当前点集合,则需要获取第一个点

int nextIndex = i + 1;

if (nextIndex >= points.Count) nextIndex = 0;

Vector2 point2 = points[nextIndex];

//计算朝向,因为点集合为逆时针点序列,如果点在线段右侧,则表示该角大于180 该多边形为凹多边形

float value = IsPointToLinePosition(point1, point, point2);

if (value > 0)

{

isConvex = false;

break;

}

}

return isConvex;

}

5.判断线段与线段是否共线

思路: 1)先判断两条线段是否平行,即两条线段的叉积等于0 2)在判断两条线段是否共线,即线段1一个点在线段2的延长线上

///

/// 线段与线段是否共线

///

public static bool IsSegmentCollineation(Vector2 segment1Start, Vector2 segment1End, Vector2 segment2Start,

Vector2 segment2End)

{

//1.判断两个向量是否平行

float value = CrossProduct2D(segment1End - segment1Start, segment2End - segment2Start);

if (Mathf.Abs(value) < 0.0003f)

{

// 平行,则判断一个线上的点是否在另一线上

if (IsPointOnLine(segment2Start, segment2End, segment2Start))

return true;

}

return false;

}

6.判断线段与线段是否重合(非相交)

1)判断两条线段必须共线 2)然后片段判断线段A的起终点是否在线段B,以及线段B的起终点,是否在线段A上,只要有一个条件成立,则可以认为两条线段是重合的 或 1)判断两条线段是否共线 2)对两条线段的4个定点进行排序,如果1,3 或 1,4 为为同一条线段上的点,则可以任务两条线段是否重合的

///

/// 线段与线段是否重合(全部重合或局部重合)

///

public static bool IsSegmentCoincide(Vector2 segment1Start, Vector2 segment1End, Vector2 segment2Start,

Vector2 segment2End)

{

//先判断两条线段是否在同一条线上

if (!IsSegmentCollineation(segment1Start, segment1End, segment2Start, segment2End))

return false;

//如果是相同的起终点

if (segment1Start == segment2Start && segment1End == segment2End) return true;

//判断检测点是否在另一条线段上

if (IsPointOnSegment2(segment1Start, segment2Start, segment2End) ||

IsPointOnSegment2(segment1End, segment2Start, segment2End) ||

IsPointOnSegment2(segment2Start, segment1Start, segment1End) ||

IsPointOnSegment2(segment2End, segment1Start, segment1End))

return true;

return false;

}

7.线段与线段是否相交

///

/// 线段是否相交

///

public static bool IsSegmentIntersect(Vector2 segment1Start, Vector2 segment1End, Vector2 segment2Start,

Vector2 segment2End)

{

//快速排斥实验

if (Mathf.Min(segment1Start.x, segment1End.x) <= Mathf.Max(segment2Start.x, segment2End.x)

&& Mathf.Min(segment2Start.x, segment2End.x) <= Mathf.Max(segment2Start.x, segment2End.x)

&& Mathf.Min(segment1Start.y, segment1End.y) <= Mathf.Max(segment2Start.y, segment2End.y)

&& Mathf.Min(segment2Start.y, segment2End.y) <= Mathf.Max(segment1Start.y, segment1End.y))

{

//先判断线段是否重合,重合,则认为也是相交

if (IsSegmentCoincide(segment1Start, segment1End, segment2Start, segment2End))

return true;

//互为跨立的判断 一线的点相对另一线的位置关系,左右 -1 1,之和为 0

int state = IsPointToLinePosition(segment1Start, segment2Start, segment2End) +

IsPointToLinePosition(segment1End, segment2Start, segment2End) +

IsPointToLinePosition(segment2Start, segment1Start, segment1End) +

IsPointToLinePosition(segment2End, segment1Start, segment1End);

if (state == 0) return true;

}

return false;

}

8.计算直线与直线的交点

///

/// 求直线的交点

///

public static Vector2 LineIntersectPoint(Vector2 line1Start, Vector2 line1End, Vector2 line2Start,

Vector2 line2End)

{

//两点式公式

//x0 = ((x3-x4) * (x2*y1 - x1*y2) - (x1-x2) * (x4*y3 - x3*y4)) / ((x3-x4) * (y1-y2) - (x1-x2) * (y3-y4));

//y0 = ((y3-y4) * (y2*x1 - y1*x2) - (y1-y2) * (y4*x3 - y3*x4)) / ((y3-y4) * (x1-x2) - (y1-y2) * (x3-x4));

float x1 = line1Start.x, x2 = line1End.x, x3 = line2Start.x, x4 = line2End.x;

float y1 = line1Start.y, y2 = line1End.y, y3 = line2Start.y, y4 = line2End.y;

Vector2 point = Vector2.zero;

point.x = ((x3 - x4) * (x2 * y1 - x1 * y2) - (x1 - x2) * (x4 * y3 - x3 * y4)) / ((x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4));

point.y = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / ((y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4));

return point;

}

9.射线与线段是否相交,以及交点

所在直线是否相交点是否在射线以及直线上

///

/// 射线与线段是否相交

///

public static bool IsRaySegmentIntersect(Vector2 rayStart, Vector2 rayDir, Vector2 segmentStart, Vector2 segmentEnd, out Vector2 point)

{

//先计算两条直线是否相交

if (!LineIntersectPoint(rayStart, rayStart + rayDir * 1, segmentStart, segmentEnd, out point))

return false;

//判断交点的位置是否在射线上 方向相同可以确定点在射线上

if (Vector2.Dot((point - rayStart).normalized, rayDir.normalized) < 0) return false;

//点是否在线段上

if (!IsPointOnSegment2(point, segmentStart, segmentEnd)) return false;

return true;

}

10.点围绕另一点旋转指定角度

///

/// 点绕另一个点进行旋转

///

public static Vector2 PointRoationOnPoint(Vector2 originPoint, Vector2 point, float angle)

{

if (originPoint == point) return originPoint;

Vector2 resultPoint = Vector2.zero;

Vector2 v = (point - originPoint).normalized;

angle *= Mathf.Deg2Rad;

resultPoint.x = v.x * Mathf.Cos(angle) - v.y * Mathf.Sin(angle);

resultPoint.y = v.x * Mathf.Sin(angle) + v.y * Mathf.Cos(angle);

return resultPoint * Vector2.Distance(originPoint, point) + originPoint;

}

///

/// 点集合绕点旋转

///

public static List PointsRoationOnPoint(List points, Vector2 point, float angle)

{

List resultPoints = new List();

if (points == null) return resultPoints;

for (int i = 0; i < points.Count; i++)

{

Vector2 nPoint = PointRoationOnPoint(point, points[i], angle);

resultPoints.Add(nPoint);

}

return resultPoints;

}

11.点是否在任意多变内

射线法:

求出多边形所在矩形,判断点是否在矩形内点是否在多边形顶点或边上以当前点做一条水平射线,计算该射线与多边形线段的相交数量,如果为奇数则点在多边形内部

///

/// 点是否在任意多边形内部

///

/// -1:不在多边形内 0:在多边形上 1:多边形内

public static int IsPointInAnyPolygon(Vector2 point, List polygon)

{

//顶点数量小于3,则无法形成多边形

if (polygon.Count < 3) return -1;

//1.先获取多边形所在矩形范围内

Vector2 rectMin = polygon[0], rectMax = polygon[0];

for (int i = 1; i < polygon.Count; i++)

{

if (polygon[i].x < rectMin.x) rectMin.x = polygon[i].x;

if (polygon[i].y < rectMin.y) rectMin.y = polygon[i].y;

if (polygon[i].x > rectMax.x) rectMax.x = polygon[i].x;

if (polygon[i].y > rectMax.y) rectMax.y = polygon[i].y;

}

if (point.x < rectMin.x || point.y < rectMin.y || point.x > rectMax.x || point.y > rectMax.y) return -1;

//2.射线相交点计算

int intersectCount = 0;

for (int i = 0; i < polygon.Count; i++)

{

int nextIndex = i + 1;

if (nextIndex >= polygon.Count)

nextIndex = 0;

//目标在顶点上

if (polygon[i] == point || polygon[nextIndex] == point)

return 0;

//目标在线段上

if (IsPointOnSegment2(point, polygon[i], polygon[nextIndex]))

return 0;

Vector2 intersectPoint;

//射线与线段相交

if (IsRaySegmentIntersect(point, Vector2.right, polygon[i], polygon[nextIndex], out intersectPoint))

{

//如果相交为线段的顶点,则需要增加2,因为在同一点进入,又在同一个点出去

if (intersectPoint == polygon[i] || intersectPoint == polygon[nextIndex])

intersectCount += 2;

else

intersectCount += 1;

}

}

return intersectCount % 2 == 1 ? 1 : -1;

}

12.写一个计时器工具,从整点开始计时,格式为:00:00:00

挂在随便一个text物体上空格暂停与开始;小键盘0清零

public class Timer: MonoBehaviour

{

private float timer = 0f;

private int h = 0;

private int m = 0;

private int s = 0;

private string timeStr = string.Empty;

Text time_text;

bool pause = true;

private void Start()

{

time_text = gameObject.GetComponent();

}

void Update()

{

if (Input.GetKeyDown(KeyCode.Space))

{

pause = !pause;

}

timer += Time.deltaTime;

if (!pause)

{

if (timer >= 1f)

{

s++;

timer = 0;

}

if (s >= 60)

{

m++;

s = 0;

}

if (m >= 60)

{

h++;

m = 0;

}

if (h >= 99)

{

h = 0;

}

}

if (Input.GetKeyDown(KeyCode.Keypad0))

{

s = 0; m = 0; h = 0;

}

timeStr = string.Format("{0:D2}:{1:D2}:{2:D2}", h, m, s);

time_text.text = timeStr;

}

}

13.用鼠标实现在场景中拖动物体,用鼠标滚轮实现缩放

鼠标拖拽,注:被拖拽物体不能与场景内其他物体在default layer上

public class DragObj : MonoBehaviour

{

private void OnMouseEnter()

{

gameObject.transform.localScale += new Vector3(0.1f, 0.1f, 0.1f);

}

private void OnMouseExit()

{

gameObject.transform.localScale -= new Vector3(0.1f, 0.1f, 0.1f);

}

private void OnMouseDrag()

{

Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);//从屏幕鼠标点击的位置向场景内发出一条射线

RaycastHit floorHit;

if (Physics.Raycast(camRay, out floorHit, 1000f, 1))//1为过滤层

{

transform.position = new Vector3(floorHit.point.x, floorHit.point.y + 0.25f, floorHit.point.z);

}

}

}

//滚轮缩放

public class ViewCtrl : MonoBehaviour

{

public float wheelspeed;

void Update()

{

transform.Translate(0, 0, Input.GetAxis("Mouse ScrollWheel") * wheelspeed * Time.deltaTime, Space.Self);

}

}

14.写一个角色控制器,鼠标控制屏幕晃动,鼠标控制开枪。

public class Player : MonoBehaviour

{

public GameObject _prefabBullet;

private float _angleSpeed = 120f;

void Update()

{

float eularY = Input.GetAxis("Mouse X") * _angleSpeed * Time.deltaTime;

transform.Rotate(new Vector3(0, eularY, 0));

if (Input.GetMouseButtonDown(0))

{

Instantiate(_prefabBullet, transform.position, transform.rotation);

}

}

}

15.3D空间有三个cube当做点,有一条鱼的模型,要求在三点之间游动,要

求转向平滑一点,控制鱼的运动朝向(用四元数和欧拉角)使用transform.localRotation = Quaternion.Slerp(Quaternion a,Quaternion b,float c)实现物体平滑转向

16.设计一款计时器(Timer)功能,拥有基础事件:开始计时、暂停计时,停止计时【计时器事件】

public class Timer : MonoBehaviour

{

public delegate void MyEventHandler(float currentTime);

#region 计时器的三种基础事件

public static event MyEventHandler onTimerStart;

public static event MyEventHandler onTimerPause;

public static event MyEventHandler onTimerStoped;

#endregion

private bool isStarted = false;

public bool IsStarted

{

get

{

return isStarted;

}

}

private bool isStoped = true;

public bool IsStoped

{

get

{

return isStoped;

}

}

private float totalTime = 0;

// Update is called once per frame

void Update()

{

//空格键当作“开始/暂停”键

if (Input.GetKeyDown(KeyCode.Space))

{

OnChangeState();

}

//回车键当作“停止”键

if (Input.GetKeyDown(KeyCode.Return))

{

OnSetStop();

}

if (isStarted)

{

isStoped = false;

totalTime += Time.deltaTime;

}

}

void OnChangeState()

{

var _startState = !isStarted;

isStarted = _startState;

if (isStarted)

{

//检查onTimerStart是否为空,防止报空 (废话了。。。下面不做赘述)

if (onTimerStart != null)

{

onTimerStart(totalTime);

}

else

{

Debug.Log("onTimerStart is Empty");

}

}

else

{

if (onTimerPause != null)

{

onTimerPause(totalTime);

}

else

{

Debug.Log("onTimerPause is Empty");

}

}

}

void OnSetStop()

{

if (onTimerStoped != null)

{

onTimerStoped(totalTime);

}

else

{

Debug.Log("onTimerStoped is Empty");

}

isStarted = false;

isStoped = true;

totalTime = 0;

}

}

好文阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。