Model-view design in Flash - actionscript-3

I'm creating a simple game to learn Flash programming. To have a clean model/view separation, I want to create a Player class which simply holds data relevant to the user. I'm also creating a StatusView class which extends MovieClip and which coresponds to a movie clip symbol which I've created in my Flash project. Basically the StatusView will display the data of my Player class onscreen.
I'm used to doing this sort of thing using listeners, so I've found the EventDispatcher class and added one as a member of my Player class. I'd like to have my StatusView movie clip add an event listener to my Player class so that it can receive messages whenever I change the data in my Player class.
The problem is, there doesn't seem to be anywhere for me to put my Player class so that the StatusView can find it (to add the listener). Everything in the project is created directly by one of the movie clips, and the runtime seems to create these movie clips in an arbitrary order. For example, say I create a MovieClip symbol called GameView and I create the instance of the Player there, and GameView is the parent of StatusView. When StatusView is constructed, I'd like to be able to access the Player from it's parent, but at that point GameView hasn't had it's constructor code run yet. This is true even if I wait for the ADDED_TO_STAGE event.
I could put the game model code in a singleton, but this seems like a hack to me. Is there a best practices way in Flash that lets me create and access my game model independent of all the MovieClip symbol stuff?

If you want to pass the reference of the Model to the constructor of the View, but are not calling the constructor yourself (because you do not create the object via code) you are out of luck here.
You could instead simply define a method on your View to pass a reference of the Model object:
public function setModel(value:Model):void
usage:
view.setModel(player);
There's no "law" that you have to pass the Model to the constructor of the View.
You can also create a set function for convenience:
public function set model(value:Model):void
usage:
view.model = player;
I feel like I have to disagree on the Singleton. The purpose of a Singleton is to guarantee that there's only one instance of it in existence. That's it.
It is not there to pass reference around easily (because the method to get the single instance is static). This is (IMO) a bad practice.
You could make anythign static in order to pass it around "easily". But this would make a mess and nobody does that.
But suddenly, just because the singleton pattern uses a static method, a lot of people think it's a clever way to get to the reference. I beg to differ.

First of all, you could implement Player class as singleton if you need just one instance. I don't think that that looks like a hack (for example, in PureMVC framework each model is a singleton).
At second, you can create instances of Player class in some general class (manager) and send them to views.
P.S. Also, I want to note that you can extend your Player class from EventDisptacher without creating specific field "eventDispatcher" in Player class. I don't know what way is better, but this one is simpler, imho.

Related

AS3: How to dispatch function from class to mainframe

This might be a silly question. But how can I call a function (to execute) from a class to the timeline.
For example, I have the class "Test" and I want to execute the function "Next" on the timline (which it is only a function to show next slide).
Hope you understand what I'm trying to do.
Thank you!
The best practice for communication (in this scenario!) is to use Events.
The timeline create the object of your class Test and registers an
event listener.
The object of your class Test dispatch an Event.
The function that the timeline registered for that Event will be executed.
Please take a look at this question that wants to send additional information to the main timeline. In your case, you do not need a custom Event, because you do not want to send any information along. You only want to communicate the occurrence of the event. You can put that information into the type of the event. an example for a dispatch could look like this:
dispatchEvent(new Event("next"));
Creating a custom class allows you to put that String literal that describes the type into a constant, which prevents errors caused by accidentally misspelling the type. That might be a reason to create a custom Event class anyway, even only for the sake of a place to put those constants.
dispatchEvent(new PresentationEvent(PresentationEvent.NEXT));
Again, this would do the same as the previous line. this is also covered in the other question and the answer to it. Please take a look.

AS3: avoid multiple instances of same class

Evening all, and thanks in advance for your wisdom.
Bear with me if I show ignorance, but here is how my project is currently built:
-TitleScreen: first class which appears. Extends Sprite.
-Startup: class I use to call other classes. Extends Sprite.
-GameScreen: the "game engine" class. Extends AssetsHandler.
-AssetsHandler: where most of the methods to manipulate the assets are. Extends GrfAssetsStore.
-GrfAssetsStore: where all graphical assets are stored. Extends Sprite.
-Level01: first level class. Extends GameScreen.
Now: when I start everything up, all is hunky dory. So, let's say I finish level 1, and I want to restart, or go to title screen: again no problems, BUT I re-instantiate the GameScreen class -and in turn AssetsHandler, and in turn GrfAssetsStore. Mind you I have not set up any EventListeners that call them back up -indeed, I tried to make sure that once started, they would be left undisturbed- but in my ignorance I've now realised that restarting Level01 is in turn re-extending the other classes.
Understandably this is greatly undesirable, but so far I cannot overcome it. I tried just instantiating the super classes within Level01 -same issue.
The aim pretty much is having GameScreen, AssetsHandler and GrfAssetsStore running under the bonnet, so to speak, while new levels are begun and ended, but without in turn restarting the superclasses, just getting methods/variables etc. from them.
So: how do I overcome this? And no, I am not greatly experienced in AS3, so I appreciate if this is obvious to actual experts, hence why I am here.
If I need to word anything better please do not hesitate in saying such.
EDIT: the issue now I believe isn't the extending, but me not de-referencing correctly the variables etc., thanks Josh for helping me realise such. As you mentioned, it makes little sense to deny one of the major aspects of OOP: as such I should defo not consider applying that incorrect logic.
I'll attempt to better GC (and force GC if necessary) until I have removed correctly all references. If this doesn't work though...I'll post another, more detailed question.
You could set it up as a Singleton.
Basic structure:
public class ClassName {
private static var _instance:ClassName;
public function ClassName() {
// run normal constructor code here
}
public static function get instance():ClassName {
if ( !_instance ) {
_instance = new ClassName();
}
return _instance;
}
}
So instead of you ever calling new ClassName() in your code, you just call ClassName.instance to access the single instance of that class. That will return the same single instance every single time, and create it if it has not already been created. This will ensure there is never more than a single instance of the code at any given time (assuming you never call new ClassName() of course)
Note that this is not a design pattern that should be used often, if at all. It goes against basic OOP principles and is a highly debated design pattern for that reason. I think this works in this case because you do not want more than one instance of your game running at any given time, but in most cases you should write your code to avoid this pattern.
http://en.wikipedia.org/wiki/Singleton_pattern

How to add a MovieClip from the library to the stage programmatically?

I am wondering how to add a MovieClip from the library onto the stage programmatically.
How would I go about doing this?
Symbols within Flash may define ActionScript Linkage.
AS Linkage may be set by right-clicking a symbol from the library and selecting Properties...
Check Export for ActionScript and enter a Class name.
If you don't need to explicitly define a base class beyond the symbol type, you can enter AS Linkage directly from the Library:
This creates a class definition no different than if you had written an ActionScript class.
Create instances by instantiating new instances of your AS Linkage type:
var symbolExample:SymbolExample = new SymbolExample();
addChild(symbolExample);
You will essentially be creating a "class" for your movieclip. Do what James suggests above... But when calling it into your program you will have to execute something like this:
//instantiate your object
var movieClip:MovieClip = new MovieClip;
//add it to the stage
addChild(movieClip);
//object will default to x=0 , y=0 so you can define that as well
movieClip.x=100;
movieClip.y=100;
//and so on...
movieClip is whatever you want... but MovieClip is the name you assign the class in the properties dialog. These var/class relationships are typically case sensitive so follow this formula for anything you create in your library.
There are many different ways to call and remove your objects, and it can get simpler or more complicated depending on what you intend to do with your object. For instance, you can tell the object which layer to occupy with:
addChildAt(movieClip, 1);
this adds movieClip to layer 1 or the layer just above the bottom-most layer.
Hope this helps...
You create your movieclip via any method you want, then when it is in the library you right click and select Properties, check the box Export for Actionscript, choose a class name and export in frame 1. Then whenever you want to add it you add it as you would any other object. I'm sure someone else will have a more detailed explanation after me, this is the general idea.

AS3: Major Slowdown

I'm working on a Flash game, and after running my game for a while there is a huge drop in frame rate. There aren't a lot of MovieClips onscreen at once, but MovieClips are being replaced using removeChild and addChild often.
How can one test for problems such as memory leaks? And what are some good AS3 programming standards on this matter?
It seems like you're not preparing your instances of MovieClip for garbage collection. This thread could be extremely helpful to you.
Some of the basic things you want to cover when discarding a MovieClip (or any other Object) properly are:
Remove the object from the DisplayList (if it's a DisplayObject). This is done via what you're doing already, removeChild()
Remove any event listeners that have been applied to the Object. Best thing to do is keep on top of this right from the beginning; by that I mean, when you call addEventListener(), be sure to somewhere in the very near future add a sister removeEventListener() as well.
Remove reference to your Object. This includes, but is not limited to: reference to the Object via being part of an Array/Vector, reference via being stored in a property of another Object, etc.
A suggestion that I can offer is to have in the base class of your objects a method that handles all of this, eg remove() or deconstruct().
Here's an example:
public function deconstruct():void
{
if(parent)
parent.removeChild(this);
removeEventListener(MouseEvent.CLICK, _onClick);
}
And when you extend this class and need other dereferencing features, just build on your deconstruct() method:
override public function deconstruct():void
{
removeEventListener(MouseEvent.MOUSE_OVER, _mouseOver);
var i:int = someArray.indexOf(this);
someArray.splice(i, 1);
super.deconstruct();
}
http://gskinner.com/talks/resource-management/

AS3 scope and garbage collection

Objetcs created inside a function are automatically marked for garbage collection if not referenced anywhere else?
Let´s say, I have a class called SubClass. in the constructor I create some displayObjects.
Then I instatiate SubClass somewhere. When I remove this SubClass instance, will the objects inside be marked for garbage collection?
thanks in advance!
cheers
Bruno
Yes, unless you have references to SubClass's members anywhere outside SubClass, or you keep an active reference to the outside of your class from within SubClass (or any objects within it).
A typical example of the latter is if SubClass subscribes to a Stage event; if the listener is not weak (5th argument of addEventListener) you will keep an active link between the stage and your SubClass instance, and even if you remove the object and null it, it will not be collected.
For simple listeners you can set that 5th argument to true, so the reference is weak and will be broken by the garbage collector. For more complex situations (or for example NetStreams, Loaders, Timeline audio, etc...), you need to create a way for the class to unlink itself for any outside objects and stop any process that could prevent collection, like a public destroy() method that closes requests, stopping media, removeListeners, etc...
But then again, for simple situations when you only have isolated childs, and no references to the outside of your class, simply removing your instance and nulling its reference should be enough for the garbage collection.