团队项目:核心算法实现

本游戏中最为核心的算法在于绘制轨道曲线的算法,实现如下:

每帧获取屏幕上的鼠标的位置设置为终点vt,之前上一帧设置的起点为v0,则这一帧所生成的轨道就是从v0到vt。在轨道生成完成后,将v0设置为vt,以便于下一帧继续进行轨道的生成。

流程图:

         图1 核心算法流程图

伪代码:

         1.检测是否按住鼠标左键,是则进入2,否则进入8。

         2.获取鼠标在屏幕上的当前位置并转换为世界坐标temp_pos。

         3.如果是第一次按下(first为true),将当前temp_pos赋给begin_pos,将first设为false。

         4.如果当前的temp_pos到begin_pos的距离在最小限度以外,且线条总长totalLength在总长限制maxLength内则进入5,否则进入8。

         5.将temp_pos赋给end_pos,若当前totalLength加上begin_pos和end_pos之间的距离tempLength超过了maxLength则对线段[begin_pos,end_pos]截取,改变end_pos的位置,使totalLength加上tempLength等于maxLength。将totalLength+tempLength赋给totalLength。

         6.在线段[begin_pos,end_pos]的终点new_pos的位置创建一个轨道元素,并调整其角度和缩放值,使其从begin_pos连接到end_pos。

         7.将end_pos赋给begin_pos。

         8.检测是否放开鼠标左键,是则进入9,否则进入10。

         9.将first设置为true,将totalLength设置为maxLength(即松开左键后不得继续创建轨道元素;clear()函数可将totalLength清零,之后可以继续画线)。

         10.回到1。

详细代码:

if (Input.GetMouseButton(0)){//如果按住左键
            temp_pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);//屏幕坐标转世界坐标
            temp_pos.z = 0;//调整世界坐标z轴
            if (first == true){//如果是第一次按左键
                begin_pos = temp_pos;//当前位置作为开始位置
                first = false;//设置第一次标志为假
            }
           //当前位置和开始位置有一定间隔&&未超出长度限制
            else if ((Vector3.Magnitude(temp_pos - begin_pos) >= 0.1) && (totalLength < maxLength)){
                end_pos = temp_pos;//当前位置作为结束为止
                float tempLength = Vector3.Magnitude(end_pos - begin_pos);//记录当前长度
                if (totalLength + tempLength > maxLength) {//若在本次超出长度限制
                 //调整end_pos并且进行截取
                    end_pos = begin_pos + (end_pos - begin_pos) * (maxLength - totalLength) / tempLength;
                    totalLength = maxLength;//总长度等于最大长度
                }
                else{//本次未超出长度限制
                    totalLength += tempLength;//总长度加上当前长度
                }
              //新的轨道物体的位置为开始位置和结束位置连线的中点
                Vector3 new_pos = (begin_pos + end_pos) / 2;
              //新的轨道物体的x方向的缩放因子为开始位置和结束位置之间的线段长度
              //(因为轨道物体的x方向长度为1)
                Vector3 new_scale = new Vector3(Vector3.Magnitude(end_pos - begin_pos), 1, 1);
                //新的轨道物体的旋转角度
              float new_degree = 0;
                if (begin_pos.y > end_pos.y){//终点在起点下方
                 //旋转角度为向量Vector3.right和end_pos-begin_pos的夹角的相反数
                    new_degree = -Vector3.Angle(Vector3.right, end_pos - begin_pos);
                 //因为Angle方法只能返回0到180度的角
                }
                else{//终点在起点上方
                 //旋转角度为向量Vector3.right和end_pos-begin_pos的夹角
                    new_degree = Vector3.Angle(Vector3.right, end_pos - begin_pos);
                 //因为Angle方法只能返回0到180度的角
                }
              //实例化track_element物体
                track_element_new=(GameObject)Instantiate(track_element, new_pos, Quaternion.identity); 
              //更改其缩放因子
                track_element_new.transform.localScale = new_scale;
              //更改其旋转角度(绕z轴正方向旋转new_degree度)
                track_element_new.transform.Rotate(Vector3.forward, new_degree);
              //更新下一次的开始位置为这一次的结束位置
                begin_pos = end_pos;
            }
        }
        if (Input.GetMouseButtonUp(0)){//如果放开鼠标左键
            totalLength = maxLength;//将当前总长度设为最大,即松开左键就不可再画(一笔画)
            first = true;//设置first标志为真
        }
原文地址:https://www.cnblogs.com/GingerAle/p/5601645.html