AS3 SharedObject, unique var? - actionscript-3

I'm playing around in AS3 and trying to make a easy note application.
So I thought that I would store the notes with SharedObject so is it possible to somehow say so.data.myVariable and get/create that shared object dynamically?
I've googled but don't find anything?
EDIT: My solution!
I managed to fix it after many hours of thinking!
In Main.as when creating the Object.
addChild(Obj)
Obj.setUniqueID(SomeID);
In my class that would contain the sharedObject. (Object.as)
public function setUniqueID(uniqueID:String):void
{
soData = SharedObject.getLocal(uniqueID);
}

I think is possible actually SharedObject.data is object that dynamic class so we can create property.Please follow bellow code.
public var sharedObj:SharedObject;
private function initSharedObject():void{
sharedObj = SharedObject.getLocal("myNotes");
}
private function clearAllNotes():void
{
sharedObj.clear();
}
private function saveNote(variableName:String,valueToSave:*/* need to specify your type */):void
{
sharedObj.data[variableName] = valueToSave;
sharedObj.flush();
}
private function getNote(variableName:String):* /* need to specify your type */
{
return sharedObj.data[variableName];
}
More details http://learn.adobe.com/wiki/display/Flex/Shared+Objects
http://livedocs.adobe.com/flex/3/html/help.html?content=lsos_2.html

Related

Can I still create Global variables in AS3

Following the answer here, I have created a file called MyGlobals.as and placed some global variables and functions so that I can access it from anywhere within my project just like AS3 buil-in functions such as trace() method.
This is MyGlobals.as which is located in the src folder (top level folder)
package {
public var MessageQueue:Array = new Array();
public var main:Main;
public var BOOKING_STATUS_DATA:Object;
public function postMessage(msg:Object):void {
MessageQueue.push(msg);
}
public function processMessage():void {
var msg:Object = MessageQueue.pop();
if (msg) {
switch (msg.type) {
}
}
}
Looks like my IDE (FD4) is also recognizing all these functions and variables and also highlighting the varibles and functions just like any other built-in global functions. However, I am getting compilation errors "Accessing possibly undefined variable xxx". The code is as simple as trace(MessageQueue) inside my Main (or another classe).
I am wondering if there was any change Adboe has done recently that it can't be done now or am I missing something? I am not sure if I need to give any special instructions to FD to include this MyGlobals.as?
I am using FD4, Flex SKD 3.1, FP12.0
I am aware of the best practices which suggests to avoid using this type of method for creating global variables but I really need it for my project for my comfort which I feel best way (right now) when compared to take any other path which involves daunting task of code refactoring. I just want do something which can be done in AS3 which I guess is not a hack.
I've done some playing around; it looks like you can only define one (1) property or method at package level per .as file. It must be the same name (case-sensitive) as the .as file it is contained in.
So no, nothing has changed since the older Flash Versions.
In your case that would mean you need five separate ActionScript files along the lines of:
MessageQueue.as:
package
{
public var MessageQueue:Array;
}
main.as:
package
{
public var main:Main;
}
...etc. As you can see this is very cumbersome, another downside to the many others when using this approach. I suggest using the singleton pattern in this scenario instead.
package{
public class Singleton{
private static var _instance:Singleton=null;
private var _score:Number=0;
public function Singleton(e:SingletonEnforcer){
trace(‘new instance of singleton created’);
}
public static function getInstance():Singleton{
if(_instance==null){
_instance=new Singleton(new SingletonEnforcer());
}
return _instance;
}
public function get score():Number{
return _score;
}
public function set score(newScore:Number):void{
_score=newScore;
}
}
}
then iin your any as3 class if you import the singleton class
import Singleton
thn where u need to update the global var_score
use for example
var s:Singleton=Singleton.getInstance();
s.score=50;
trace(s.score);
same thing to display the 50 from another class
var wawa:Singleton=Singleton.getInstance();
trace(wawa.score)

AS3 MVC Design Multiple Controllers

So I'm reading a book about MVC and the author create a controller (PlayerController) and put some functions for keyboard use and some for mouse use. But he just comment out every keyboard use.
It gave me a idea to create 2 controllers, PlayerMouseController and PlayerKeyboardController so I can decide how to control the player changing one line. And if I can design this way, later I can add a AIController for monsters that use the same view and model but are controlled by AI and so on...
I have my model Player and it do the physics stuff. Now I want two controller, one for mouse and other for keyboard. So I create a PlayerMouseController and PlayerKeyboardController.
The PlayerMouseController has 2 functions: processUpdate() and processMouseDown()
The PlayerKeyboardController has 2 functions: processKeyDown() and processKeyUp()
I create the object like this:
_player = new Player();
_playerController = new PlayerMouseController(_player);
_playerView = new PlayerView(_player, _playerController, stage);
addChild(_playerView);
If I want to change the controller I can just change the _playerController line for this:
_playerController = new PlayerKeyboardController(_player);
And it works fine... But I dont know if the design I use is fine for a large project
To make this work I have to create a Controller class with nothing so I can extends the others controllers and my view can call all methods.
public class Controller
{
public function processKeyDown(e:KeyboardEvent):void
{
}
public function processKeyUp(e:KeyboardEvent):void
{
}
public function processUpdate(stage:Stage):void
{
}
public function processMouseDown(e:MouseEvent):void
{
}
}
In my view (PlayerView) I accept any Controller:
public function PlayerView(model:Player, controller:Controller, stage:Stage)
{
_model = model;
_controller = controller;
_stage = stage;
}
and I decide what to use based on its type:
if (_controller is PlayerKeyboardController)
{
_stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
_stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
else if (_controller is PlayerMouseController)
{
_model.addEventListener(Model.UPDATE, onUpdate);
_stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
// EVENTS PlayerKeyboardController
private function onKeyDown(e:KeyboardEvent):void
{
_controller.processKeyDown(e);
}
private function onKeyUp(e:KeyboardEvent):void
{
_controller.processKeyUp(e);
}
// EVENTS PlayerMouseController
private function onUpdate(e:Event):void
{
_controller.processUpdate(_stage);
}
private function onMouseDown(e:MouseEvent):void
{
_controller.processMouseDown(e);
}
So... this is a good idea? How should I improve??
I think as your project evolves you'll soon hit a bottleneck with this kind of approach. I'd suggest creating a general IEntityController interface (don't be afraid of the word 'entity', it just shows that this is a game object controller, something that is parent for example of hero, enemy, etc.).
Then I'd create two separate implementations of this interface: BasicMouseController and BasicKeyboardController, so that I'd have two branches of these controllers with basic logic. If you need additional functionality for the Hero, you'd create a HeroMouseController class which would extend the BasicMouseController class and would have the advantage of calling super methods and adding the extended functionality easily.
You'd still have the benefit of passing different controllers to the PlayerView class as it's constructor would receive an IEntityController as a parameter, meaning anything implementing this class can be passed in.
There are many approaches for problems like this and StackOverflow is usually not meant to give these kind of answers, as every answer to these kind of questions is subjective and this website more fit for Problem/Solution kind of posts.

AS3: How to work with properties of the classes on stage (display list) from class not in the display list?

Hi guys,
I have two objects on stage so I presume they are in the Display list as well (Progress_mc, Ship_mc). I have Calculator class which doesn't represent any visual shape or anything but as3 code so it isn't in the display list.
What is the best way to work with the properties of Progress_mc?
Example: Calculator_as has to receive Progress_mc.width any time width has been changed and after some calculation Calculator has to send some calculated results to Ship_mc.x.
I was thinking if I have to addChild(Calculator) on stage so I can have access to those MCs in Calculator.as but this class isn't a visual object so I am not sure this is the right way.
Or I have to do this (code below) in Calculator class and then try to access the properties but I this way wont work either because the properties wont be of the instances on stage:
private var prg:Progress_mc = new Progress_mc;
private var ship:Ship_mc = new Ship_mc;
Or I have to add them as children of Calculator and add Calculator on stage?
The other problem is that I can't just use setter and getter as static functions in Calculator because "width" property is a read-only and cannot be used in static function (error:?)
What is the best way to access those properties and manipulate them?
Thank you so much good people!
I'm assuming Calculator instance is sort of globally accessible. In that case, I think you have
public function setProgressMcWidth(width:Number):void {...}
in Calculator class. This function needs to be called whenever progressMc's width is updated. Later when calculator needs to pass some width to shipMc, it can dispatch an event such as
package {
public class CalculatorEvent extends Event {
private var _width:Number = width;
public function CalculatorEvent(type:String, width:Number)
{
super(type);
_width = width;
}
override public function clone():Event {
var ret:CalculatorEvent = new CalculatorEvent(type, _width);
return ret;
}
public function getWidth():Number {return _width;}
}
}
and have dispatch code in Calculator like:
dispatch(new CalculatorEvent("shipWidthCalculated", calculatedShipWidth));
Ship mc, in turn, would listen to calculator's event like:
calculator.addEventListener("shipWidthCalculated", handleShipWidthCalculated);
private function handleShipWidthCalculated(event:CalculatorEvent):void {
trace('calculator calculated my width to be: ' + event.getWidth);
}
But if the calculator instance isn't in the display list, it won't receive any events.

Adding an object reference to a component from the properties window

Is there a way to pass an object reference to a component directly from the property/component parameter window? Using the [Inspectible] tag only allows me to input strings and not actual object references.
For example, I have a custom component called "knob" which should hold a reference to a door on the stage which it opens. I know this can be easily done in code with "knob.door = someDoor;" but since there are many objects in the scene I would prefer if I could do it visually trough the properties window.
I don't think you can do this. Your best bet is to pass in a string identifier (perhaps a whole dot-separated path if your clips are deeply nested), and then implement code inside your custom component to find that item by name.
I've got a custom component which lays itself out relative to horizontal and vertical predecessor components, so I do this:
protected var horizontalPredecessor:String = "";
[Inspectable(name = "HorizontalPredecessor", type = String, defaultValue="")]
public function set HorizontalPredecessor($value:String):void
{
horizontalPredecessor = $value;
drawNow();
}
override protected function draw():void
{
if (parent)
{
if (horizontalPredecessor != "")
{
var hp:DisplayObject = parent.getChildByName(horizontalPredecessor);
if (hp)
{
x = hp.y + hp.height + horizontalSpacing;
}
}
}
}
... which is made easy because all these components share the same parent.
Alternatively, if there's only one door, you could make it a singleton, and give it a static reference, like this:
public class Door
{
private static var _singleton:Door;
public static function get Singleton():Door
{
if(!_door) _door = new Door();
return _door;
}
}
Then your handle can just refer to Door.Singleton and you don't have to worry about passing anything in. Alternatively, you could have a static array of Doors in the Door class, and give your handle an index number to link it to a specific Door.

Library design quandary

Ok so I am writing an open source library. A section of this library deals with moving an entity in a two and three dimensional space so it will have functions that manipulate the rotation, position etc.
Now ideally I would like my library to work well with other libraries, in particular things like Papervision3D and other Flash 3D engines, but not forgotting basic image objects like a Sprite or Movieclip.
So this is my quandary. The functions that will manipulate the entity will also need to modify the values of the underlying model data (so either a Sprite, Papervision object etc). What is the best way to make my library flexible so that it can support multiple data models. Performance is also important aspect too.
Currently I am thinking of something like this:
//this is the public function that I expose in my library
public function rotate(val:Number,func:Function,objData:*):void
{
func(val,objData);
}
//example of a function that could be passed in
//this one will rotate a MovieClip
private function modelFunction1(rot:Number,objData:*):void
{
var myMov:MovieClip = objData as MovieClip;
myMov.rotation = rot;
}
//second example of a function that could be pass in
//this one will rotate a point
private function modelFunction2(rot:Number,objData:*):void
{
//yes I know this piece of code makes no sense :P
var p:Point = objData as Point;
p.x = Math.cos(rot);
p.y = Math.sin(rot);
}
so then it could be used like:
rotate(4,modelFunction2,myPoint)
//or
rotate(4,modelFunction1,mySprite);
I should add that in reality I, as the client code, won't be able to directly call the rotate function. Instead the rotate function that I want to pass in would need to be stored somewhere as a class member and then be called by the rotate function. Its just less code for me to write it out like above.
This to me seems quite flexible although the performance implications of casting and passing functions concerns me (but might be ok). Can anyone else suggest an alternative or is what I have the most logical solution. Thanks :)
I suggest the adapter pattern.
In your case you could define interfaces which offer type safe definitions for what your library expects instead of having function arguments.
then you need to write adapter classes which implement your librarys interfaces and wrap for instance a papervision object and delegate the function calls to your interface methods to the papervision object.
interface IRotatatable {
function rotate(deg : Number) : void
}
class YourLibraryClass {
public function rotate(r : IRotatatable, val : Number):void {
r.rotate(val)
}
}
class P3DAdapter implements IRotatable {
public function P3DAdapter(p3d : SomePaperVisionObject) {
_p3d = p3d;
}
public function rotate(r :Number):void {
p3d.rot = r;
}
}
function someClientCode():void {
var adapter : IRotatable = new P3DAdapter(p3d)
new SomeLibraryClass().rotate(adapter, val));
}