Tutorials‎ > ‎

Adding a Scope to a Flixel AS3 Game

posted Jul 29, 2011, 2:12 PM by Jeff Campbell   [ updated Aug 1, 2011, 8:59 AM by Jeff Campbell ]


This is a basic scope that I added to my flixel game I am working on.  I am fairly new to this stuff so bare with me if my code isn't optimized or anything.

1. Create a new class called ScopeGroup.as
2. Copy and paste this code into the class:


package 
{
    import org.flixel.*;
    import flash.display.Shape;

    /**
     * ...
     * @author Jeff Campbell
     */
    public class ScopeGroup extends FlxGroup
    {
        //embed your crosshair image.  the crosshair graphic needs to be the perfect size to look right
        [Embed(source = "data/crosshair2.png")] protected var ImgCross:Class;
       
        //Declare Variables
        public var maskingShape:Shape; //the circle mask object
        public var crosshairs:FlxSprite; //the sprite for the crosshair graphic 
        public var mouseFollower:FlxSprite; //object to follow the mouse since FlxCamera's cant follow the mouse
        public var scopeCamera:FlxCamera; //the actual camera
       
        /**
         * Creates a Scope <code>FlxGroup</code> that includes a camera, masking, and crosshair graphic
         *
         *
         * @param    _x                X location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
         * @param    _y                Y location of the camera's display in pixels. Uses native, 1:1 resolution, ignores zoom.
         * @param    _width            The width of the camera display in pixels.
         * @param    _height            The height of the camera display in pixels.
         * @param    _zoom            The initial zoom level of the camera.  A zoom level of 2 will make all pixels display at 2x resolution.
         */
        public function ScopeGroup(_x:int, _y:int, _width:int, _height:int, _zoom:Number=0)
        {
            super();
           
           
            crosshairs = new FlxSprite(0, 0, ImgCross);
            add(crosshairs);
           
            crosshairs.offset.x = crosshairs.width / 2;
            crosshairs.offset.y = crosshairs.height / 2;
           
            scopeCamera = new FlxCamera(_x, _y, _width, _height, _zoom);
            add(scopeCamera);
           
           
            FlxG.addCamera(scopeCamera);
            FlxG.visualDebug = true;
           
           
            mouseFollower = new FlxSprite(0,0);
            mouseFollower.makeGraphic(1, 1, 0x0080FF80);
            this.add(mouseFollower);
           
            scopeCamera.follow(mouseFollower);
           
           
           
            //maskingShape = new FlxSprite(0,0, ImgCmask);
            maskingShape = new Shape;
            maskingShape.x = maskingShape.y = 0;
            maskingShape.graphics.lineStyle();
            maskingShape.graphics.beginFill(0xFFFFFF,1);
            maskingShape.graphics.drawEllipse(0,0,160,160);
            maskingShape.graphics.endFill();
           
                           
            scopeCamera.getContainerSprite().mask = maskingShape;
           
           
           
           
           
           
           
        }
       
        /**
         * Called when the weapon is fired for scope shaking effects
         *
         *
         * @param    _Intensity        Percentage of screen size representing the maximum distance that the screen can move while shaking.
         * @param    _Duration        The length in seconds that the shaking effect should last.
         */
        public function fire(_Intensity:Number=0.05, _Duration:Number=0.05):void
        {
            scopeCamera.shake(_Intensity, _Duration);
           
           
        }
       
        //update function
        override public function update():void
        {           
           
            var mousex:int = FlxG.mouse.x;
            var mousey:int = FlxG.mouse.y;
            var mousescreenx:int = FlxG.mouse.screenX;
            var mousescreeny:int = FlxG.mouse.screenY;
           
            scopeCamera.x = mousescreenx * 2 - (scopeCamera.width*1.5); //needs to be in screen coordinates x world camera scale (ex. 2)
            scopeCamera.y = mousescreeny * 2 - (scopeCamera.height*1.5); //needs to be in screen coordinates x world scale (ex. 2)
               
            maskingShape.x = (mousescreenx * 2) - maskingShape.width/2; //needs to be in screen coordinates x world camera scale (ex. 2)
            maskingShape.y = (mousescreeny * 2) - maskingShape.width/2; //needs to be in screen coordinates x world camera scale (ex. 2)
           
            maskingShape.graphics.moveTo(0, 0); //this basically redraws the mask circle and is required for some reason
               
            crosshairs.x = mousex; //needs to be in world coordinates (its scaled 2)
            crosshairs.y = mousey; //needs to be in world coordinates (its scaled 2)
           
            mouseFollower.x = mousex + 0; //needs to be in world coordinates
            mouseFollower.y = mousey + 0; //needs to be in world coordinates
           
        }
       
        //Called by flixel to help clean up memory.
        override public function destroy():void
        {
            super.destroy();

            scopeCamera = null;
            mouseFollower = null;
            crosshairs = null;           
            maskingShape = null;
        }
    }

}

3. add the variable declaration in your FlxState of the game

public var thescope:ScopeGroup;

4. create and add the scope to the stage, place this in the create function.  Please note that everything is configured to look right at this size below in a world with scale 2 and a scope that scales 3.  If you change these values, you will have to update the scope class for different offsets.  I'll make it work right sometime but for now this will get you most of the way there:
thescope = new ScopeGroup(0,0,80,80,3);
           
add(thescope);

5. Thats pretty much it.  The scope has a function called fire that for now just shakes the camera in the scope only.  call it with something like this added to your update function:
if (FlxG.mouse.justPressed())
    thescope.fire(0.1,0.1);

Here is the scope image:
If you notice it has a transparent blue hint to it to make it look nicer.

Email me with questions or comments: hourang@gmail.com