游戏开发_数学与物理

https://blog.csdn.net/wfenglinxu/article/details/46732147   游戏中的数学与物理(一)

1.1让物体沿水平方向运动

     了解匀速直线运动(最简单的运动),若左边为x,速度为v,则:x+=v,v=-v。

      注意: 注意物体的中心点,不同的游戏引擎,可能设计的中心点不同,而中心点不同,边界也就不同。

1.2通过键盘控制物体的运动

     主要用到小学学的勾股定理,原理很简单,而且很实用。

      PS: 在模拟运动时,要控制个方向的速度。

随机喷射:

正态分布:

可以根据均匀分布的随机数生成满足正态分布的随机数的算法。

 

 

第三章 碰撞检测

德摩根定律:对全体条件的否定可以分解为对所有单个条件的否定。

矩形之间的碰撞检测:分别对两个矩形的上坐标和下坐标都进行判定。

应用:

用于对2D物体的判断,使用屏幕空间的坐标

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


/// <summary>
/// 任意形状,任意长宽的物体相交时弹开
/// 在相交时,沿着向量方向移动,可以是任意现状的物体相交,任意大小的物体相交,UI等
/// </summary>
public class OpenDrawPlane : MonoBehaviour
{

    public List<Transform> listTrans = new List<Transform>();
    public List<Info> listScreenPos= new List<Info>();
    public float prinfWidth = 150; 
    public float prinfHeight = 160;

    /// <summary>
    /// 因为这个画板的中心点还需要加上地下画笔的高度
    /// </summary>
    [Range(-40, 40)]
    public float heightScreen=20;
    /// <summary>
    /// 调整偏移的比率
    /// </summary>
    [Range(-20, 20)]
    public float offsetX =0;
    [Range(-40, 40)]
    public float offsetY = 0;

    Vector3 drawSheepPanelFar = new Vector3(0, -100, -870);
    void Update()
    {

        listScreenPos.Clear();


        //适应不同分辨率的画板长宽
        prinfWidth = Screen.width / (Screen.width / prinfWidth);
        prinfHeight = Screen.height / (Screen.height / prinfHeight);
        heightScreen = Screen.height / (Screen.height / heightScreen);



        //for (int row = 0; row < listTrans.Count; row++)
        //{
        //    Vector3 screenPos = 
        // Camera.main.WorldToScreenPoint(listTrans[row].transform.position);
        //    Info info = new Info();
        //    info.trans = listTrans[row].transform;
        //    info.screenPos = screenPos;
        //    info.width = 100;
        //    info.height = 100;
        //    listScreenPos.Add(info);
        //}



        Transform drawBoardPar = transform;
        for (int row = 0; row < drawBoardPar.GetChildCount(); row++)
        {
            Transform trans = drawBoardPar.GetChild(row);
            if (trans.localPosition != drawSheepPanelFar)
            {
                Vector3 screenPos = Camera.main.WorldToScreenPoint(trans.position);
                Info info = new Info();
                info.trans = trans;
                info.screenPos = screenPos;

                //此处可以是不同的长宽度物体,或者直接获取物件相在屏幕空间下的长宽
                info.width = prinfWidth;
                info.height = prinfHeight;
                listScreenPos.Add(info);
            }
        }


        for (int row = 0; row < listScreenPos.Count; row++)
          {
            for (int cow = 0; cow < listScreenPos.Count; cow++)
            {
                //画板和画板的检测
                if (listScreenPos[row].trans != listScreenPos[cow].trans)
                {
                    //在相交时,沿着向量方向移动,可以是任意现状的物体相交,任意大小的物体相交
                    //两个物体的位置的x位置和两物体的y的位置  x<width*2    y<height*2
                    float centerX = Mathf.Abs(listScreenPos[row].screenPos.x - listScreenPos[cow].screenPos.x);
                    float centerY = Mathf.Abs(listScreenPos[row].screenPos.y - listScreenPos[cow].screenPos.y);
                    if (centerX < (listScreenPos[row].width / 2 + listScreenPos[cow].width / 2) &&
                       centerY < (listScreenPos[row].height / 2 + listScreenPos[cow].height / 2))
                    {
                        //Debug.Log(listScreenPos[row].trans.gameObject.name + "      和         " + listScreenPos[cow].trans.gameObject.name + "       想交");

                        /////对于中心点完全相同的,则dir =0,则需要减去一个位置偏移-new Vec(0.2,0.2f,0.2))
                        Vector3 dir = listScreenPos[row].trans.localPosition - listScreenPos[cow].trans.localPosition;


                        //设置在屏幕以内运动
                        Vector3 screenPosRow = Camera.main.WorldToScreenPoint(listScreenPos[row].trans.position);
                        if ((screenPosRow.x + listScreenPos[row].width / 2) < Screen.width && (screenPosRow.x - listScreenPos[row].width / 2) > 0 &&
                           (screenPosRow.y + listScreenPos[row].height / 2) < Screen.height && (screenPosRow.y - listScreenPos[row].height / 2) > 0 + heightScreen)
                        {
                            listScreenPos[row].trans.Translate(dir.normalized * Time.deltaTime);
                        }
                    }
                }
                else
                {
                    //画板和屏幕的检测
                    Vector3 screenPosRow = Camera.main.WorldToScreenPoint(listScreenPos[row].trans.position);

                    if ((screenPosRow.y + listScreenPos[row].height / 2) > Screen.height)
                    {
                        listScreenPos[row].trans.Translate(-listScreenPos[row].trans.up * Time.deltaTime);
                    }
                    else   if ((screenPosRow.y - listScreenPos[row].height / 2) < 0 + heightScreen)
                    {
                        listScreenPos[row].trans.Translate(listScreenPos[row].trans.up * Time.deltaTime);
                    }

                    if ((screenPosRow.x + listScreenPos[row].width / 2) > Screen.width)
                    {
                        listScreenPos[row].trans.Translate(-listScreenPos[row].trans.right * Time.deltaTime);
                    }
                    else if ((screenPosRow.x - listScreenPos[row].width / 2) < 0)
                    {
                        listScreenPos[row].trans.Translate(listScreenPos[row].trans.right * Time.deltaTime);
                    }
                }
            }
        }
    }

  public  class Info
    {
        public Transform trans;
        public Vector3 screenPos;
        public float width = 150;
        public float height = 160;
    }

}

  

 

用于对3D物体的判断,加入z向量,使用世界空间的坐标

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour {

    public List<Transform> listTrans = new List<Transform>();
    public List<Info> listScreenPos = new List<Info>();
    
    void Update()
    {

        listScreenPos.Clear();
        for (int row = 0; row < listTrans.Count; row++)
        {
            Info info = new Info();
            info.trans = listTrans[row].transform;
            info.screenPos = listTrans[row].transform.position;
            info.width = 1.2f;  //单位为1的cube
            info.height = 1.2f;
            info.back = 1.2f;
            listScreenPos.Add(info);
        }
        
        for (int row = 0; row < listScreenPos.Count; row++)
        {
            for (int cow = 0; cow < listScreenPos.Count; cow++)
            {
                //画板和画板的检测
                if (listScreenPos[row].trans != listScreenPos[cow].trans)
                {
                    //在相交时,沿着向量方向移动,可以是任意现状的物体相交,任意大小的物体相交
                    //两个物体的位置的x位置和两物体的y的位置  x<width*2    y<height*2
                    float centerX = Mathf.Abs(listScreenPos[row].screenPos.x - listScreenPos[cow].screenPos.x);
                    float centerY = Mathf.Abs(listScreenPos[row].screenPos.y - listScreenPos[cow].screenPos.y);
                    float centerZ = Mathf.Abs(listScreenPos[row].screenPos.z - listScreenPos[cow].screenPos.z);
                    if (centerX < (listScreenPos[row].width / 2 + listScreenPos[cow].width / 2) &&
                        centerY < (listScreenPos[row].height / 2 + listScreenPos[cow].height / 2)&&
                        centerZ < (listScreenPos[row].back / 2 + listScreenPos[cow].back / 2))
                    {
                        Vector3 dir = listScreenPos[row].trans.localPosition - listScreenPos[cow].trans.localPosition;
                        listScreenPos[row].trans.Translate(dir.normalized * Time.deltaTime*0.2F);
                    }
                }
            }
        }
    }

    public class Info
    {
        public Transform trans;
        public Vector3 screenPos;
        public float width = 150;
        public float height = 160;
        public float back = 160;
    }

}

矩形攻击或 对于判断前方是否触发了NPC的判断:

角色和NPC之间的向量为DirVec

<1. 判断Vector.Forword和DirVec的点乘,大于0,在前方。

<2. 满足第一条后,在判断DirVec在Vector.Forword方向的投影,长度是否是player的可视范围。

扇形攻击:扇形攻击角度60度,半径R, |A|=|NPC->player|

<1. 算夹角<角度/2【30】

<2. |A|<R

 

圆和圆的碰撞检测:对此向量求模长,后再和两者半径之和做比较

矩形和圆形物体的碰撞检测

思路:

<1. 先把矩形长宽扩张长度r. 扩张后新的矩形包含了圆心坐标,再进行第二步

<2. 假设圆心在扩张后的四个角处,圆内有没有包含长方形最近的顶点【扩张前矩形的某个顶点】,则圆和矩形没有碰撞

细长形物体【激光\剑】与圆形物体的碰撞检测

满足Lmin<r1+r2  ,则碰撞。

即求处Lmin的距离,把问题转换为点到线段的距离

这个公式,是求点到一条无限长度的直线的距离,不可取。

向量表示直线上的位置向量p 【游戏编程长用向量表示直线】:

扇形物体的碰撞检测:

挥剑,受伤范围

【定比分公式】

【圆与线段的交点判断】

 

满足上边任意一条,则证明发生碰撞,在剑的伤害范围内。但是一般优先检测两个不可能碰撞的条件

【即(圆心到扇心的距离) > (圆半径+扇半径)】

应用:

用向量点乘法计算是否在区域内

扇形攻击:扇形攻击角度60度,半径R, |A|=|NPC->player|

<1. 算夹角<角度/2【30】

<2. |A|<R

 

矩形攻击区域和扇形的攻击区域怎么判断是否有交叉?【把面 的交叉转换为点的交叉】。

<1. 判断矩形的中心点是否在扇形区域内,矩形的两个顶点是否也在区域内

 

展开阅读全文

没有更多推荐了,返回首页