You are on page 1of 90

Flash without Flash

Tronster Firaxis Games / Geek House Games

Pipeline FlashDevelop setup Syntax Display Chain Events Bitmaps Pixel Bender

Pipeline

Non-Flash Flash Pipeline

+
FlashDevelop Java 1.6

+
Flex 4 SDK

=
SWF, EXE, AIR

Non-Flash Flash Pipeline


.as

.swc

FlashDevelop Setup

Three Setup Steps


1. Unzip FLEX SDK to c:\flex_sdk_4\ 2. Java SDK 1.6+ 3. Install FlashDevelop to c:\program files (x86)\FlashDevelop\

Data stored at: c:\users\thartley\AppData\Local\FlashDevelop\


your us er name h ere

Program Settings

Flex directory

Path to debug Flash Player

Create New Project

AS3 Project

Name project Location Check it!

Run
or press Ctrl-ENTER

Should see...

Demo HelloWorld

Syntax

Basics
// Comment /* Mult-line comment... No really you can have multiple lines.

*/

var myVariable : int = 32;

{ }

trace

trace( Foo is: + foo );

for loop

for ( i = 0; i < 10; ++i) { trace( i ); }

Classes
package {! ! public class Foo ! {! // Ctor ! ! function Foo() { ! ! } ! ! ! ! public function something() :void { ! ! ! trace(I just did something!); ! ! } ! ! ! ! } ! ! ! } private function something( a:int, b:Number ) :int { ! return a + Math.floor(b); }

Encapsulation
package {! ! public class Foo ! {! ! ! public var x : int; ! ! protected var y : int; ! ! private var z : int; ! ! ! ! ! ! ! ! ! ! } ! ! ! ! ! ! ! ! ! } function Foo() { } public function something() :void { ! trace(I just did something!); } private function something( a:int, b:Number ) :int { ! return a + Math.floor(b); }

Variables & Functions


package {! ! public class Foo ! {! ! ! public var d : Number; ! ! public var msg : String = answer is;

initial value arguments return type casting

! ! ! ! ! }

! ! ! ! }

public function something( a:int, b:int ):String { ! var c:uint = 0x32fa; d = 76.3; ! return msg + (a + b + c + int(d) ); }

Constructor
package {! ! public class Foo ! {! ! ! public var x : int; ! ! protected var y : int; ! ! private var z : int; ! ! ! ! ! ! ! ! ! ! } ! ! ! ! ! ! ! ! ! } function Foo() { } public function something() :void { ! trace(I just did something!); } private function something() :void { ! trace(Im hidden.); }

Ctor is special

Deriving

package { ! public class Bar extends Foo ! { ! } }

Override

package { ! public class Foo ! { ! ! public function stuff() :void ! ! { ! ! } ! } }

package { ! public class Bar extends Foo ! { ! ! override public function stuff() :void ! ! { ! ! } ! } }

new & null

var foo :Foo = new Foo(); foo = null;

this & super

private var x :int; override public function calc() :void { ! super.calc(); }

public function stuff( x:int ) :void { ! this.x = x; }

Static
package {! ! public class Foo ! {! ! ! static public var x : int; ! } }

var a:Foo = new Foo(); a.x = 12; Foo.x = 12; trace( Foo.x );

// Compiler ERROR

// 12

Global namespace
package { ! public class Foo ! {! ! ! function Foo() ! ! { ! ! } ! ! ! ! public function something() :void { ! ! ! trace(I just did something!); ! ! } ! ! ! ! } ! ! ! } private function something() :void { ! trace(Im hidden.); }

No name after package means contents are in the global namespace.

specic namespace
package com.tronster.examples { ! public class Foo ! {! ! ! function Foo() ! ! { ! ! } ! ! ! ! public function something() :void { ! ! ! trace(I just did something!); ! ! } ! ! ! ! } ! ! ! } private function something() :void { ! trace(Im hidden.); } import com.tronster.examples.Foo; package { ! public class Bar ! { ! ! private var foo:Foo; ! } }

Why namespaces?
package com.tronster.examples { ! public class Foo ! {! ! } } import com.tronster.examples.Foo; import dude.stuff; package { ! public class Bar ! { ! ! ! ! ! ! ! ! } ! ! ! ! ! ! ! } public function xyz():void { ! var foo1 :com.tronster.examples.Foo = ! ! new com.tronster.examples.Foo(); ! ! } var foo2 :dude.stuff.Foo = ! new dude.stuff.Foo();

package dude.stuff { ! public class Foo ! {! ! } }

When to use?
Game Engine Shareable class Shareable library

OVERKILL for simple lab experiments

Syntax not covered here...


interface IFoo { }

public var get mySweetProperty():int { return sugar; }

try { throw new Error(Sad Panda); } catch( e :Error ) {}

var func :Function = fooFunction;

Intermission...
Wonder.net

Display Chain

Native Displayable Types


Stage Bitmap Shape

MovieClip

TextField

Sprite

Without Flash IDE


Stage Bitmap Shape

MovieClip

TextField

Sprite

Hierarchy
Object DisplayObject Shape Bitmap

Texteld DisplayObjectContainer Sprite Stage

Multiple Lists
Stage Bitmap Sprite Bitmap

Sprite

Sprite

On Screen

Bitmap

Hidden

Sprite.graphics

graphics.beginFill( 0xff0000, 1.0 ); graphics.drawCircle( 0, 0, 100 ); graphics.endFill();

addChild( )

var foo :Sprite = new Sprite(); stage.addChild( foo );

Our Sprite
// OurSprite.as import flash.display.Sprite; package { ! public class OurSprite extends Sprite { ! ! ! ! ! ! } ! ! ! ! ! } function OurSprite() { ! graphics.beginFill( 0xff0000 ); ! graphics.drawCircle( 0, 0, 100 ); ! graphics.endFill(); }

// In Main.as init() stage.addChild( new OurSprite() );

Control Placement
// In Main.as ... ! ! private function init( e:Event = null ) :void {! ! removeEventListener( ! ! Event.ADDED_TO_STAGE, init); ! ! ! ! } var os:OurSprite = new OurSprite(); stage.addChild( os ); os.x = stage.stageWidth * 0.5; os.y = stage.stageHeight * 0.5;

Demo Circle

Events

Registering Event Listeners


package { ! import flash.display.Sprite; ! import flash.events.Event; ! ! public class Main extends Sprite ! {! ! ! ! public function Main():void ! ! { ! ! ! if (stage) init(); ! ! ! else addEventListener( Event.ADDED_TO_STAGE, init ); ! ! } ! ! ! ! private function init(e:Event = null) :void ! ! { ! ! ! removeEventListener( Event.ADDED_TO_STAGE, init ); ! ! ! // entry point ! ! }! ! ! } }

Event name (just a string) function to call The function with an event argument removal takes same parameters as add

Flash Players Racetrack

player events

user code

render

time

ENTER_FRAME

addEventListener( Event.ENTER_FRAME, onFrame );

//...

private function onFrame( e:Event ) :void { ! trace(entering a frame...) }

Typical

player events user code

nothing

render

time

Time is wasted each frame

wasted time

wasted time

wasted time

frame 1

frame 2

frame 3

Optimal

player events

user code

player events

user code

render

logic

draw

Timer & getTimer()


package { ! import flash.display.Sprite; ! import flash.events.TimerEvent; ! import flash.utils.getTimer; ! import flash.utils.Timer; ! ! public class Main extends Sprite { ! ! private const DELAY! : int = 20; ! ! private var timer!! : Timer; ! ! ! ! public function Main() :void { ! ! ! timer = new Timer( DELAY ); ! ! ! timer.addEventListener( TimerEvent.TIMER, onTick ); ! ! ! timer.start(); ! ! } ! ! ! ! private function onTick( e:TimerEvent ) :void { ! ! ! trace( "Tick at: " + getTimer() + "ms"); ! ! } ! } }

Demo TickTock

KeyboardEvent

KEY_DOWN
import flash.events.KeyboardEvent;

stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyDown );

private function onKeyDown( e:KeyboardEvent ) :void { ! trace( "You pressed: " + e.keyCode + ", " + e.charCode ); }

hardware code, unique to each button

ascii, unique to each character

MouseEvent

CLICK, localX, localY


import flash.events.MouseEvent;

stage.addEventListener( MouseEvent.CLICK, onMouseClick );

private function onMouseClick( e:MouseEvent ) :void { ! graphics.beginFill( Math.random() * 0xffffff ); ! graphics.drawCircle( e.localX, e.localY, 30 ); ! graphics.endFill(); }

relative to object

Demo Input

Bitmaps

Bitmap vs BitmapData
Stage Bitmap Bitmap BitmapData

BitmapData
setPixel() setPixel32() noise() perlinNoise() scroll() paletteMap() more...

Adding Bitmap to Display


private function init(e:Event = null):void { ! removeEventListener(Event.ADDED_TO_STAGE, init); ! ! ! ! var bitmapData :BitmapData = new BitmapData( 100, 100 ); ! bitmapData.perlinNoise( 100, 100, 5, 0, false, false ); ! ! } var bitmap :Bitmap = new Bitmap( bitmapData ); addChild( bitmap );

Reusing BitmapData
private function init(e:Event = null):void { ! removeEventListener(Event.ADDED_TO_STAGE, init); ! ! ! ! var bitmapData:BitmapData = new BitmapData( 100, 100 ); ! bitmapData.perlinNoise( 100, 100, 5, 0, false, false ); ! ! ! ! ! ! ! } var for { ! ! ! ! } bitmap:Bitmap; (var i:int = 0; i < 10; ++i) bitmap = new Bitmap( bitmapData ); addChild( bitmap ); bitmap.x = (i % 3) * bitmapData.width; bitmap.y = int(i * 0.33) * bitmapData.height;

Demo BitmapDrawing

External Graphics

[Embed("../lib/jump0007.png")] private var png7:Class;

addChild( new png7() );

Animation
// In class definition [Embed("../lib/image1.png")] private var png1:Class; [Embed("../lib/image2.png")] private var png2:Class; private var bitmap :Bitmap; private var bitmapData1 :BitmapData; private var bitmapData2 :BitmapData;

// In init bitmapData1 = (new png1() as Bitmap).bitmapData; bitmapData2 = (new png2() as Bitmap).bitmapData; addChild( bitmap = new Bitmap( bitmapData1 ) );

// In ENTER_FRAME handler switch( frame % 2 ) { ! case 0: bitmap.bitmapData = bitmapData1; break; ! case 1: bitmap.bitmapData = bitmapData2; break; }

Demo ExternalGraphics

Pixel Bender

myBitmap.filters = [ new BevelFilter() ];

myBitmap.filters = [ new BevelFilter(), new GlowFilter() ];

Filters
BevelFilter BlurFilter ColorMatrixFilter ConvolutionFilter DisplacementMapFilter DropShadowFilter GlowFilter GradientBevelFilter GradientGlowFilter ShaderFilter

Filters
BevelFilter BlurFilter ColorMatrixFilter ConvolutionFilter DisplacementMapFilter DropShadowFilter GlowFilter GradientBevelFilter GradientGlowFilter ShaderFilter

Filters
BevelFilter BlurFilter ColorMatrixFilter ConvolutionFilter DisplacementMapFilter DropShadowFilter GlowFilter GradientBevelFilter GradientGlowFilter ShaderFilter

Filters
BevelFilter BlurFilter ColorMatrixFilter ConvolutionFilter DisplacementMapFilter DropShadowFilter GlowFilter GradientBevelFilter GradientGlowFilter ShaderFilter

Demo Filters

void evaluatePixel() { float twirlAngleRadians = radians(twirlAngle); float2 relativePos = outCoord() - center; float distFromCenter = length( relativePos ); distFromCenter /= radius; float adjustedRadians; float sincWeight = sin( distFromCenter ) * twirlAngleRadians / ( distFromCenter ); float gaussWeight = exp( -1.0 * distFromCenter * distFromCenter ) * twirlAngleRadians; adjustedRadians = (distFromCenter == 0.0) ? twirlAngleRadians : sincWeight; adjustedRadians = (gaussOrSinc == 1) ? adjustedRadians : gaussWeight; float cosAngle = cos( adjustedRadians ); float sinAngle = sin( adjustedRadians ); float2x2 rotationMat = float2x2( cosAngle, -sinAngle, sinAngle, cosAngle );

relativePos = rotationMat * relativePos; outputColor = sampleLinear( oImage, relativePos + center ); }

=
.pbk Pixel Bender Toolkit

0100111 1011101 0110101 0111100

.pbj

=
.pbk Pixel Bender

0100111 1011101 0110101 0111100

+
.as

.pbj

Vanilla Flash

[Embed("../lib/twirl.pbj", mimeType ="application/octet-stream")] private var twirltPbj :Class;! private var shader :Shader;

[Embed("../lib/twirl.pbj", mimeType ="application/octet-stream")] private var twirltPbj :Class;!

create shader

private var shader ...

:Shader;

shader parameters

shader = new Shader( new twirltPbj() as ByteArray ); shader.data.radius.value = [102.3];!! // float shader.data.center.value = [70, 30];! // float2 (x,y) shader.data.twirlAngle.value = [ 84 ];! // float ! ! ! bitmap.filters = [ new ShaderFilter( shader ) ];

set shader on an object

Demo Bending Pixels

Thank You
tronster.com

Misc

Dynamic
import flash.utils.getQualifiedClassName; import flash.utils.getDefinitionByName;

var typeName :String = getQualifiedClassName( object ); var type :Class = getDefinitionByName( typeName ) as Class; var myObj :type = new type();

Singleton
package { ! public class Foo ! {! ! ! static private var instance :Foo; ! ! ! ! ! ! ! ! } ! ! ! ! ! ! ! } static public function getInstance(): Foo { ! if (instance == null) ! ! instance = new Foo( new Lock() ); ! return instance; } function Foo( k:Lock ) { }

internal class Lock { }

Container classes
var obj :Object = {};

var arr :Array = [];

var dict :Dictionary = new Dictionary();

var vec :Vector.<int> = new Vector.<int>();

Multitouch (BETA)
import flash.ui.Multitouch;

flash.events.TouchEvent flash.events.GestureEvent flash.events.GesturePhase flash.events.TransformGestureEvent flash.events.PressAndTapGestureEvent

mySprite.addEventListener( TouchEvent.TOUCH_TAP, onTap );

Additional: Dispose pattern Doc? Sound Pre-processor CONFIG::Debug