예제 #1
0
        /// <summary>
        /// Make the camera follow an object with a specified follow-style
        /// </summary>
        /// <param name="Target"></param>
        /// <param name="Style"></param>
        public void follow(FlxObject Target, uint Style = STYLE_LOCKON)
        {
            target = Target;
            float helper, w, h;

            switch (Style)
            {
            case STYLE_PLATFORMER:
                w        = width / 8;
                h        = height / 3;
                deadzone = new FlxRect((width - w) / 2, (height - h) / 2 - h * 0.25f, w, h);
                break;

            case STYLE_TOPDOWN:
                helper   = FlxU.max(width, height) / 3;
                deadzone = new FlxRect((width - helper) / 3, (height - helper) / 3, helper, helper);
                break;

            case STYLE_TOPDOWN_TIGHT:
                helper   = FlxU.max(width, height) / 12;
                deadzone = new FlxRect((width - helper) / 2, (height - helper) / 2, helper, helper);
                break;

            case STYLE_LOCKON:
                break;

            case STYLE_LOOSE:
                deadzone = new FlxRect(0, 0, width, height);
                break;

            default:
                deadzone = null;
                break;
            }
        }
예제 #2
0
        /// <summary>
        /// Internal function used by FlxEmitter to create the particles
        /// </summary>
        /// <param name="Graphic"></param>
        /// <param name="Rotation"></param>
        /// <param name="Width"></param>
        /// <param name="Height"></param>
        /// <returns></returns>
        public FlxSprite loadParticleGraphic(Texture2D Graphic, float Rotation, float Width = 0, float Height = 0)
        {
            rotateBy = Rotation * 0.0174532925f;
            texture  = Graphic;
            int numFrames = (int)FlxU.floor(texture.Width / texture.Height);

            if (Width == 0 || Height == 0)
            {
                Width  = texture.Height;
                Height = Width;
            }
            frameWidth  = width = Width;
            frameHeight = height = Height;
            List <FlxRect> _draws = new List <FlxRect>();

            for (int i = 0; i < numFrames; i++)
            {
                FlxRect textureArea = new FlxRect(i * height, 0, width, height);
                _draws.Add(textureArea);
            }
            int    di;// = (int)Math.Round(FlxU.randomBetween(0, numFrames));
            Random r = new Random();

            di           = r.Next(numFrames);
            particleRect = _draws[di];
            //FlxRect t = _draws[di];
            sourceRect = new FlxRect(particleRect.x, particleRect.y, particleRect.width, particleRect.height);
            return(this);
        }
예제 #3
0
        /**
         * Call this function to give this object a path to follow.
         * If the path does not have at least one node in it, this function
         * will log a warning message and return.
         *
         * @param	Path		The <code>FlxPath</code> you want this object to follow.
         * @param	Speed		How fast to travel along the path in pixels per second.
         * @param	Mode		Optional, controls the behavior of the object following the path using the path behavior constants.  Can use multiple flags at once, for example PATH_YOYO|PATH_HORIZONTAL_ONLY will make an object move back and forth along the X axis of the path only.
         * @param	AutoRotate	Automatically point the object toward the next node.  Assumes the graphic is pointing upward.  Default behavior is false, or no automatic rotation.
         */
        public void followPath(FlxPath Path, float Speed = 100, uint Mode = PATH_FORWARD, bool AutoRotate = false)
        {
            if (Path.nodes.Count <= 0)
            {
                FlxG.log("WARNING: Paths need at least one node in them to be followed.");
                return;
            }

            path        = Path;
            pathSpeed   = FlxU.abs(Speed);
            _pathMode   = Mode;
            _pathRotate = AutoRotate;

            //get starting node
            if ((_pathMode == PATH_BACKWARD) || (_pathMode == PATH_LOOP_BACKWARD))
            {
                _pathNodeIndex = path.nodes.Count - 1;
                _pathInc       = -1;
            }
            else
            {
                _pathNodeIndex = 0;
                _pathInc       = 1;
            }
        }
예제 #4
0
        /// <summary>
        /// Internal function for updating the position and speed of this object.
        /// </summary>
        private void updateMotion()
        {
            float delta;
            float velocityDelta;

            velocityDelta    = (FlxU.computeVelocity(angularVelocity, angularAcceleration, angularDrag, maxAngular) - angularVelocity) / 2;
            angularVelocity += velocityDelta;
            angle           += angularVelocity * FlxG.elapsed;
            angularVelocity += velocityDelta;

            velocityDelta = (FlxU.computeVelocity(velocity.x, acceleration.x, drag.x, maxVelocity.x) - velocity.x) / 2;
            velocity.x   += velocityDelta;
            delta         = velocity.x * FlxG.elapsed;
            velocity.x   += velocityDelta;
            x            += delta;

            velocityDelta = (FlxU.computeVelocity(velocity.y, acceleration.y, drag.y, maxVelocity.y) - velocity.y) / 2;
            velocity.y   += velocityDelta;
            delta         = velocity.y * FlxG.elapsed;
            velocity.y   += velocityDelta;
            y            += delta;
        }
예제 #5
0
        private void pathLogic()
        {
            _currPos.make(x, y);

            if (moving)
            {
                makePathTimer += FlxG.elapsed;
            }
            if (makePathTimer >= 0.3)
            {
                if (FlxU.getDistance(_currPos, _lastPos) >= 5)
                {
                    //FlxG.log(FlxU.getDistance(_currPos, _lastPos));
                    _lastPos.make(x, y);
                    _nodes.Add(_lastPos);
                    if (!_indoors)
                    {
                        footsteps.emitParticle();
                    }
                    //FlxG.log("+node at ("+_currPos.x+", "+_currPos.y+")");
                }
                makePathTimer = 0;
            }
        }
예제 #6
0
        /**
         * Shoots a ray from the start point to the end point.
         * If/when it passes through a tile, it stores that point and returns false.
         *
         * @param	Start		The world coordinates of the start of the ray.
         * @param	End			The world coordinates of the end of the ray.
         * @param	Result		A <code>Point</code> object containing the first wall impact.
         * @param	Resolution	Defaults to 1, meaning check every tile or so.  Higher means more checks!
         * @return	Returns true if the ray made it from Start to End without hitting anything.  Returns false and fills Result if a tile was hit.
         */
        public bool ray(FlxPoint Start, FlxPoint End, FlxPoint Result = null, float Resolution = 1f)
        {
            float step = _tileWidth;

            if (_tileHeight < _tileWidth)
            {
                step = _tileHeight;
            }
            step /= Resolution;
            float deltaX   = End.x - Start.x;
            float deltaY   = End.y - Start.y;
            float distance = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
            int   steps    = (int)FlxU.ceil(distance / step);
            float stepX    = deltaX / steps;
            float stepY    = deltaY / steps;
            float curX     = Start.x - stepX - x;
            float curY     = Start.y - stepY - y;
            int   tileX;
            int   tileY;
            int   i = 0;

            while (i < steps)
            {
                curX += stepX;
                curY += stepY;

                if ((curX < 0) || (curX > width) || (curY < 0) || (curY > height))
                {
                    i++;
                    continue;
                }

                tileX = (int)curX / _tileWidth;
                tileY = (int)curY / _tileHeight;
                if (Convert.ToBoolean((_tileObjects[_data[tileY * widthInTiles + tileX]] as FlxTile).allowCollisions))
                {
                    //Some basic helper stuff
                    tileX *= _tileWidth;
                    tileY *= _tileHeight;
                    float rx = 0;
                    float ry = 0;
                    float q;
                    float lx = curX - stepX;
                    float ly = curY - stepY;

                    //Figure out if it crosses the X boundary
                    q = tileX;
                    if (deltaX < 0)
                    {
                        q += _tileWidth;
                    }
                    rx = q;
                    ry = ly + stepY * ((q - lx) / stepX);
                    if ((ry > tileY) && (ry < tileY + _tileHeight))
                    {
                        if (Result == null)
                        {
                            Result = new FlxPoint();
                        }
                        Result.x = rx;
                        Result.y = ry;
                        return(false);
                    }

                    //Else, figure out if it crosses the Y boundary
                    q = tileY;
                    if (deltaY < 0)
                    {
                        q += _tileHeight;
                    }
                    rx = lx + stepX * ((q - ly) / stepY);
                    ry = q;
                    if ((rx > tileX) && (rx < tileX + _tileWidth))
                    {
                        if (Result == null)
                        {
                            Result = new FlxPoint();
                        }
                        Result.x = rx;
                        Result.y = ry;
                        return(false);
                    }
                    return(true);
                }
                i++;
            }
            return(true);
        }
예제 #7
0
        // overlapsWithCallBack
        public Boolean overlapsWithCallback(FlxObject Object, Func <FlxObject, FlxObject, Boolean> Callback = null, Boolean FlipCallbackParams = false, FlxPoint Position = null)
        {
            Boolean results = false;

            float X = x;
            float Y = y;

            if (Position != null)
            {
                X = Position.x;
                Y = Position.x;
            }

            //Figure out what tiles we need to check against
            int  selectionX      = (int)FlxU.floor((Object.x - X) / _tileWidth);
            int  selectionY      = (int)FlxU.floor((Object.y - Y) / _tileHeight);
            uint selectionWidth  = (uint)(selectionX + (FlxU.ceil((int)Object.width / _tileWidth)) + 2);
            uint selectionHeight = (uint)(selectionY + (FlxU.ceil((int)Object.height / _tileHeight)) + 2);

            //Then bound these coordinates by the map edges
            if (selectionX < 0)
            {
                selectionX = 0;
            }
            if (selectionY < 0)
            {
                selectionY = 0;
            }
            if (selectionWidth > widthInTiles)
            {
                selectionWidth = (uint)widthInTiles;
            }
            if (selectionHeight > heightInTiles)
            {
                selectionHeight = (uint)heightInTiles;
            }

            //Then loop through this selection of tiles and call FlxObject.separate() accordingly
            uint    rowStart = (uint)selectionY * (uint)widthInTiles;
            uint    row      = (uint)selectionY;
            uint    column;
            FlxTile tile;
            Boolean overlapFound;
            float   deltaX = X - last.x;
            float   deltaY = Y - last.y;



            while (row < selectionHeight)
            {
                column = (uint)selectionX;
                while (column < selectionWidth)
                {
                    overlapFound = false;
                    tile         = _tileObjects[(int)_data[(int)(rowStart + column)]] as FlxTile;
                    if (Convert.ToBoolean(tile.allowCollisions))
                    {
                        tile.x      = X + (int)column * _tileWidth;
                        tile.y      = Y + (int)row * _tileHeight;
                        tile.last.x = tile.x - deltaX;
                        tile.last.y = tile.y - deltaY;
                        if (Callback != null)
                        {
                            if (FlipCallbackParams)
                            {
                                overlapFound = Callback(Object, tile);
                            }
                            else
                            {
                                overlapFound = Callback(tile, Object);
                            }
                        }
                        else
                        {
                            overlapFound = (Object.x + Object.width > tile.x) && (Object.x < tile.x + tile.width) && (Object.y + Object.height > tile.y) && (Object.y < tile.y + tile.height);
                        }
                        if (overlapFound)
                        {
                            if ((tile.callback != null))
                            {
                                tile.mapIndex = (uint)rowStart + column;
                                tile.callback(tile, Object);
                            }
                            results = true;
                        }
                    }
                    else if ((tile.callback != null))
                    {
                        tile.mapIndex = (uint)rowStart + (uint)column;
                        tile.callback(tile, Object);
                    }
                    column++;
                }
                rowStart += (uint)widthInTiles;
                row++;
            }
            return(results);
        }
예제 #8
0
        /**
         * Internal function for moving the object along the path.
         * Generally this function is called automatically by <code>preUpdate()</code>.
         * The first half of the function decides if the object can advance to the next node in the path,
         * while the second half handles actually picking a velocity toward the next node.
         */
        protected void updatePathMotion()
        {
            //first check if we need to be pointing at the next node yet
            _point.x = x + width * 0.5f;
            _point.y = y + height * 0.5f;
            FlxPoint node   = path.nodes[_pathNodeIndex];
            float    deltaX = node.x - _point.x;
            float    deltaY = node.y - _point.y;

            bool horizontalOnly = (_pathMode & PATH_HORIZONTAL_ONLY) > 0;
            bool verticalOnly   = (_pathMode & PATH_VERTICAL_ONLY) > 0;

            if (horizontalOnly)
            {
                if (((deltaX > 0)?deltaX:-deltaX) < pathSpeed * FlxG.elapsed)
                {
                    node = advancePath();
                }
            }
            else if (verticalOnly)
            {
                if (((deltaY > 0)?deltaY:-deltaY) < pathSpeed * FlxG.elapsed)
                {
                    node = advancePath();
                }
            }
            else
            {
                if (Math.Sqrt(deltaX * deltaX + deltaY * deltaY) < pathSpeed * FlxG.elapsed)
                {
                    node = advancePath();
                }
            }

            //then just move toward the current node at the requested speed
            if (pathSpeed != 0)
            {
                //set velocity based on path mode
                _point.x = x + width * 0.5f;
                _point.y = y + height * 0.5f;
                if (horizontalOnly || (_point.y == node.y))
                {
                    velocity.x = (_point.x < node.x)?pathSpeed:-pathSpeed;
                    if (velocity.x < 0)
                    {
                        pathAngle = -90;
                    }
                    else
                    {
                        pathAngle = 90;
                    }
                    if (!horizontalOnly)
                    {
                        velocity.y = 0;
                    }
                }
                else if (verticalOnly || (_point.x == node.x))
                {
                    velocity.y = (_point.y < node.y)?pathSpeed:-pathSpeed;
                    if (velocity.y < 0)
                    {
                        pathAngle = 0;
                    }
                    else
                    {
                        pathAngle = 180;
                    }
                    if (!verticalOnly)
                    {
                        velocity.x = 0;
                    }
                }
                else
                {
                    pathAngle = FlxU.getAngle(_point, node);
                    FlxU.rotatePoint(0, pathSpeed, 0, 0, pathAngle, velocity);
                }

                //then set object rotation if necessary
                if (_pathRotate)
                {
                    angularVelocity     = 0;
                    angularAcceleration = 0;
                    angle = pathAngle;
                }
            }
        }
예제 #9
0
        // update camera scroll in here
        // make sure it stays within bounds
        public override void update()
        {
            //zooming = FlxG.zoom;
            //rotating = FlxG.rotation;
            //follow closely or check deadzones
            if (target != null)
            {
                if (deadzone == null)
                {
                    focusOn(target.getMidpoint());   //add getMidpoint() for FlxObjects
                }
                else
                {
                    //FlxG.log("deadzone is not null");
                    float edge;
                    float targetX = FlxU.ceil(target.x + ((target.x > 0) ? 0.0000001f : -0.0000001f));
                    float targetY = FlxU.ceil(target.y + ((target.y > 0) ? 0.0000001f : -0.0000001f));

                    edge = targetX - deadzone.x;
                    if (scroll.x > edge)
                    {
                        scroll.x = edge;
                    }
                    edge = targetX + target.width - deadzone.x - deadzone.width;
                    if (scroll.x < edge)
                    {
                        scroll.x = edge;
                    }

                    edge = targetY - deadzone.y;
                    if (scroll.y > edge)
                    {
                        scroll.y = edge;
                    }
                    edge = targetY + target.height - deadzone.y - deadzone.height;
                    if (scroll.y < edge)
                    {
                        scroll.y = edge;
                    }

                    //SHAKE
                }
            }

            //make sure we didnt go outside camera's bounds
            if (bounds != null)
            {
                //FlxG.log("bounds is not null");
                if (scroll.x < bounds.left)
                {
                    scroll.x = bounds.left;
                }
                if (scroll.x > bounds.right - width)
                {
                    scroll.x = bounds.right - width;
                }
                if (scroll.y < bounds.top)
                {
                    scroll.y = bounds.top;
                }
                if (scroll.y > bounds.bottom - height)
                {
                    scroll.y = bounds.bottom - height;
                }
            }

            //update effects

            //shake
            if (_fxShakeDuration > 0)
            {
                _fxShakeDuration -= FlxG.elapsed;
                if (_fxShakeDuration <= 0)
                {
                    _fxShakeOffset.make();
                    if (_fxShakeComplete != null)
                    {
                        _fxShakeComplete();
                    }
                }
                else
                {
                    if ((_fxShakeDirection == SHAKE_BOTH_AXES) || (_fxShakeDirection == SHAKE_HORIZONTAL_ONLY))
                    {
                        _fxShakeOffset.x = (FlxG.random() * _fxShakeIntensity * width * 2 - _fxShakeIntensity * width) * _zoom;
                    }
                    if ((_fxShakeDirection == SHAKE_BOTH_AXES) || (_fxShakeDirection == SHAKE_VERTICAL_ONLY))
                    {
                        _fxShakeOffset.y = (FlxG.random() * _fxShakeIntensity * height * 2 - _fxShakeIntensity * height) * _zoom;
                    }
                }
            }


            scroll.x -= _fxShakeOffset.x;
            scroll.y -= _fxShakeOffset.y;

            if (zooming < 1)
            {
                zooming = 1;
            }
        }
예제 #10
0
 /// <summary>
 /// Internal random float from 0 to 1
 /// </summary>
 /// <returns></returns>
 static internal float random()
 {
     return(globalSeed = FlxU.random());
 }
예제 #11
0
        /**
         * Handles fade out, fade in, panning, proximity, and amplitude operations each frame.
         */
        override public void update()
        {
            base.update();
            if (_source != null)
            {
                x = _source.getMidpoint().x;
                y = _source.getMidpoint().y;
            }

            float radial = 1.0f;
            float fade   = 1.0f;

            //Distance-based volume control
            if (_target != null)
            {
                radial = (_radius - FlxU.getDistance(_target.getMidpoint(), new FlxPoint(x, y))) / _radius;
                if (radial < 0)
                {
                    radial = 0;
                }
                if (radial > 1)
                {
                    radial = 1;
                }
            }

            //Cross-fading volume control
            if (_fadeOutTimer > 0)
            {
                _fadeOutTimer -= FlxG.elapsed;
                if (_fadeOutTimer <= 0)
                {
                    if (_pauseOnFadeOut)
                    {
                        pause();
                    }
                    else
                    {
                        stop();
                    }
                }
                fade = _fadeOutTimer / _fadeOutTotal;
                if (fade < 0)
                {
                    fade = 0;
                }
            }
            else if (_fadeInTimer > 0)
            {
                _fadeInTimer -= FlxG.elapsed;
                fade          = _fadeInTimer / _fadeInTotal;
                if (fade < 0)
                {
                    fade = 0;
                }
                fade = 1 - fade;
            }

            if ((autoDestroy && playCount > 0) && (_sound.State != SoundState.Paused && _sound.State != SoundState.Playing))
            {
                _sound.Dispose();
            }

            _volumeAdjust = radial * fade;
            updateTransform();
        }