Exemplo n.º 1
0
        public void Update()
        {
            lastPos = pos;
            //更新绳子物理
            if (rope != null)
            {
                rope.Update(tentacleIndex != 0 ? tentacle.tChunks[tentacleIndex - 1].pos : tentacle.FloatBase, pos);
                if (!RopeActive || phase > -1.0 || tentacleIndex > 0 && tentacle.tChunks[tentacleIndex - 1].phase > -1.0 || rope.totalLength > tentacle.idealLength / (double)tentacle.tChunks.Length * 5.0)
                {
                    rope.Reset();
                }
            }

            //如果当前Chunk已定相
            if (phase == -1.0)
            {
                if (phasesToSameLocation > 0 && tentacle.segments[this.currentSegment] == afterPhaseStuckPos)
                {
                    pos = Utils.RestrictInRect(pos, StuckRect);
                }

                //如果是第一个触手节(靠近基座)
                if (tentacleIndex == 0)
                {
                    //计算距离基座的方向和距离
                    Vector2 dir  = Utils.DirVec(pos, tentacle.FloatBase);
                    float   dist = Vector2.Distance(pos, tentacle.FloatBase);
                    if (RopeActive)
                    {
                        dir  = Utils.DirVec(pos, rope.BConnect);
                        dist = rope.totalLength;
                    }
                    //计算收缩长度 =(理想长度 * 撤回因子)/ 触手关节数目
                    float length = tentacle.idealLength / tentacle.tChunks.Length * Mathf.Lerp(1f, 0.1f, tentacle.retractFac);
                    if (tp.stiff || dist > (double)length)
                    {
                        //更新当前Chunk的Pos、Vel属性
                        pos -= dir * (length - dist) * (1f - tp.pullAtConnectionChunk);
                        vel -= dir * (length - dist) * (1f - tp.pullAtConnectionChunk);
                        //如果触手属性对生物连接体有拉力:更新连接Chunk的Pos、Vel属性
                        if (tentacle.connectedChunk != null && tp.pullAtConnectionChunk > 0.0)
                        {
                            if (RopeActive)
                            {
                                dir = Utils.DirVec(rope.AConnect, tentacle.connectedChunk.pos);
                            }
                            tentacle.connectedChunk.pos += dir * (length - dist) * tp.pullAtConnectionChunk;
                            tentacle.connectedChunk.vel += dir * (length - dist) * tp.pullAtConnectionChunk;
                        }
                    }
                    //计算当前拉伸系数 = 理想长度 /( 触手关节数 * 与上一关节距离)
                    stretchedFac = tentacle.idealLength / tentacle.tChunks.Length / Mathf.Max(1f, dist);
                }
                //(计算逻辑基本同上)
                else
                {
                    //计算与前一触手节的方向和距离
                    Vector2 dir  = Utils.DirVec(pos, tentacle.tChunks[tentacleIndex - 1].pos);
                    float   dist = Vector2.Distance(pos, tentacle.tChunks[tentacleIndex - 1].pos);
                    if (RopeActive)
                    {
                        dir  = Utils.DirVec(pos, rope.BConnect);
                        dist = rope.totalLength;
                    }
                    float num = tentacle.idealLength / tentacle.tChunks.Length * Mathf.Lerp(1f, 0.1f, tentacle.retractFac);
                    if (tp.stiff || dist > (double)num)
                    {
                        pos -= dir * (num - dist) * (1f - tp.massDeteriorationPerChunk);
                        vel -= dir * (num - dist) * (1f - tp.massDeteriorationPerChunk);
                        if (RopeActive)
                        {
                            dir = Utils.DirVec(rope.AConnect, tentacle.tChunks[tentacleIndex - 1].pos);
                        }
                        tentacle.tChunks[tentacleIndex - 1].pos += dir * (num - dist) * tp.massDeteriorationPerChunk;
                        tentacle.tChunks[tentacleIndex - 1].vel += dir * (num - dist) * tp.massDeteriorationPerChunk;
                    }
                    stretchedFac = tentacle.idealLength / tentacle.tChunks.Length / Mathf.Max(1f, dist);
                }

                //StuckPos不等于trail首个位置时,trail首位插入StuckPos
                if (StuckPos != currentSegmentTrail[0])
                {
                    currentSegmentTrail.Insert(0, StuckPos);
                    currentSegmentTrail.RemoveAt(currentSegmentTrail.Count - 1);
                }

                //检测撤回关节索引不存在  && 当前Chunk位置和Segment直线不可达
                if (tentacle.backtrackFrom == -1 && !tentacle.Visual(tentacle.room.GetTilePosition(pos), tentacle.segments[this.currentSegment]))
                {
                    tentacle.backtrackFrom = tentacleIndex;
                }
                //如果当前触手体存在撤回索引,且当前Chunk索引大于撤回索引
                if (tentacle.backtrackFrom != -1 && tentacleIndex >= tentacle.backtrackFrom)
                {
                    bool flag = false;
                    for (int index = 1; index <= currentSegment && !flag; ++index)
                    {
                        if (!PhysicsUtils.RayTraceTilesForTerrain(tentacle.room, tentacle.room.GetTilePosition(pos), tentacle.segments[index]) &&
                            PhysicsUtils.RayTraceTilesForTerrain(tentacle.room, tentacle.room.GetTilePosition(pos), tentacle.segments[index - 1]))
                        {
                            vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[index - 1]) - pos, 20f) * tp.backtrackSpeed / 20f;
                            flag = true;
                        }
                    }
                    if (!flag)
                    {
                        //获取前一触手节位置
                        Vector2 tentacleBase = tentacle.FloatBase;
                        if (tentacleIndex > 0)
                        {
                            tentacleBase = tentacle.tChunks[tentacleIndex - 1].pos;
                        }
                        //更新当前Chunk速度 =( 矢量距离 * 撤回速度)/ 20f
                        vel += Vector2.ClampMagnitude(tentacleBase - pos, 20f) * tp.backtrackSpeed / 20f;
                        //更新前一Chunk速度
                        if (tentacleIndex > 0)
                        {
                            tentacle.tChunks[tentacleIndex - 1].vel += Vector2.ClampMagnitude(tentacleBase - pos, 20f) * tp.backtrackSpeed / 20f;
                        }
                    }
                    //当前关联Point不为空
                    if (!flag && (contactPoint.x != 0 || contactPoint.y != 0))
                    {
                        //定相尝试次数递增1
                        ++phaseAttempts;
                        //定相尝试次数 > 触手属性值
                        if (phaseAttempts > tentacle.tProps.terrainHitsBeforePhase)
                        {
                            //开始定相
                            PhaseToSegment();
                            phaseAttempts = 0;
                        }
                    }
                }
                //不存在撤回索引  or  撤回索引大于当前Chunk索引
                else
                {
                    phaseAttempts = 0;
                    //瘫软状态
                    if (tentacle.limp)
                    {
                        //从当前Seg往前遍历
                        for (int currentSegment = this.currentSegment; currentSegment >= 0; --currentSegment)
                        {
                            //如果当前Chunk位置和Seg视觉可见
                            if (tentacle.Visual(tentacle.room.GetTilePosition(pos), tentacle.segments[currentSegment]))
                            {
                                if (tentacle.room.GetTile(tentacle.segments[currentSegment].x, tentacle.segments[currentSegment].y - 1).Solid)
                                {
                                    vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[currentSegment].x, tentacle.segments[currentSegment].y) - pos, 20f) * 0.005f;
                                    break;
                                }
                                vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[currentSegment]) - pos, 20f) * 0.005f;
                                break;
                            }
                        }
                    }
                    //触手非瘫软状态
                    else
                    {
                        //触手存在抓取目标
                        if (tentacle.floatGrabDest.HasValue)
                        {
                            //计算抓取目标对Chunk的吸引力 : 修改速度
                            if (tentacleIndex == tentacle.tChunks.Length - 1)
                            {
                                vel += Vector2.ClampMagnitude(tentacle.floatGrabDest.Value - pos, 20f) * tp.goalAttractionSpeedTip / 20f;
                            }
                            else
                            {
                                vel += Vector2.ClampMagnitude(tentacle.floatGrabDest.Value - pos, 20f) * tp.goalAttractionSpeed / 20f;
                            }
                        }
                        //Chunk速度 对齐Segment
                        vel += Vector2.ClampMagnitude(tentacle.room.MiddleOfTile(tentacle.segments[currentSegment]) - pos, 20f) * tp.alignToSegmentSpeed / 20f;
                    }
                }

                //Clamp速度、更新位置
                vel  = Vector2.ClampMagnitude(vel, tp.chunkVelocityCap);
                pos += vel;
                //与地形发生碰撞、计算碰撞后的位置、速度、碰撞点
                if (collideWithTerrain)
                {
                    lastContactPoint = contactPoint;
                    PhysicsUtils.TerrainCollisionData terrainCollisionData = PhysicsUtils.HorizontalCollision(tentacle.room, PhysicsUtils.SlopesVertically(tentacle.room, PhysicsUtils.VerticalCollision(tentacle.room, new PhysicsUtils.TerrainCollisionData(pos, pos - vel, vel, rad, new IntVector2(0, 0), true))));
                    contactPoint = terrainCollisionData.contactPoint;
                    pos          = terrainCollisionData.pos;
                    vel          = terrainCollisionData.vel;
                }
            }
            //如果当前Chunk为定相
            else
            {
                //定相逐帧计数(后面的数值基本都设置为:15)
                phase += 1f / tp.segmentPhaseThroughTerrainFrames;
                //根据当前定相进度,插值改变Pos属性(PhaseFrom->StuckPos)
                if (phase <= 1.0)
                {
                    pos = Vector2.Lerp(phaseFrom, tentacle.room.MiddleOfTile(StuckPos), Mathf.Min(1f, phase));
                }
                //速度设置为0
                vel *= 0.0f;
                //定相完成
                if (phase >= 1.0)
                {
                    phase = -1f;
                    if (afterPhaseStuckPos == StuckPos)
                    {
                        ++phasesToSameLocation;
                    }
                    else
                    {
                        phasesToSameLocation = 0;
                    }
                    afterPhaseStuckPos = StuckPos;
                }
                //如果是触手关节、且前一触手节未定相
                if (tentacleIndex > 0 && tentacle.tChunks[tentacleIndex - 1].phase == -1.0)
                {
                    //计算与前一触手节的方向和距离
                    Vector2 dir  = Utils.DirVec(pos, tentacle.tChunks[tentacleIndex - 1].pos);
                    float   dist = Vector2.Distance(pos, tentacle.tChunks[tentacleIndex - 1].pos);
                    //计算收缩长度 =(理想长度 * 撤回因子)/ 触手关节数目
                    float length = tentacle.idealLength / tentacle.tChunks.Length * Mathf.Lerp(1f, 0.1f, tentacle.retractFac);
                    if (tp.stiff || dist > (double)length)
                    {
                        //对前一触手节产生影响
                        tentacle.tChunks[tentacleIndex - 1].pos += dir * (length - dist) * tp.massDeteriorationPerChunk;
                        tentacle.tChunks[tentacleIndex - 1].vel += dir * (length - dist) * tp.massDeteriorationPerChunk;
                    }
                    //计算拉伸系数
                    stretchedFac = length / dist;
                }
            }

            UpdateDebugSprites();
        }