AS3 central event dispatcher shared between instances (not static) - actionscript-3

I'm building a flash app (just AS3 with FlashDevelop) and I'm having some trouble keeping things loosely coupled around the event system. I've done a lot of reading about central event systems and static eventdispatchers but they don't quite fit the bill for me.
What I'm building is similar to a video player. I have a Player class which is the parent of all the other little parts of the app. The Player class extends Sprite and I've currently designed it so that you could instantiate multiple Player's and put them on the stage. I also have a Controller class which extends EventDispatcher and I dispatch all my events through this class. It's a central event class.
The problem is that I need to pass around a reference to this class so that all the other classes can dispatch and listen through it. Passing around the reference works but it's the exact opposite of loose coupling. I know I could make a static EventDispatcher that all the classes could see but then if I had two or three Player's on the stage they would all hear each others events.
How can I create a type of sandbox that will allow all the child classes of a Player instance to be aware of the central dispatcher without passing a reference or making it static?

I'd suggest to use my static dispatcher, this one has an ID mechanism that allows to tell which Player instance dispatches an event.

It turns out what I was really trying to understand was loose-coupling using something like dependency injection.
I never ended up doing this in any AS3 projects as I don't do much of it anyway. Having done more C# recently I more easily grasped this concept using libraries such as StructureMap and Ninject.
For AS3 you could use a framework like Robotlegs. This will probably change the way you code AS3 and may not be for all developers/situations.

Related

Need some help getting started with OOD in ActionScript 3

So being new to AS3 but not development in general, during a recent project that I just started I hit an immediate snag where my normal method of OOD is causing errors in AS3.
I created a layer in Adobe Flash called code just to keep everything separate and in frame one under actions I used the following code to get started:
var GameContainerSize:int = 400;
class GameInfo {
var GameID:int;
var HomeTeam:String;
var VisitingTeam:String;
function GameInfo()
{
}
}
This simple code immediately causes an error though
Scene 1, Layer 'Code', Frame 1, Line 4 1131: Classes must not be nested.
And my best guess is this is because the timeline and all code on it exists within a class already. So what should I be doing if I want to develop this program using class objects, or is this even possible in flash?
You can't define classes on the timeline. Each timeline is exported as a class, var and function declarations become members of the class, and frame code is moved to its own frame functions which are called when the timeline reaches that frame. Thus the error is saying "you can't put a class in a class" because the timeline already is a class.
To define classes you must use external .as files with package blocks:
// GameInfo.as
package {
public class GameInfo {
public var GameID:int;
public var HomeTeam:String;
public var VisitingTeam:String;
public function GameInfo(){ }
}
}
In Flash Pro you can link a class to a timeline (document or symbols). Such a class must extend Sprite or MovieClip.
You can also refer to any of your classes from any frame script. For example, you could put on frame 1 of your main timeline:
var gameInfo:GameInfo = new GameInfo();
Typical OOP would involve using external .as class files for almost everything, with only minimal function calls on your timeline frames, like stop() at the end of a timeline or calling a custom function you've added to the class linked to the timeline.
I created a layer
That's not ideal. The problem is that it will not get you any closer to understanding the code, because it isn't code. It's a feature of the flash authoring environment. You might as well spend a day with the drawing tool drawing something.
to keep everything separate and in frame one under actions
Organisation is important, but layers aren't the way to go. As each class definition goes into its own external file, you have to create additional files anyway if you want to create more classes. And you want to create more classes because having only one is horrible object oriented design. Being consistent here is important. That's why people in the comments suggested to use a document class and have no code on any frames. All code is organised in classes. No exceptions1.
Having said all that, I highly advice against using Adobe Flash to learn As3. There's too much obfuscation going on behind the scenes. If you want to learn how to code As3, use a code editor. (or plain text editor + compiler if you prefer). Learning what settings dialog has to be adjusted in order to get what you want is not going to get you any closer to understanding OOD in As3.
I also see package, is this kind of like a namespace and does it need to be named, if not what is its purpose?
No, packages are packages and namespaces are namespaces. Apples and oranges.
Packages are used to organize classes just like a structure of
folders is used to organize the .as fiels of those classes. In fact,
the package is pretty much exactly that folder structure, for example:
flash.display is for all display related classes
flash.events is for events
A namespace allows you to control access to members of a class. Namespaces are very rarely used in As3. Here's an article from grant skinner about namespaces. Personally, I never needed to use namespaces. If you are jsut getting started, you can very well ignore them for now.
That sounds perfect! except I cannot get it to launch on my Win10 machine. I may just end up outsourcing this at this ratio
flash develop is the alternative editor. It's free, fast and lightweight.
my normal method of OOD
You want to extend your definition of normal with
always explicitly specify the access control modifiers
member names start with small letters
public class GameInfo {
private var gameID:int;
private var homeTeam:String;
private var visitingTeam:String;
function GameInfo()
{
}
}
1admittedly, there are top level functions that are pretty much free floating functions without a class. If you want to do oop, this is not what you want. It's for the occasional independent utility function. Stick to classes for now.

Preloading Instantiated Class Objects inside a main Class

I have a main class in which 3 other class objects are managed and instantiated and are all extended from Sprite. My issue is getting these loaded correctly as I have external assets(images,and sounds) being loaded into these 3 classes. I have a simple .fla that is referencing the "Main". How would I go about ensuring the appropriate class instance is being loaded properly before it is added to the stage?
I have tried making the three classes inherit from the Loader class to retrieve the bytesloaded/total for the class but this causes other issues in the code that require attributes from Sprite. Would I need to preload ALL assets inside the class first, thus making the instantiated object on "Main" preloaded? Thank you for any help/advice.
Thank you all very much for your help. This particular application was being deployed in a learning management system. The issue was the application its self was freezing due to a .js script used for SCORM communication. However, it was very useful for me to learn how flash is managing instantiation, I really appreciate the help both of you provided.

AS3 How to communicate between frames

I have been writing a game in timeline code. I want the different frames (rooms) in the game to be able to share information between each other. Of course, timeline code is limited to the frame it is written in.
After doing quite a bit of reading ("Foundation Game Design with Flash" and a number of articles, tutorials, forums etc) I decided to employ a document class. This did not work either. It seems it only works for frame one but not the rest of the frames (I have four).
How can I have frame four respond to something that happpened in frame one? For example, if the player achieves something in frame one, I want a movie clip in frame four to be visible.
If You are writing your code on the timeline, My suggestion would be to create two layers in the timeline, one for 'frame-actions' - in this layer you insert the code specific to a single frame (will work when the movieclip is stopped on that particular frame).. And also create one more layer called global-actions (for the entire timeline). Only the first frame will be a key frame and there should be empty frames till the end of the timeline.
In this layer actions write the code that you want to access from any keyframe in the same timeline.
If you define a variable in the actions which are written for the whole timeline (global-actions) then that will be available on all the frames.
Now if you want to go to a different frame based on some action, just write some functions in the layer which contains global actions and call that particular function through the frame actions. To go to a different frame use the 'gotoAndStop(frameNumber)' function of flash.
I want to tell you that while it will work, I would not recommend using it in this way.
HTH.
You can use static variables - these are variables which are linked to a class, rather than an instance of it.
Suppose your document class was called Document.as, and you wanted a variable, playerLives, to be visible from any part of the program.
Declare it inside Document.as:
public static var playerLives:int = 3;
You can then reference this directly from anywhere else in your code with:
Document.playerLives
(note that the variable is a member of the class itself, not an instance of it).
You could use a dedicated Statics class to hold these variables if you want to keep your document neat, or attach them to the relevant classes (eg Player.lives)
I've not used timeline/frames for some years but I believe this is how I used to do it!
NB Statics will be fine for your purposes but they are, in some ways, an equivalent to the _global variable in AS2 (at least, they can be used in the same manner) - many would not approve of their use, or over-use, as they are freely accessible from anywhere in your program (thus anathema to the OO concept of encapsulation), but personally I try not to worry about it in small cases - the most important thing to know about the rules of any design pattern is when they can be broken!
They are also slightly slower to access than instance members, but you won't notice this unless you are constantly accessing/changing them (making things like player velocity, which will need to be referenced/changed every frame, static, is not a good idea).
Hope this helps.
You may find the simplest way to link everything with the document class is to move your four frames into a movieclip together and have that on the first frame, then interact with that movieclip.
E.g. in the document class, where the movieclip instance on the timeline is called 'game'.
game.gotoAndStop(4);
game.objectToDisplay.visible = true;
If you encounter reference errors in the IDE then you can avoid these by using [] notation to refer to the properties of game, e.g. game["objectToDisplay"].visible = true;
Note that it's not really best practice to do this, but it will at least help you to finish that first game which is really more important at this stage in your learning. Afterwards, if you want to learn more then I'd recommend "The Essential Guide to Flash Games" by Jeff Fulton from 8bitrocket.com - it will teach you how to use the document class effectively.

LibGdx Texture loading in game and using it for various listeners

hi i am developing a game using libgdx. I want to make the texture object available to entire application. I have a requirement like, initialize the texture in one application listener and i want to use it in another application listener. Can anyone help me on this.
There are two ways I think you can do this. First, you could read the data into a static variable. For an example of this, take a look at the Art class in metagun demo: Art.java. The second way, which I have not tried yet, is to use the new AssetManager class. There is example use in the AssetManager test. These should help you access your textures more easily.
You don't need to have 2 or more Application listeners. Actually that only makes things harder.
Use Screens instead (extending Game in your core class instead of directly implementing ApplicationListener).
Either way, you should be able to just send the textures as arguments. For example I have a class Assets that contains all the textures and I sent it to each screen. You can make them static as Doran suggested too.

Explanation of Base Class (Flash) and inheritance

I have a MovieClip called PopUp where I wrote some code.
I need to make another MovieClip that uses pretty much the same code...can I just use the PopUp class as the base class for my other MovieClip?
They look different but they have the same instances on the stage and stuff.
You can just create a new class called PopUpBase, and let your new MC's extend that class. Generally changing the base class in the IDE can cause some problems, so it's best practice not to, but to create classes (and .as files) for each MC that needs code.
Depending on what you're doing with this, it might be okay just to change the base classes to PopUpBase (in the IDE) :)