I have the following code in the Game.as:
package
{
import flash.display.Bitmap;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
import starling.textures.Texture;
import starling.utils.deg2rad;
public class Game extends Sprite
{
private const NUM_SAUSAGES: uint = 400;
private var sausagesVector: Vector.<Image> = new Vector.<Image>(NUM_SAUSAGES, true);
[Embed(source = "../media/textures/sausage.png")]
private static const Sausage: Class;
public function Game()
{
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e: Event): void
{
var sausageBitmap: Bitmap = new Sausage();
var texture: Texture = Texture.fromBitmap(sausageBitmap);
for (var i: int = 0; i < NUM_SAUSAGES; ++i)
{
var image: Image = new Image(texture);
image.alpha = Math.random();
image.x = Math.random() * stage.stageWidth;
image.y = Math.random() * stage.stageHeight;
image.rotation = deg2rad(Math.random() * 360);
addChild(image);
sausagesVector[i] = image;
}
}
}
}
But when I run the code it gives me the following error:
ReferenceError: Error #1065: Variable Game_Sausage is not defined.
What is the problem with the code because I have no idea?
I don't know the notation but I would hazard a guess that:
private static const Sausage: Class;
is never assigned, but defined as const. The [Embed] might not be finding the file?
a quick google found:
http://www.flexer.info/2009/05/01/getdefinitionbyname-error-variable-is-not-defined/
which might or might not be relevant
Related
I have been digging for custom Flex preloaders and they all seem to rely on the same template:An SWC is created with Flash CS5 and then used by Flash Builder using the "preloader" application property.
I don't own Flash CS, and it feels that Flash builder should be able to do the trick.
I created a Library Project in Flash Builder with the following bare bones code:
package loader
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.utils.getTimer;
import mx.events.RSLEvent;
import mx.preloaders.DownloadProgressBar;
import mx.preloaders.SparkDownloadProgressBar;
public class Preloader extends SparkDownloadProgressBar
{
[Embed(source="loaderlogo.png")] public var logoClass:Class;
private var _displayStartCount:uint = 0;
private var _initProgressCount:uint = 0;
private var _downloadComplete:Boolean = false;
private var _showingDisplay:Boolean = false;
private var _startTime:int;
// private var preloaderDisplay:PreloaderDisplay;
private var rslBaseText:String = "loading: ";
public function Preloader()
{
super();
}
/**
* Event listener for the <code>FlexEvent.INIT_COMPLETE</code> event.
* NOTE: This event can be commented out to stop preloader from completing during testing
*/
override protected function initCompleteHandler(event:Event):void
{
dispatchEvent(new Event(Event.COMPLETE));
}
/**
* Creates the subcomponents of the display.
*/
override protected function createChildren():void
{
var img:DisplayObject = new logoClass();
img.x = Math.round( ( stageWidth - img.width) / 2);
img.y = Math.round( ( stageHeight - img.height) / 2);
addChild( img);
var dpb:DownloadProgressBar = new DownloadProgressBar();
dpb.x = img.x + 100;
dpb.y = img.x + 100;
dpb.width = 170;
dpb.height = 20;
addChild( dpb);
}
/**
* Event listener for the <code>RSLEvent.RSL_PROGRESS</code> event.
**/
override protected function rslProgressHandler(evt:RSLEvent):void {
if (evt.rslIndex && evt.rslTotal) {
//create text to track the RSLs being loaded
rslBaseText = "loading RSL " + evt.rslIndex + " of " + evt.rslTotal + ": ";
}
}
/**
* indicate download progress.
*/
override protected function setDownloadProgress(completed:Number, total:Number):void {
}
/**
* Updates the inner portion of the download progress bar to
* indicate initialization progress.
*/
override protected function setInitProgress(completed:Number, total:Number):void {
}
/**
* Event listener for the <code>FlexEvent.INIT_PROGRESS</code> event.
* This implementation updates the progress bar
* each time the event is dispatched.
*/
override protected function initProgressHandler(event:Event):void {
var elapsedTime:int = getTimer() - _startTime;
_initProgressCount++;
if (!_showingDisplay && showDisplayForInit(elapsedTime, _initProgressCount)) {
_displayStartCount = _initProgressCount;
show();
// If we are showing the progress for the first time here, we need to call setDownloadProgress() once to set the progress bar background.
setDownloadProgress(100, 100);
}
if (_showingDisplay) {
// if show() did not actually show because of SWFObject bug then we may need to set the download bar background here
if (!_downloadComplete) {
setDownloadProgress(100, 100);
}
setInitProgress(_initProgressCount, initProgressTotal);
}
}
private function show():void
{
// swfobject reports 0 sometimes at startup
// if we get zero, wait and try on next attempt
if (stageWidth == 0 && stageHeight == 0)
{
try
{
stageWidth = stage.stageWidth;
stageHeight = stage.stageHeight
}
catch (e:Error)
{
stageWidth = loaderInfo.width;
stageHeight = loaderInfo.height;
}
if (stageWidth == 0 && stageHeight == 0)
return;
}
_showingDisplay = true;
createChildren();
}
}
}
For short, it's loading a logo and a progress bar
It displays a preloader, but really late in the loading process. As if it was being loaded after Flex.
Do I need to compile this in CS5 to completely avoid use of MX/Spark?
You shouldn't use any components in preloader. Try to remove you imports (Ctrl+Shift+O):
import mx.controls.Image;
import spark.components.Label;
Use TextField and Loader instead if needed. I'm not sure about DownloadProgressBar component.
Also don't use create children in preloader. Here is one working sample:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import mx.core.mx_internal;
import mx.preloaders.SparkDownloadProgressBar;
use namespace mx_internal;
public class Preloader extends SparkDownloadProgressBar {
private var preloaderLogo : MovieClip;
private var loadingText : TextField;
private var loadingProgress : TextField;
private var _initProgressCount : uint = 0;
private var textFormat : TextFormat = new TextFormat("Verdana", 16, 0x666666, true);
public function Preloader() {
super();
textFormat.align = "center";
}
override public function set preloader(value : Sprite) : void {
super.preloader = value;
if (!preloaderLogo) {
preloaderLogo = new Assets.PRELOADER_LOGO; // kakaranet logo
var startX : Number = Math.round((stageWidth - preloaderLogo.width) / 2);
var startY : Number = Math.round(stageHeight / 2 - preloaderLogo.height) - 100;
preloaderLogo.x = startX;
preloaderLogo.y = startY;
loadingText = new TextField();
loadingProgress = new TextField();
loadingText.width = stageWidth;//to allow center align
loadingProgress.width = stageWidth;
loadingText.text = "Loading...";
loadingText.y = preloaderLogo.y + preloaderLogo.height + 20;
loadingProgress.text = "0%";
loadingProgress.y = loadingText.y + loadingText.textHeight + 10;
addChild(preloaderLogo);
addChild(loadingText);
addChild(loadingProgress);
loadingText.setTextFormat(textFormat);
loadingProgress.setTextFormat(textFormat);
}
}
override protected function progressHandler(event : ProgressEvent) : void {
super.progressHandler(event);
if (loadingProgress) {
loadingProgress.text = Math.floor(event.bytesLoaded / event.bytesTotal * 100) + "%";
loadingProgress.setTextFormat(textFormat);
}
}
override protected function completeHandler(event : Event) : void {
loadingText.text = "Ready!";
loadingText.setTextFormat(textFormat);
preloaderLogo.stop();
}
override protected function initProgressHandler(event : Event) : void {
super.initProgressHandler(event);
//similar to super
_initProgressCount++;
if (loadingProgress) {
loadingProgress.text = "100% / " + Math.floor(_initProgressCount / initProgressTotal * 100) + "%";
loadingProgress.setTextFormat(textFormat);
}
}
}
}
If you create a popup via:
PopUpManager.addPopUp( popup, this, false );
PopUpManager.bringToFront( popup );
It will create a popup and bring it on top of any other visual piece. I have one problem though. This 'popup' needs to stay up even when the user interacts with the background.
I would use modal, but I need the ability to interact with the back. Any way to tell the popup manager not to remove the popup when the user clicks off of it?
Thanks!
here's a helper class which would help you (tested only in Flex 4, but probably could be changed for Flex 3 too):
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.core.mx_internal;
import mx.managers.ISystemManager;
import mx.managers.systemClasses.ActiveWindowManager;
use namespace mx_internal;
public class PopupHelper
{
private var popup : DisplayObject;
private var systemManager : ISystemManager;
public function PopupHelper(popup : DisplayObject, systemManager : ISystemManager) : void
{
this.popup = popup;
this.systemManager = systemManager;
}
public function forceToFront() : void
{
systemManager.addEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown);
popup.addEventListener(Event.REMOVED_FROM_STAGE, onPopupRemoved)
}
private function onSystemMouseDown(e : MouseEvent) : void
{
bringToFront(popup);
}
private function onPopupRemoved(e : Event) : void
{
popup.removeEventListener(Event.REMOVED, onPopupRemoved);
systemManager.removeEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown);
}
private function bringToFront(popup : DisplayObject) : void
{
var windowManager : ActiveWindowManager = systemManager.getImplementation("mx.managers::IActiveWindowManager") as ActiveWindowManager;
var index : int = systemManager.getChildIndex(popup);
var newIndex : int = index;
var n : int = windowManager.forms.length;
for (var j : int = 0; j < n; j++)
{
var f : DisplayObject = windowManager.forms[j];
if (systemManager.contains(f))
if (systemManager.getChildIndex(f) > index)
newIndex = Math.max(systemManager.getChildIndex(f), newIndex);
}
if (newIndex > index)
{
systemManager.setChildIndex(popup, newIndex);
}
}
}
Here's a test example:
import helperClasses.PopupHelper;
import mx.managers.PopUpManager;
import spark.components.TitleWindow;
public function showPopup() : void
{
var popup1 : TitleWindow = new TitleWindow();
popup1.title = "Popup 1";
new PopupHelper(popup1, systemManager).forceToFront();
var popup2 : TitleWindow = new TitleWindow();
popup2.title = "Popup 2";
PopUpManager.addPopUp(popup1, this, false);
PopUpManager.addPopUp(popup2, this, false);
PopUpManager.bringToFront(popup1);
popup1.x = 20;
popup1.y = 20;
}
I had tired loading an image form a url below is my sample code , when tried to load a large image which is greater than 8191 pixel in width or height the Event.COMPLETE is not dispatched , i am aware of the flash player 10 BitmapData limit ,so cant we load an image greater than this 8191 pixel limit ?is there any workaround for this Or any other method you suggest in doing ?
private function loadImage(url:String):void
{
var request:URLRequest = new URLRequest(url);
var imageLoader:Loader = new Loader();
var context:LoaderContext;
context = new LoaderContext();
context.checkPolicyFile = true;
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, image_completeHandler);
imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imageLoader.load(request,context);
}
private function image_completeHandler(event:Event):void
{
trace(" Image load Complete");
}
private function ioErrorHandler(event:IOErrorEvent):void
{
trace("ioErrorHandler: " + event);
}
I would recommend that you split up the images. If you need Flash to handle the images as one (moving, scaling) I would write a holder-class that adds the image pieces as children of the itself.
I added some code and a link to a test below. Look at the code in action here. (wait for the SWF to load).
//TestClass
package
{
import com.kazumakzak.display.TileImage;
import flash.display.Sprite;
import flash.events.Event;
public class TestBigImage extends Sprite
{
[Embed(source="assets/piece.png")]
private var imageClass : Class;
private var _image : TileImage;
private var _counter : Number = 0;
public function TestBigImage()
{
// create image with tile size 640x480
_image = new TileImage(640, 480);
// add tiles at positions
_image.addTile(new imageClass(), 1, 1);
_image.addTile(new imageClass(), 1, 2);
_image.addTile(new imageClass(), 2, 1);
_image.addTile(new imageClass(), 2, 2);
_image.addTile(new imageClass(), 3, 1);
_image.addTile(new imageClass(), 3, 2);
// add to display list
addChild(_image);
addEventListener(Event.ENTER_FRAME, render);
}
private function render(event : Event) : void
{
_counter += 0.05;
_image.x = -640 + Math.cos(_counter) * 640
}
}
}
//TileImage.as
package com.kazumakzak.display
{
import flash.display.Bitmap;
import flash.display.Sprite;
public class TileImage extends Sprite
{
private var _tileWidth : int;
private var _tileHeight : int;
public function TileImage(tileWidth : int, tileHeight : Number)
{
_tileWidth = tileWidth;
_tileHeight = tileHeight;
}
public function addTile(source : Bitmap, tileX : int, tileY : int) : void
{
source.x = (tileX-1) * _tileWidth;
source.y = (tileY-1) * _tileHeight;
addChild(source);
}
}
}
Has anyone successfully implemented a custom preloader in Flex 4? In my experience, when I specify a custom preloader using the preloader="com.foo.MyPreloader" in the Application tag, the preloader does not display until the SWF is completely downloaded, defeating the purpose of the preloader! Perhaps this is a bug in the still-beta Flex 4 framework?
I've been using this example in many Flex3 projects. It's still working with Flex4 sdk:
I can remember where I get it from. And you are right when you say it's important that this script is NOT referencing anything...
<s:Application tag ... preloader="com.YYY.XXX.shell.view.CustomPreloader"
CustomPreloader
package com.YYY.XXX.shell.view
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import mx.events.FlexEvent;
import mx.preloaders.DownloadProgressBar;
public final class CustomPreloader
extends DownloadProgressBar
{
public var loader : LoadScreen;
private var _timer : Timer;
public function CustomPreloader()
{
super();
}
override public function initialize() : void
{
super.initialize();
this.loader = new LoadScreen();
this.addChild(this.loader);
this._timer = new Timer(1);
this._timer.addEventListener(TimerEvent.TIMER, handleTimerTick);
this._timer.start();
}
override public function set preloader(preloader : Sprite):void
{
preloader.addEventListener(ProgressEvent.PROGRESS, SWFDownLoadScreen);
preloader.addEventListener(Event.COMPLETE, SWFDownloadComplete);
preloader.addEventListener(FlexEvent.INIT_PROGRESS, FlexInitProgress);
preloader.addEventListener(FlexEvent.INIT_COMPLETE, FlexInitComplete);
}
private function SWFDownLoadScreen(event : ProgressEvent) : void
{
var prog : Number = event.bytesLoaded / event.bytesTotal * 100;
if (this.loader)
{
this.loader.progress = prog;
}
}
private function handleTimerTick(event : TimerEvent) : void
{
this.stage.addChild(this);
this.loader.x = (this.stageWidth - this.loader.width) / 2;
this.loader.y = (this.stageHeight - this.loader.height) / 2;
this.loader.refresh();
}
private function SWFDownloadComplete(event : Event) : void {}
private function FlexInitProgress(event : Event) : void {}
private function FlexInitComplete(event : Event) : void
{
this.loader.ready = true;
this._timer.stop();
this.dispatchEvent(new Event(Event.COMPLETE));
}
override protected function showDisplayForInit(elapsedTime:int, count:int):Boolean
{
return true;
}
override protected function showDisplayForDownloading(elapsedTime:int,
event:ProgressEvent):Boolean
{
return true;
}
}
}
LoadScreen
package com.YYY.XXX.shell.view
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Sprite;
import flash.utils.ByteArray;
import mx.graphics.codec.PNGEncoder;
public class LoadScreen extends Loader {
//~ Settings ----------------------------------------------------------
private static var _BarWidth : int = 153; // Progress bar width
private static var _BarHeight : int = 12; // Progress bar height
private static var _LogoHeight : int = 153; // Logo picture height
private static var _LogoWidth : int = 68; // Logo picture width
private static var _Padding : int = 5; // Spacing between logo and progress bar
private static var _LeftMargin : int = 0; // Left Margin
private static var _RightMargin : int = 0; // Right Margin
private static var _TopMargin : int = 1; // Top Margin
private static var _BottomMargin : int = 1; // Bottom Margin
private static var _BarBackground : uint = 0xFFFFFF; // background of progress bar
private static var _BarOuterBorder : uint = 0x737373; // color of outer border
private static var _BarColor : uint = 0x6F9FD5; // color of prog bar
private static var _BarInnerColor : uint = 0xFFFFFF; // inner color of prog bar
//~ Instance Attributes -----------------------------------------------
[Embed(source="/asset/embed/img/XXX.gif")]
private var MyLogoClass: Class;
private var _logo : Bitmap;
private var _logoData : BitmapData;
private var isReady : Boolean = false;
public var progress : Number;
//~ Constructor -------------------------------------------------------
public function LoadScreen()
{
super();
this.progress = 0;
this._logo = new MyLogoClass as Bitmap;
}
//~ Methods -----------------------------------------------------------
public function refresh() : void
{
this._logoData = this.draw();
var encoder : PNGEncoder = new PNGEncoder();
var bytes : ByteArray = encoder.encode(this._logoData);
this.loadBytes(bytes);
}
override public function get width() : Number
{
return Math.max(_BarWidth, _LogoWidth) + _LeftMargin + _RightMargin;
}
override public function get height() : Number
{
return _LogoHeight + _BarHeight + _Padding + _TopMargin + _BottomMargin;
}
private function draw() : BitmapData
{
// create bitmap data to create the data
var data : BitmapData = new BitmapData(this.width, this.height, true, 0);
// draw the progress bar
var s : Sprite = new Sprite();
var g : Graphics = s.graphics;
// draw the bar background
g.beginFill(_BarBackground);
g.lineStyle(2, _BarOuterBorder, 1, true);
var px : int = (this.width - _BarWidth) / 2;
var py : int = _TopMargin + _LogoHeight + _Padding;
g.drawRoundRect(px, py, _BarWidth, _BarHeight, 2);
var containerWidth : Number = _BarWidth - 4;
var progWidth : Number = containerWidth * this.progress / 100;
g.beginFill(_BarColor);
g.lineStyle(1, _BarInnerColor, 1, true);
g.drawRect(px + 1, py + 1, progWidth, _BarHeight - 3);
data.draw(s);
// draw the logo
data.draw(this._logo.bitmapData, null, null, null, null, true);
return data;
}
public function set ready(value : Boolean) : void
{
this.isReady = value;
this.visible = !this.isReady;
}
public function get ready() : Boolean { return this.isReady; }
}
}
I feel dumb...I was referencing one of my main application classes from within the preloader, thus causing all of my classes to be compiled into the preloader, meaning it cannot display the preloader until everything is loaded.
For future reference: Double-check every reference in your preloader, make sure you use nothing more than what is absolutely necessary
There is a Flex 4 Custom Preloader code sample here http://www.leavethatthingalone.com/blog/index.cfm/2009/11/11/Flex4CustomPreloader
I have an image (mx) and i want to get the uint of the pixel that was clicked.
Any ideas?
A few minutes on the BitmapData LiveDoc Page will take you where you need to go. Once you have your image loaded into a Bitmap variable, you can access its BitmapData property. Add a Mouse Click Event Listener to the image and then use BitmapData::getPixel. The example for getPixel shows how to convert the uint response to an rgb hex code.
Here's a modification of the Example given on the BitmapData page that worked for me (using mxmlc - YMMV):
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
public class BitmapDataExample extends Sprite {
private var url:String = "santa-drunk1.jpg";
private var size:uint = 200;
private var image:Bitmap;
public function BitmapDataExample() {
configureAssets();
}
private function configureAssets():void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
var request:URLRequest = new URLRequest(url);
loader.load(request);
addChild(loader);
}
private function completeHandler(event:Event):void {
var loader:Loader = Loader(event.target.loader);
this.image = Bitmap(loader.content);
this.addEventListener(MouseEvent.CLICK, this.clickListener);
}
private function clickListener(event:MouseEvent):void {
var pixelValue:uint = this.image.bitmapData.getPixel(event.localX, event.localY)
trace(pixelValue.toString(16));
}
}
}
Here's an even simpler implementation. All you do is take a snapshot of the stage using the draw() method of bitmapData, then use getPixel() on the pixel under the mouse. The advantage of this is that you can sample anything that's been drawn to the stage, not just a given bitmap.
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.*;
stage.addEventListener(MouseEvent.CLICK, getColorSample);
function getColorSample(e:MouseEvent):void {
var bd:BitmapData = new BitmapData(stage.width, stage.height);
bd.draw(stage);
var b:Bitmap = new Bitmap(bd);
trace(b.bitmapData.getPixel(stage.mouseX,stage.mouseX));
}
Hope this is helpful!
Edit:
This edited version uses a single BitmapData, and removes the unnecessary step of creating a Bitmap. If you're sampling the color on MOUSE_MOVE then this is essential to avoid memory issues.
Note: if you're using a custom cursor sprite you'll have to use an object other than 'state' or else you'll be sampling the color of the custom sprite instead of what's under it.
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.*;
private var _stageBitmap:BitmapData;
stage.addEventListener(MouseEvent.CLICK, getColorSample);
function getColorSample(e:MouseEvent):void
{
if (_stageBitmap == null) {
_stageBitmap = new BitmapData(stage.width, stage.height);
}
_stageBitmap.draw(stage);
var rgb:uint = _stageBitmap.getPixel(stage.mouseX,stage.mouseY);
var red:int = (rgb >> 16 & 0xff);
var green:int = (rgb >> 8 & 0xff);
var blue:int = (rgb & 0xff);
trace(red + "," + green + "," + blue);
}
This is not specific to Flex or mx:Image, and allows you to grab a pixel color value from any bitmap drawable object (provided you have permission):
private const bitmapData:BitmapData = new BitmapData(1, 1);
private const matrix:Matrix = new Matrix();
private const clipRect:Rectangle = new Rectangle(0, 0, 1, 1);
public function getColor(drawable:IBitmapDrawable, x:Number, y:Number):uint
{
matrix.setTo(1, 0, 0, 1, -x, -y)
bitmapData.draw(drawable, matrix, null, null, clipRect);
return bitmapData.getPixel(0, 0);
}
You could easily grab a pixel from the stage or your mx:Image instance. It's a lot more efficient than drawing the entire stage (or drawable object), and should be fast enough to hook up to MouseEvent.MOUSE_MOVE for instant visual feedback.