Пример #1
0
 public static void GetColliderPosition
 (
     GeoDataElement geoDataElement,
     out int collisionMinX,
     out int collisionMaxX,
     out int collisionMinY,
     out int collisionMaxY,
     out int collisionMinZ,
     out int collisionMaxZ
 )
 {
     collisionMinX = geoDataElement.Location.X;
     collisionMinY = geoDataElement.Location.Y;
     collisionMinZ = geoDataElement.Location.Z;
     collisionMaxX = geoDataElement.Location.X + (geoDataElement.ColliderSize.X > 0 ? (geoDataElement.ColliderSize.X - 1) : 0);
     collisionMaxY = geoDataElement.Location.Y + (geoDataElement.ColliderSize.Y > 0 ? (geoDataElement.ColliderSize.Y - 1) : 0);
     collisionMaxZ = geoDataElement.Location.Z + (geoDataElement.ColliderSize.Z > 0 ? (geoDataElement.ColliderSize.Z - 1) : 0);
 }
Пример #2
0
        public static Point3 <double> GetRandomExitPosition(List <GeoDataElement> geoDataList)
        {
            if (geoDataList.Count == 0)
            {
                return(null);
            }

            int            randomIndex = (geoDataList.Count > 1 ? Measure.GetRandomNumber(0, geoDataList.Count - 1) : 0);
            GeoDataElement geoElement  = geoDataList[randomIndex];

            int collisionMinX, collisionMaxX, collisionMinY, collisionMaxY, collisionMinZ, collisionMaxZ;

            GetColliderPosition(geoElement, out collisionMinX, out collisionMaxX, out collisionMinY, out collisionMaxY, out collisionMinZ, out collisionMaxZ);

            return(new Point3 <double>
                   (
                       Measure.Lerp(Convert.ToDouble(collisionMinX), Convert.ToDouble(collisionMaxX), 0.5) + 0.5,
                       Measure.Lerp(Convert.ToDouble(collisionMinY), Convert.ToDouble(collisionMaxY), 0.5) + 0.5,
                       Convert.ToDouble(collisionMaxZ) + 1
                   ));
        }
Пример #3
0
        public static BoxedData ValidateMovement(List <GeoDataElement> geoDataList, CharacterMovementDetails movementDetails)
        {
            BoxedData data = new BoxedData();
            GeoDataValidationDetails details = new GeoDataValidationDetails();
            string msg = "";

            try
            {
                #region Sub arrays
                //SUB ARRAYS
                GeoDataElement[] terrainSubArray  = new GeoDataElement[geoDataList.Count];
                GeoDataElement[] obstacleSubArray = new GeoDataElement[geoDataList.Count];
                int terrainFilledSize             = 0;
                int obstacleFilledSize            = 0;

                for (int i = 0; i < geoDataList.Count; i++)
                {
                    switch (geoDataList[i].ElementType)
                    {
                    case GeoDataElement.Type.Terrain:
                        terrainSubArray[terrainFilledSize] = geoDataList[i];
                        terrainFilledSize++;
                        break;

                    case GeoDataElement.Type.Obstacle:
                        obstacleSubArray[obstacleFilledSize] = geoDataList[i];
                        obstacleFilledSize++;
                        break;

                    case GeoDataElement.Type.Platform:
                        terrainSubArray[terrainFilledSize]   = geoDataList[i];
                        obstacleSubArray[obstacleFilledSize] = geoDataList[i];
                        terrainFilledSize++;
                        obstacleFilledSize++;
                        break;
                    }
                }

                #endregion

                //PARAMETERS

                bool            valid = true;
                Point3 <double> lastValidMovementPoint = movementDetails.OldLocationLocal.Copy();
                double          tStep = Measure.GetTParamStep(movementDetails.OldLocationLocal, movementDetails.NewLocationLocal)
                                        / 2;

                double tParam        = 0;
                double tParamClamped = 0;
                bool   tParamReached = false;

                //VALIDATION

                if (tStep > 0 && tStep < 1)
                {
                    double currentXDbl, currentYDbl, currentZDbl;
                    int    currentX, currentY, currentZ;
                    int    collisionMinX, collisionMaxX, collisionMinY, collisionMaxY, collisionMinZ, collisionMaxZ;

                    GeoDataElement geoDataElement;
                    bool           obstacleDetected = false;
                    bool           hasGroundUnderFeet;

                    while (!tParamReached)
                    {
                        tParamClamped = Measure.Clamp(0.0000, 1.0000, tParam);
                        currentXDbl   = Measure.Lerp(movementDetails.OldLocationLocal.X, movementDetails.NewLocationLocal.X, tParamClamped);
                        currentYDbl   = Measure.Lerp(movementDetails.OldLocationLocal.Y, movementDetails.NewLocationLocal.Y, tParamClamped);
                        currentZDbl   = Measure.Lerp(movementDetails.OldLocationLocal.Z, movementDetails.NewLocationLocal.Z, tParamClamped)
                                        + _marginZ;

                        currentX = Convert.ToInt32(Math.Floor(currentXDbl));
                        currentY = Convert.ToInt32(Math.Floor(currentYDbl));
                        currentZ = Convert.ToInt32(Math.Floor(currentZDbl));

                        #region Obstacle check
                        //OBSTACLE CHECK
                        for (int i = 0; i < obstacleFilledSize; i++)
                        {
                            geoDataElement = obstacleSubArray[i];
                            GetColliderPosition(geoDataElement, out collisionMinX, out collisionMaxX, out collisionMinY, out collisionMaxY, out collisionMinZ, out collisionMaxZ);

                            if
                            (
                                currentX >= collisionMinX && currentX <= collisionMaxX &&
                                currentY >= collisionMinY && currentY <= collisionMaxY &&
                                currentZ >= collisionMinZ && currentZ <= collisionMaxZ
                            )
                            {
                                obstacleDetected = true;
                                break;
                            }
                        }

                        #endregion

                        #region Ground check
                        //GROUND CHECK
                        hasGroundUnderFeet = false;

                        if (!obstacleDetected) //NOTE: ground check is not necessary if player collides with obstacle (performance)
                        {
                            for (int i = 0; i < terrainFilledSize; i++)
                            {
                                geoDataElement = terrainSubArray[i];
                                GetColliderPosition(geoDataElement, out collisionMinX, out collisionMaxX, out collisionMinY, out collisionMaxY, out collisionMinZ, out collisionMaxZ);

                                if
                                (
                                    currentX >= collisionMinX && currentX <= collisionMaxX &&
                                    currentY >= collisionMinY && currentY <= collisionMaxY &&
                                    currentZ >= collisionMinZ - 1 && currentZ <= collisionMaxZ + 2
                                )
                                {
                                    hasGroundUnderFeet = true;
                                    break;
                                }
                            }
                        }

                        #endregion

                        if (obstacleDetected || !hasGroundUnderFeet)
                        {
                            valid = false;
                            break;
                        }
                        else
                        {
                            lastValidMovementPoint.X = currentXDbl;
                            lastValidMovementPoint.Y = currentYDbl;
                            lastValidMovementPoint.Z = currentZDbl - _marginZ;
                        }

                        //Console.WriteLine($"tClamped [{tParamClamped}] pos [{currentX}; {currentY}; {currentZ}] obstacle [{obstacleDetected}]");

                        if (tParam >= 1)
                        {
                            tParamReached = true;
                        }

                        tParam += tStep;
                    }
                }


                details.Valid = valid;
                details.LastValidMovementPoint = lastValidMovementPoint;
                details.LastTParamValue        = tParamClamped;
            }
            catch (Exception exception)
            {
                msg = $"Error occured while geo data movement validation for character's ID [{movementDetails.CharId}]: {exception.Message}";
            }

            data.Data = details;
            data.Msg  = msg;
            return(data);
        }