This blog has moved to a new location! http://iqandreas.github.com/
Showing posts with label class. Show all posts
Showing posts with label class. Show all posts

Friday, December 11, 2009

Debug Text has been updated - now with Documentation!

In addition to making the appearance of the blog a little nicer, I finally got around to updating and creating Documentation for DebugText.


DebugText now has it's very own hosting thanks to a very helpful contributor. :)

The library can be downloaded directly at:
http://iqandreas.isbetterthanyou.org/DebugText/DebugText_1.0.0.zip
(If anyone prefers "rar" or any other compression, just ask)

And the Documentation can be viewed directly in the browser at:
http://iqandreas.isbetterthanyou.org/DebugText/Documentation/


The ZIP file includes the class, ASDoc documentation, and and some example usage.

Check out the old thread for a few examples, all of which can also be found in the example.swf file found in the ZIP:
http://iqandreas.blogspot.com/2009/10/debugtext-onscreen-trace-replacement.html



This is taken directly from the "README.txt" file.
DebugText version 1.0

DebugText is a lightweight, onscreen, visual tracing tool.

This tool was developed because 'trace()' is not always available (like when preloading external SWFs), and the process of creating new TextFields all the time can become a bit of a hassle. The DebugText class will create a small textField on the screen that displays whatever you "trace" out, and instead of several lines of code to make this TextField, one line is enough.

There are two versions of the DebugText class. Both versions use the same code, but different packages:
  • Top level (no package name) - Place the AS file directly into your Global Classpath. Named for convenience, to avoid import statements. It can be moved to a specific package, but then an import statement is required at the top of every class that uses DebugText.
  • aRenberg.utils.DebugText - Requires import statements for each class DebugText is used in.

For sample uses, see the Examples folder.

I hereby release this code to the general public. All users are allowed to use and modify the code as they please as long as they don't publicly take credit for the code as their own work. References to where the code can be found are appreciated, but not required.


Copyright 2009 Andreas Renberg
http://iqandreas.blogspot.com/
http://iqandreas.isbetterthanyou.org/



Now I only have go get around to creating the rest of the Debug suite...

Wednesday, October 28, 2009

DebugText - Onscreen "trace" replacement

Debug text has been updated!
And, DebugText now has it's very own hosting thanks to a very helpful contributor. :) Follow this link for the current version:
http://iqandreas.isbetterthanyou.org/DebugText/DebugText_1.0.0.zip
(If anyone prefers "rar" or any other compression, just ask)

And the Documentation can be viewed directly in the browser at:
http://iqandreas.isbetterthanyou.org/DebugText/Documentation/


The ZIP file includes the class, ASDoc documentation, and and some example usage.


The blog entry with more details can be found at:
http://iqandreas.blogspot.com/2009/12/debug-text-has-been-updated-now-with.html





It's not much, but because trace is not always available (like when preloading external SWFs), and the process of creating new textFields all the time is a bit of a hassle.

The DebugText class will create a small textField on the screen that displays whatever you "trace" out, and instead of several lines, one line is enough. It's just a quick little thing I made in a few minutes, and I definitely plan on expanding on it in the future.


Usage
Place the AS file directly into your Global Classpath. It can be moved to a specific package, but then an import statement is required at the top of every class that uses DebugText.

It is possible to create a new DebugText instance, but it is not recommended. Instead, use the static function "add" to trace output onto a specific DisplayObject (such as the stage or a new or specific sprite)

The first parameter is the container for the DebugText. Note that you can trace to several different locations completely separate to one another by just passing in different values for container. Calling the "add" function several times with the same container passed in will not create multiple instances of DebugText, instead it will add text to the existing DebugText instances.

Since DebugText is a textField, the font can be changed by referencing that DebugText instance which can be made available from either "DebugText.getDebugText(container)" or the instance that is returned from "add()"

Sample
ActionScript Code:
//Outputs to the stage: Hello World!
DebugText.add(stage, "Hello World!");

//The third parameter lets you timestamp the output, but is by default set to false
//Outputs to stage: [0012428] Collision detection completed.
DebugText.add(stage, "Collision detection completed.", true);

//Removes the DebugText instance from the stage, and removes all references for garbage collection
DebugText.remove(stage);

In this example, a lot of items are going to be traced out at once:
ActionScript Code:
var nameArray:Array = ["Andreas", "Brad", "Cedric", ... ];

//Limits to a maximum of 15 lines on the screen at once
DebugText.maxDisplayedLines = 15;

//Trace out all of the names in an array
//Because of the previous line, even if there are more than 15 names in the array,
//only the LAST 15 names will still be visible.
for (var i:int = 0; i < style="color: rgb(0, 0, 255);">length; i++)
{
DebugText.add(stage, "[" + i + "]" + nameArray[i]);
}

//To save everything that has been recorded by a specific DebugText instance,
//use the "listOutput" property
var allNames:String = DebugText.getDebugText(stage).listOutput;

trace(allNames);
//Outputs the following:
// 1 Andreas
// 2 Brad
// 3 Cedric
// etc...


//For verbose output of ALL DebugText instances,
//use the static DebugText.listOutput.
var allOutput:String = DebugText.listOutput;

trace(allOutput);
//Outputs the following:
// [00001291] [object Stage] 1 Andreas
// [00001292] [object Stage] 2 Brad
// [00001292] [object Stage] 3 Cedric
// etc...

One more sample use, here you can trace out directly onto the button when it is hovered over, and hovered out:
ActionScript Code:
btn1.addEventListener(MouseEvent.ROLL_OVER, onOver);
btn2.addEventListener(MouseEvent.ROLL_OVER, onOver);
btn3.addEventListener(MouseEvent.ROLL_OVER, onOver);
// etc...

btn1.addEventListener(MouseEvent.ROLL_OUT, onOut);
btn2.addEventListener(MouseEvent.ROLL_OUT, onOut);
btn3.addEventListener(MouseEvent.ROLL_OUT, onOut);
// etc...

DebugText.maxDisplayedLines = 1;

function onOver(ev:Event)
{
DebugText.add(ev.currentTarget, "OVER");
}
function onOut(ev:Event)
{
DebugText.add(ev.currentTarget, "OUT");
}


TODO (Future updates):
  1. Allow the textField to dock to a specific part of the screen instead of just the default top left
  2. Allow each instance to have a different max characters
  3. Allow each instance to "clear screen" of all existing text
  4. Treat each trace string as an object instead of a string, allowing additional information to be added such as time when traced
  5. Allow users to add monitoring to specific properties, so when that property value changes, the new value is updated on the list (this is reserved for my LiveDebug project, still work in progress)

I didn't add these features yet because it's difficult, but only because I don't need these features yet, but if anyone has any need for them, I can easily add them.


Any more suggestions for improvement?

Fixing Vector Support in FlashDevelop

More and more of my projects are becoming entirely FlashDevelop based, as 98% of the time, I don't need to see the stage. If I do, I code everything in FlashDevelop, and debug it with Flash.

Sadly, I ran into a snag when FlashDevelop didn't want to recognize the Vector class, at least not with code completion. The solution was actually quite simple.

Make sure you have the intrinsic AS file
Browse to the directory where you have FlashDevelop stored (in my case "C:\Program Files\FlashDevelop\".

Continue browsing through to "\Library\AS3\intrinsic\FP10\".
If you have the same setup as me (the default install path) the folder should now read:
C:\Program Files\FlashDevelop\Library\AS3\intrinsic\FP10\

If that folder contains Vector.as, you are good to go on to the next step, otherwise, you either need to update to the newest FlashDevelop, and/or the newest stable release of the Adobe Flex SDK (big file)


Make sure your projects are being treated as Flash 10 and not Flash 9
Finally, (and this was the part that wasn't working for me) on the menu bar, choose Tools > Settings, or press F10.

When the dialog appears, go to "AS3Context", and make sure the "Default Flash Version" is set to 10, instead of the default 9.


While you are in there, take the time to make sure other settings are set to your preference, such as class paths and the SDK location.


If it's still not working for someone, post a comment, and I'll try to debug it.

Wednesday, September 9, 2009

Error: Error #2071: The Stage class does not implement this property or method.

Error: Error #2071: The Stage class does not implement this property or method.
at Error$/throwError()
at flash.display::Stage/set x()
at Untitled_fla::MainTimeline/frame1()[Untitled_fla.MainTimeline::frame1:1]
Similar to Error #2069, Error #2071 occurs when you try to set stage properties that have been overriden.

To quote the ActionScript 3.0 Language Reference:
Quote:
In addition, the following inherited properties are inapplicable to Stage objects. If you try to set them, an IllegalOperationError is thrown. These properties may always be read, but since they cannot be set, they will always contain default values.
  • accessibilityProperties
  • alpha
  • blendMode
  • cacheAsBitmap
  • contextMenu
  • filters
  • focusRect
  • loaderInfo
  • mask
  • mouseEnabled
  • name
  • opaqueBackground
  • rotation
  • scale9Grid
  • scaleX
  • scaleY
  • scrollRect
  • tabEnabled
  • tabIndex
  • transform
  • visible
  • x
  • y
Logically thinking, you can't really set the x, y, or rotation values of the stage, since it is supposedly "God", what everything else in Flash is measured against. Sure, if the user is running a SWF as a projector or through the debugger, they can move the dialog box around, however, this doesn't really change the x and y values of the stage, as the stage will still always be at 0,0 inside of its container.

If you want to measure any farther, you will have to start measuring in the operating system's coordinate space. That's going a little too far, and is even outside of Flash's capabilities.

Also note that the following stage properties are overriden, and throw errors if you try to set them. These are different than the properties listed above because they will hold actual values, not just the default ones, but you are still not allowed to modify them.
  • height - can be read, but throws an IllegalOperationError if set
  • width - can be read, but throws an IllegalOperationError if set
  • stageHeight - is able to be set, and will not throw an error, but it seems as though changing this property has no effect on the stage, at least not when run in the Debugger Player
  • stageWidth - is able to be set, and will not throw an error, but it seems as though changing this property has no effect on the stage, at least not when run in the Debugger Player
  • textSnapshot - cannot be read or accessed. Should be in the list above, but I'm not sure why Adobe didn't include this property to the list.

NOTE: Unless you like boring nitty gritty details, you can just stop reading right here. The rest is just for reference.

In addition, some properties and methods cannot be run outside of the stage's security sandbox without the proper permissions, so those methods are overridden just so Flash can check their security credentials. They act just as the regular methods they override with the difference that they will dispatch a SecurityError if accessed by an object outside of the current sandbox.

The affected properties all have to do with children and are "mouseChildren", "numChildren", and "tabChildren". The affected methods that have to do with containing children are addChild(), addChildAt(), removeChild(), removeChildAt(), setChildIndex(), and swapChildrenAt(). Finally, the only other affected methods have to do with Event Dispatching, and are all overriden for security checks; addEventListener(), dispatchEvent(), hasEventListener(), and willTrigger(). Strangely enough, removeEventListener(), doesn't require a security check...

However, don't bother memorizing them as these methods will act just like any other display object to outside users, and won't affect your code at all.



Thanks to Senocular for pointing much of this out.

Error: Error #2069: The Loader class does not implement this method.

Error: Error #2069: The Loader class does not implement this method.
at Error$/throwError()
at flash.display::Loader/addChild()
at Main/onXMLComplete()[C:\Documents and Settings\Andreas\Desktop\temp\menu_8_sept\Main.as: 116]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
Following this error number leads to a simple line:
ActionScript Code:
var imgLoader:Loader = new Loader();
var preloader:Preloader = new Preloader(); //Just a little custom preloader class that says "Image Loading"
imgLoader.addChild(new Preloader()); //ERROR #2069



At first thought, this should be possible. Checking the language reference, the Loader class extends "DisplayObjectContainer", so it should indeed have that function.

In fact, all of the following functions will give an error message:
  • addChild()
  • addChildAt()
  • removeChild()
  • removeChildAt()
  • setChildIndex()


The answer is hidden away in small print inside of the Language Reference:
Quote:
The Loader class overrides the following methods that it inherits, because a Loader object can only have one child display object—the display object that it loads. Calling the following methods throws an exception: addChild(), addChildAt(), removeChild(), removeChildAt(), and setChildIndex(). To remove a loaded display object, you must remove the Loader object from its parent DisplayObjectContainer child array.
So, basically, because the Loader class can only ever contain one item, you are not allowed to run functions on the loader class that change how many items are inside of the loader.

As usual, the ActionScript 3.0 Language Reference is your best friend.

Friday, April 10, 2009

Understanding the AS3 "1203 No default constructor found in base class %s. " Error

Gather 'round children, and I will describe to you the 1203 error in child friendly Layman's Terms.

"1203 No default constructor found in base class %s.
You must explicitly call the constructor of the base class with a super() statement if it has 1 or more required arguments."



When you extend a class in AS3, flash will automatically add a function that initializes the class that you are extending.

For example, let's say you have a "ship" class. When you create this class, you have a whole bunch of functions that create walls, shields, passenger compartments, motors, etc.

ActionScript Code:
public class Ship
{
public function Ship():void
{
//Here you will build the ship, and make sure it is functional.
this.buildHullAndWalls();
this.buildPassengerCompartments();
this.addElectronics();
this.addNavigation();
this.addMotors(new HyperDrive(), new SublightEngine());
this.addSheilds();

if (this.scanForDefects())
{
emailCaptain("Ship is in working order and ready to go! :) ");
}
else
{
emailCaptain("There is something wrong! There are problems with this ship still!");
throw new ShipBuildError("An error occured when building the ship. Please wait for repairs.");
}
}

}



Now, when you want to extend a class, it is like creating a new version of the parent class AND adding to it.

So to create a Cruiser (basically a basic ship with weapons), you could write all this out:
ActionScript Code:
public class Cruiser
{
public function Cruiser():void
{
//Here you will build the ship, and make sure it is functional.
this.buildHullAndWalls();
...
this.addSheilds();
this.addWeapons();

if (this.scanForDefects())
{
...
}
}

}


But doing this for each and every ship that extends the Ship is long, tedious, and memory consuming. Also, if you want to make any changes to the way the ship works (for example, adding the shields before you add the motors), you have to go back and change that code in every single ship that is built from a Ship, or extends the Ship.

So to have the Cruiser extend Ship:
ActionScript Code:
public class Cruiser extends Ship
{
public function Cruiser():void
{
this.addWeapons();
}
}



This simplifies making ships immensely, however, we have one (major) problem. Here, you are telling the crew to start adding weapons to the ship. That's fine and dandy, but where is the ship? You haven't told the crew to start building a ship yet! How are they supposed to add on the weapons?

Luckily, The Flash Compiler (known to his friends as "Foreman Flash") realizes this, so when you tell the crew to start building the ship, Flash looks through the list of tasks for the crew to do. He realizes that you are technically building a ship, and since the builders can't add anything to the ship until the ship is built, he adds a task for the builders at the start of the list. He tells them "First, build a standard ship, like the one you made for Larry last month. Then, add weapons to it, and make it a cruiser instead."

ActionScript Code:
public class Cruiser extends Ship
{
public function Cruiser():void
{
super(); //This means, do everything that the super class (or Ship) does to start out.
this.addWeapons(); //Now you can add weapons when you have a ship built!
}
}



That's OOP 101. However, sometimes things get a little more complicated than that. What if in order to build the standard Ship, the builders have to know how many passengers it will hold. Otherwise, they don't know if they should build a little or a small ship.
ActionScript Code:
public class Ship
{
public function Ship(howManyPassengers:Number):void
{
//Here you will build the ship, and make sure it is functional.
this.buildHullAndWalls();
this.buildPassengerCompartments(howManyPassengers);
this.addElectronics();
this.addNavigation();
this.addMotors(new HyperDrive(), new SublightEngine());
this.addSheilds();

if (this.scanForDefects())
{
...
}
}

}



Now we run into a problem. Foreman Flash has the task of building another Cruiser. As usual, he looks through the list to check if the ship can be built, so cruiser weapons can be added to it. Realizing that someone forgot that command, he again adds super() to the list, and the builders start working.

The builders start gathering supplies, when one person calls out "Wait a minute! How big is this ship supposed to be? Foreman Flash, we do not know how many passengers this thing will hold!"

Foreman flash looks at his clipboard again and again, but he has no idea of how big the client wanted the cruiser. He is now confused, and the builders are getting angry. Guessing a random numbe could be disasterous.

"1203 No default constructor found in base class! Help! I'm confused! No one ever told me what to do! I can't build without proper instructions!"

There is your error.


Next time, the ship buying millionare is smarter. When he orders a Cruiser, he says "I want the ship to hold 24,000 passengers. Get it done right this time."

ActionScript Code:
//This code is run elsewhere, perhaps on the main timeline
var NumberOfPassengersForMyCruiser:Number = 24000;
var MyPimpedOutCruiser:Cruiser = new Cruiser(NumberOfPassengersForMyCruiser);

//Here is the actual class located elsewhere.
public class Cruiser extends Ship
{
public function Cruiser(passengers:Number):void
{
super(passengers); //Now we add building the ship to the list so the Foreman doesn't have to worry about adding it himself.
this.addWeapons(); //Now you can add weapons, because the builders know how big the ship will be!
}
}



Another way of doing this, is perhaps there is a law in place which states that all cruisers must be built for 40,000 passengers. No more, no less.
ActionScript Code:
public class Cruiser extends Ship
{
public function Cruiser():void
{
super(40000); //Because the super() command just won't suffice!
this.addWeapons(); //Now you can add weapons, because the builders know how big the ship will be!
}
}



Or, if you are really smart, you could change the plans of the Ship design to say that, unless you hear anything differently, the ship will always be built for 30,000 passengers.

ActionScript Code:
public class Ship
{
public function Ship(howManyPassengers:Number = 30000):void
{
//Here you will build the ship, and make sure it is functional.
this.buildHullAndWalls();
this.buildPassengerCompartments(howManyPassengers);
this.addElectronics();
this.addNavigation();
this.addMotors(new HyperDrive(), new SublightEngine());
this.addSheilds();

if (this.scanForDefects())
{
...
}
}

}


Now the Cruiser class can look like this:
ActionScript Code:
public class Cruiser extends Ship
{
public function Cruiser(passengers:Number):void
{
//Don't bother adding the super() command here. The Foreman will do it automatically. That's what he's getting paid for. :)
//You can add it if you want to, but I say it is a waste of your time.
this.addWeapons();
}
}


When the Foreman looks through the list, he sees that you never told the workers start building the ship. "No problem, I'll just add the super() command here."

Then the builders receive their instructions. "First, build a ship, then add weapons to it. Wait! The foreman never told us how many passengers he want the ship to hold. Oh well, by default, they want 30,000 passengers, so we will just do what we usually do."

No errors. Everyone is happy.



Now. To go back to your code...
ActionScript Code:
package
{
import com.RadarPoint;
public class Rp1 extends RadarPoint
{
function Rp1():void
{
trace("YEAY! New RadarPoint child RP1 created!");
}
}
}


The Foreman looks through this code, and sees that you are building a RadarPoint, but you never told the workers to start building the RadarPoint! Proposterous! He quckly adds it to the list and send the workers on their way.

ActionScript Code:
import com.RadarPoint;
public class Rp1 extends RadarPoint
{
function Rp1():void
{
super(); //Added by the foreman.
trace("YEAY! New RadarPoint child RP1 created!");
}
}


So the workers look at the list, and start building a Radar Point. "Woah!! Big problem!! Foreman!!! We don't know what the values of newProp1:int, newProp2:Number, and newProp3:String are supposed to be!!"

ActionScript Code:
import flash.display.Sprite;
public class RadarPoint extends Sprite
{
function RadarPoint(newProp1:int, newProp2:Number, newProp3:String):void
{
this._prop1 = newProp1;
this._prop2 = newProp2;
this._prop3 = newProp3;
}
}



Next time, when the millinaire is ordering his brand new RP1, he remembers to tell the foreman and the builders what specifications he wants, avoiding any confusion:
ActionScript Code:
package
{
import com.RadarPoint;
public class Rp1 extends RadarPoint
{
function Rp1():void
{
super(3467, -345.37327, "Red/Blue");
trace("YEAY! New RadarPoint child RP1 created!");
}
}
}


Moral of the story, always tell Foreman Flash what to do, otherwise he gets mad and thows errors and swearwords in your way.



I should win a Pulizer.