Пример #1
0
        bool TestPositionAgainDiagonalWalls(Map _theMap, int minX, int minY, int maxX, int maxY, ref bool environmentCollision, ref Point2 newPos)
        {
            bool collidedOnDiagonal = false;

            Point2 result = new Point2();
            Point2 slideBlockCentre = new Point2();

            Point2 localNewPos = new Point2(newPos);
            bool localEnvironmentCollision = environmentCollision;

            for (int y = minY; y < maxY; y++)
            {
                for (int x = minX; x < maxX; x++)
                {
                    if (x >= _theMap.getWidth() / _theMap.getTileWidth() &&
                        y >= _theMap.getHeight() / _theMap.getTileHeight())
                    {
                        continue;
                    }

                    TileType tileType = _theMap.getMapTileType(x, y);

                    Point2 pixel = new Point2(
                        x * _theMap.getTileWidth(),
                        y * _theMap.getTileHeight());

                    int pixelCenX = pixel.X + _theMap.getTileWidth() / 2;
                    int pixelCenY = pixel.Y + _theMap.getTileHeight() / 2;

                    m_boundingTileCircle.Center = new Vector3(pixelCenX, pixelCenY, 0);
                    m_boundingTileCircle.Radius = _theMap.getTileWidth() / 2;

                    if (Map.isTileTypeDiagonalWall(tileType) && _theMap.isTileTypePixelCollision(tileType))
                    {
                        TileType pixelCheckType = _theMap.GetTileTypePixelCollision(tileType);
                        Point2 topLeft = new Point2(
                                localNewPos.X - m_tileSet.getTileWidth() / 2,
                                localNewPos.Y - m_tileSet.getTileHeight() / 2);
                        bool localIntersects = m_tileSet.checkForCollision(_theMap.getTileSet(), m_frameIndexCollision, topLeft, (int)pixelCheckType, pixel);

                        if (localIntersects)
                        {
                            if (Map.isTileTypeDiagonalWall(tileType))
                            {
                                if (localEnvironmentCollision || collidedOnDiagonal)
                                {
                                    localNewPos = new Point2(m_position);
                                }
                                else
                                {
                                    if (GetSlidePositionOffDiagonalBlock(tileType, m_position, localNewPos, ref result, pixel))
                                    {
                                        localNewPos = new Point2(result);
                                    }
                                    else
                                    {
                                        slideBlockCentre = new Point2(pixelCenX, pixelCenY);
                                        GetSlidePositionOffBlock(m_position, localNewPos, slideBlockCentre, _theMap.getTileWidth(), m_characterRadius, ref localNewPos);
                                    }

                                    collidedOnDiagonal = true;
                                }

                                localEnvironmentCollision = true;
                            }
                        }
                    } // if diagonal wall
                } // for loop
            } // for loop

            environmentCollision = localEnvironmentCollision;
            newPos.X = localNewPos.X;
            newPos.Y = localNewPos.Y;
            return collidedOnDiagonal;
        }
Пример #2
0
        public bool movePosition(float frameTime, Map _theMap, Character[] _characterArray, bool slideAgainstWalls, bool canUseSlides)
        {
            bool movingOnSlide = false;

            bool slideAgainstDiagonalWalls = slideAgainstWalls && true;
            bool environmentCollision = false;

            // todo this shouldnt be assigned here each frame
            m_characterRadius = m_tileSet.getTileWidth() / 2 * 8 / 10;

            Point2 change = new Point2();

            int tileIndexX = m_position.X / _theMap.getTileWidth();
            int tileIndexY = m_position.Y / _theMap.getTileHeight();
            TileType tileTypeStoodOn = _theMap.getMapTileType(tileIndexX, tileIndexY);

            Boolean onSlide = Map.isTileTypeSlide(tileTypeStoodOn) && canUseSlides;
            int SLIDE_EXIT_LENGTH = 10;
            // If not sliding (on slide exit) then allow movement
            if (!onSlide)
            {
                float moveSpeed = m_moveSpeedPerSecond * frameTime;

                float cos = (float)Math.Cos(m_rotation);
                float sin = (float)Math.Sin(m_rotation);

                change.X = (int)( sin * moveSpeed);
                change.Y = (int)(-cos * moveSpeed);
            }

            Point2 newPos = new Point2();

            // Velocity is only for slide movement
            if (m_velocity.Length() > MAX_VELOCITY)
            {
                m_velocity.Normalize();
                m_velocity *= MAX_VELOCITY;
            }

            change.X += (int)(m_velocity.X * frameTime);
            newPos.X = m_position.X + change.X;

            change.Y += (int)(m_velocity.Y * frameTime);
            newPos.Y = m_position.Y + change.Y;

            if (Map.isTileTypeSlide(tileTypeStoodOn) && canUseSlides)
            {
                Vector2 targetPoint = new Vector2();
                Vector2 charPoint = new Vector2(m_position.X, m_position.Y);
                targetPoint.X = tileIndexX * _theMap.getTileWidth() + m_tileSet.getTileWidth() / 2;
                targetPoint.Y = tileIndexY * _theMap.getTileHeight() + m_tileSet.getTileHeight() / 2;

                if (tileTypeStoodOn == TileType.SLIDE_DOWN)
                {
                    targetPoint.Y += m_tileSet.getTileHeight();
                }
                else if (tileTypeStoodOn == TileType.SLIDE_UP)
                {
                    targetPoint.Y -= m_tileSet.getTileHeight();
                }
                else if (tileTypeStoodOn == TileType.SLIDE_LEFT)
                {
                    targetPoint.X -= m_tileSet.getTileWidth();
                }
                else if (tileTypeStoodOn == TileType.SLIDE_RIGHT)
                {
                    targetPoint.X += m_tileSet.getTileWidth();
                }

                Vector2 vector = targetPoint - charPoint;

                // Its important this is high to keep the player in the center of the slide
                // So they dont come out off-center and get stuck in collision
                const float VELOCITY_INCREASE = 200.0f;
                m_velocity += vector * VELOCITY_INCREASE * frameTime;
                movingOnSlide = true;
            }
            else if (m_velocity.Length() > 0)
            {
                // dubious code to reduce velocity
                m_velocity *= (25 * frameTime);

                change.X += (int)(m_velocity.X * frameTime);
                change.Y += (int)(m_velocity.Y * frameTime);
                newPos.X = m_position.X + change.X;
                newPos.Y = m_position.Y + change.Y;
                if (m_velocity.Length() < SLIDE_EXIT_LENGTH)
                {
                    m_velocity.X = 0;
                    m_velocity.Y = 0;
                    stopMovement();
                }
            }
            else
            {
                newPos.X = m_position.X + change.X;
                newPos.Y = m_position.Y + change.Y;
            }

            Point2 lastPos = new Point2(newPos);

            // check per tile here
            if (Map.isTileTypeSlide(tileTypeStoodOn) == false && BuildConstants.COLLISION_OFF == false)// && onSlide == false)// && m_teleporting == false)
            {
                // Check against the very boundarys of the map
                newPos.X = capValue(newPos.X, m_characterRadius, _theMap.getWidth() - m_characterRadius);
                newPos.Y = capValue(newPos.Y, m_characterRadius, _theMap.getHeight() - m_characterRadius);

                if (lastPos.X != newPos.X || lastPos.Y != newPos.Y)
                {
                    environmentCollision = true;
                }

                int minX = capValue(tileIndexX - 1, 0, _theMap.getWidth() / _theMap.getTileWidth());
                int maxX = capValue(tileIndexX + 2, 0, _theMap.getWidth() / _theMap.getTileWidth());

                int minY = capValue(tileIndexY - 1, 0, _theMap.getHeight() / _theMap.getTileHeight());
                int maxY = capValue(tileIndexY + 2, 0, _theMap.getHeight() / _theMap.getTileHeight());

                m_boundingCharCircle.Center = new Vector3(newPos.X, newPos.Y, 0);
                m_boundingCharCircle.Radius = m_characterRadius;

                for (int y = minY; y < maxY; y++)
                {
                    for (int x = minX; x < maxX; x++)
                    {
                        if (x >= _theMap.getWidth() / _theMap.getTileWidth() &&
                            y >= _theMap.getHeight() / _theMap.getTileHeight())
                        {
                                 continue;
                        }

                        TileType tileType = _theMap.getMapTileType(x, y);

                        Point2 pixel = new Point2(
                            x * _theMap.getTileWidth(),
                            y * _theMap.getTileHeight());

                        bool intersects = false;

                        int pixelCenX = pixel.X + _theMap.getTileWidth() / 2;
                        int pixelCenY = pixel.Y + _theMap.getTileHeight() / 2;

                        m_boundingTileCircle.Center = new Vector3(pixelCenX, pixelCenY, 0);
                        m_boundingTileCircle.Radius = _theMap.getTileWidth() / 2;

                        if (Map.isTileTypeSquareBlock(tileType, m_frameIndexRendering) || (canUseSlides == false && Map.isTileTypeSlide(tileType)))
                        {
                            m_boundingTileBox = BoundingBox.CreateFromSphere(m_boundingTileCircle);
                            bool localIntersects = m_boundingCharCircle.Intersects(m_boundingTileBox);

                            if(localIntersects)
                            {
                                if (slideAgainstWalls)
                                {
                                    if (GetSlidePositionOffBlock(m_position, newPos, new Point2(pixelCenX, pixelCenY), _theMap.getTileWidth(), m_characterRadius, ref newPos))
                                    {
                                        environmentCollision = true;
                                    }
                                }
                                else
                                {
                                    intersects = true;
                                }
                            }
                        }
                        else if (Map.isTileTypeCircle(tileType))
                        {
                            intersects = m_boundingCharCircle.Intersects(m_boundingTileCircle);
                        }
                        else if (_theMap.isTileTypePixelCollision(tileType))
                        {
                            TileType pixelCheckType = _theMap.GetTileTypePixelCollision(tileType);
                            Point2 topLeft = new Point2(
                                    newPos.X - m_tileSet.getTileWidth() / 2,
                                    newPos.Y - m_tileSet.getTileHeight() / 2);
                            bool localIntersects = m_tileSet.checkForCollision(_theMap.getTileSet(), m_frameIndexCollision, topLeft, (int)pixelCheckType, pixel);

                            if (localIntersects && (!Map.isTileTypeDiagonalWall(tileType) || slideAgainstDiagonalWalls == false))
                            {
                                intersects = localIntersects;
                            }

                        }

                        if (intersects)
                        {
                            environmentCollision = true;
                            newPos = new Point2(m_position);
                        }
                    }
                }

                // 2nd pass for diagonal walls
                if (slideAgainstDiagonalWalls)
                {
                    TestPositionAgainDiagonalWalls(_theMap, minX, minY, maxX, maxY, ref environmentCollision, ref newPos);
                }

                m_boundingCharCircle.Center = new Vector3(newPos.X, newPos.Y, 0);
                m_boundingCharCircle.Radius = m_characterRadius;

                if (_characterArray != null)
                {
                    // Check against other characters
                    for (int c = 0; c < _characterArray.Length; c++)
                    {
                        if (_characterArray[c] == this || _characterArray[c].m_health <= 0 || _characterArray[c].m_finishedLevel)
                        {
                            continue;
                        }

                        BoundingSphere otherCharBounding = new BoundingSphere();
                        otherCharBounding.Center = new
                            Vector3(_characterArray[c].m_position.X, _characterArray[c].m_position.Y, 0);
                        otherCharBounding.Radius = m_characterRadius;

                        if (m_boundingCharCircle.Intersects(otherCharBounding))
                        {
                            if (m_frameIndexRendering == (int)CharacterTile.BADDY)
                            {
                                _characterArray[c].applyDamageDrain(frameTime, GameConstants.baddyDrainAmountPerSec);
                                continue;
                            }
                            // characters are facing each other
                            // This means if characters do occupy the same space (via resurrection or teleport) then they can still move appart
                            else if (IsFacing(_characterArray[c]))
                            {
                                newPos = new Point2(m_position);
                            }

                        }

                    }

                }

            }

            if (slideAgainstWalls)
            {
                m_position.X = newPos.X;
                m_position.Y = newPos.Y;
            }
            else
            {
                int realChangeX = newPos.X - m_position.X;
                int percentageX = 100;
                // This will let user get stuck on things instead of just sliding around
                if (change.X * change.X > realChangeX * realChangeX)
                {
                    percentageX = 100 * realChangeX / change.X;
                }

                int realChangeY = newPos.Y - m_position.Y;
                int percentageY = 100;
                // This will let user get stuck on things instead of just sliding around
                if (change.Y * change.Y > realChangeY * realChangeY)
                {
                    percentageY = 100 * realChangeY / change.Y;
                }

                int lowestPercentage = percentageX < percentageY ? percentageX : percentageY;

                // Calculate final position
                m_position.X += change.X * lowestPercentage / 100;
                m_position.Y += change.Y * lowestPercentage / 100;
            }

            SetMovingOnSlideState(movingOnSlide);
            return environmentCollision;
        }