AS3 Object Oriented GUI Design - actionscript-3

I'm trying to make a small Flash game that has a GUI, which is basically a menu where players can select certain items, sort of like the Tower Defense games.
Would it be a good idea to make the GUI a singleton? Because obviously there can only be 1 instance of the GUI class.
Is there a better way?

In my opinion, the rest of the system should not know about your GUI, so making it a singleton is pointless. The view (GUI) should bind to some kind of models to show the current state.
In general, it's a good idea to avoid Singletons altogether.
By binding to a model I mean something like that:
class MyGUI
{
...
public function set game(g:Game):void {
g.addEventListener('pointsChanged', function(e:Event):void {
ptsLabel.text = g.points.toString() + " points";
})
}
}
class Game extends EventDispatcher
{
private var _points:int = 0;
public function get points():int {
return _points;
}
public function set points(points:int):void {
_points = points;
dispatchEvent(new Event('pointsChanged'));
}
}

Related

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.

Use FLVplayback in FlashDevelop, add Sprite Class to a World in AS3

Hi (excuse me if there are grammar mistakes, I'm french),
I'm a beginner in AS3 but I know a bit better Flashpunk; whatever, I have really some difficulties to code in AS3 and can't get how to insert a video in an AS3 project using FlashDevelop.
Well I found some code for what I'm looking for, insert a flv video, here : http://www.flashdevelop.org/community/viewtopic.php?f=9&t=6407
But I have some issues to get this code working... As I said before I know better Flashpunk so it's hard for me to link basic AS3 with my knowledges in Flashpunk.
I tried to organize it in classes but I know these are wrong, but please, can anyone tell me how I should do to get the code working ? I think the "addChild" is only a Sprite or Movieclip function so my FLVplayback and PlayerGfx extend Sprite, but I don't know how to add them and display them... Here is my code :
public class testMyWorld extends World
{
public var player:PlayerGfx;
public var _FLV:testFLV;
public function testMyWorld()
{
_FLV = new testFLV;
player = new PlayerGfx();
}
}
public class testFLV extends Sprite
{
public var flvPlayback:FLVPlayback;
public var player:PlayerGfx;
public function testFLV()
{
flvPlayback = new FLVPlayback();
flvPlayback.skin = "none"
flvPlayback.autoPlay = false;
flvPlayback.source = "FLVSkyrim.flv"
player.addChild(flvPlayback);
}
}
and well I didn't know what to put in it but in the link before there is a "player class" so...
public class PlayerGfx extends Sprite
{
public function PlayerGfx()
{
}
}
I'm desperately looking for help, I can't find anyone that can explain me what I should do :/ I just need to display a video in as AS3 project for school and I don't want to use FlashProfessional... But I don't understand many things, such as addChild, display a Sprite Class, etc... But if you know an other code better that I could use and that you could explain to me, I would be very grateful.
Thanks in advance !
EDIT : gosh I'm sorry idk if I saw your answers at the time I asked this. The thing is, one of my coworkers at school wrote me a pretty nice bit of code that answered exactly what I needed to do because it was a bit tricky. I can give it to anyone who may need it, but I'm not sure it would suit any "usual" situation because it was pretty personalized and explained irl. Anyway, thanks for your answers.
Why is your base class a World? In a pure AS3 project it should be a Sprite.
Then, once your player (FLVPlayback) is created, you just have to add it to the display list:
import fl.video.FLVPlayback;
public class Main extends Sprite
{
private var flvPlayback:FLVPlayback;
public function testMyWorld()
{
flvPlayback = new FLVPlayback();
flvPlayback.skin = "none"
flvPlayback.autoPlay = false;
flvPlayback.source = "FLVSkyrim.flv"
addChild(flvPlayback);
}
}
Be simple, you don't need all those classes ;)
This is tricky, because FlashPunk replaces the display list by a custom Bitmap-based renderer.
Your World object is not a regular display object and it can't hold a FLVPlayback component.
Your best option is to attach the video player to the stage. Your Main class (extending Engine) is a display object so it has a reference to the stage.
First you need a global reference to your Main instance so you can find the stage:
public class Main extends Engine
{
static public instance:Main; // global static reference
public function Main():void
{
instance = this;
...
}
}
Now you can attach display objects on the stage (over the FlashPunk stage):
public class testMyWorld extends World
{
private var player:MyPlayer; // your FLV player class extending Sprite
public function testMyWorld()
{
player = new MyPlayer();
}
// when the world is shown
override public function begin():void
{
Main.instance.stage.addChild(player);
}
// when the world is hidden
override public function end():void
{
if (player.parent) Main.instance.stage.removeChild(player);
}
}
PS: I didn't actually run this code

Application Design Patterns AS3

just thought I would share something I have found to help delivering data across an application I am wondering what others think about this I wanted to have a way to capture event bubbling up back down to other components but in a way that it would make it easy to use anywhere in may app so this is what i came up with.
I Extend the Application class and wrap in an abstract function registering a function of any component anywhere and capture it at the top most level and pass to where ever i chose to.
public class AxApplication extends Application
{
public var ___registeredEvents:Array = new Array();
public var ___registeredFunctions:Array = new Array();
function AxApplication()
{
super();
}
public function localRegisterForEvent(e:Event,func:*,caller:*):void
{
caller.addEventListener(e.type,localCallerEventHandler,true,3);
caller.addEventListener(e.type,localCallerEventHandler,false,3);
___registeredEvents.push(e);
___registeredFunctions.push(func);
}
public function localCallerEventHandler(e:*):void
{
if(e!=null)
{
for(var i:int = 0 ; i< ___registeredEvents.length; i++)
{
if(e.type == ___registeredEvents[i].type)
{
___registeredFunctions[i](e);
//the registered function gets called
//there no garbage collection implemented!
}
}
}
}
}
I think that is not a very useful solution. Why? Because you scatter AxApplication references around the application. Views and Model instance don't need any references to the application at all. It would be better to to implement a controller layer which uses a simple eventBus property, which could look like:
private static const _EVENT_BUS:IEventDispatcher = FlexGlobals.topLevelApplication;
protected final function eventBus():IEventDispatcher {
return _EVENT_BUS;
}
If you implement a base view controller/mediator (depending from which framework you're coming), you don't have any reference to non-framework classes at all, which makes it highly reusable. It is just a simple reuse of the Application singleton which you use to dispatch system wide events. You register listeners in the view controller/mediator and update the views or models accordingly. RobotLegs for example uses a system wide event dispatcher as well.
Why not just using the parentApplication approach? Because you can't implement tests (the generated test-runner of IDEs won't extend your AxApplication) or just yank the components/models in a different application - that is basically not possible.

Game decision design pattern

So I have many objects with materials that each possess different properties (brick, glass, etc.) and are each affected differently by elemental effects. A brick material for example will be affected differently by fire or acid than a cement material. A brick that's Burning or Melting will be affected differently when another Burning/Melting effect is applied.
At this point in my game, I have an FSM but it's very simple. If I drop a fire element on a brick, it would go to the Burning state. However if I then dropped a water element on the brick, I might want the fire to go out, take/add health and change textures (or not depending on the current combination).
The point is, I have many combinations with no commonality between them so I can't create something uniform. Sometimes I need to change the texture and other times I don't. Sometimes take damage while other times add health. Sometimes I need to just do nothing in a function. At this point, the only thing I can thing of is creating a global mapping such as:
FunctionMap[ObjectMaterial][CurrentObjectState][ElementBeingApplied]
(i.e.
FunctionMap[Brick][Burning][Acid]
FunctionMap[Brick][Melting][Acid]
)
The problem is, is that this is obviously a ton of functions due to the amount of combinations available with materials and effect types. Can anyone recommend a route to take or pattern to look at?
Although not entirely relevant to the discussion, this is being made in AS3 and Away3D.
Here are some of my classes for one example:
public class Brick extends AbstractBlock implements IFireable
{
public function Brick()
{
super(this);
this.material = new BitmapMaterial(_spriteManager.GetBlockMaterial(BlockUtilities.GetMaterialMap["brick_new"]));
_type = "Brick";
/*
RulesManager.StateMap["Brick"]["OnFire"]["Water"] = some function;
RulesManager.StateMap["Brick"]["OnFire"]["Fire"] = some function;
RulesManager.StateMap["Brick"]["OnFire"]["Acid"] = some function;
RulesManager.StateMap["Brick"]["OnFire"]["Ice"] = some function;
RulesManager.StateMap["Brick"]["OnWater"]["Water"] = some function;
//and so on...there are nine different materials so I'm not liking this way
*/
}
public override function render():void
{
super.render();
}
}
public class OnFire extends AbstractDamage
{
protected var _timeStart:Number = 0;
private var _damageAccumulated:Number = 0;
public function OnFire(block:AbstractBlock,bombType:String)
{
super(block,bombType);
}
public override function enter():void
{
super.enter();
}
public override function exit():void
{
super.exit();
}
public override function update(time:Number):void
{
super.update(time);
if(_timeStart == 0)
_timeStart = time;
var time_delta:Number = (time - _timeStart)/_waitTime;
var damageToSubtract:Number = (time_delta * _damageDone);
_damageAccumulated += damageToSubtract;
_self.Integrity = _self.Integrity - _damageAccumulated;
}
}
}
Thus, a fire element could be applied to a bunch of applies. One those blocks, currently frozen, is now hit and is now changing to the OnFire state. Each block has its own state machine and the states are themselves objects as you can see.
block.FSM.changeState(new OnFire(block));
So your problem is that you have 9 * 5 * 4 combinations of effects, right? Having separate functions for each of those would not be fun to manage. But, even if it's a lot of data, you need it. I would make that data as simple as possible, then parse it. Something like:
var materialProperties = {
brick: {
fire: {
normal: {damage: 10, image: 'brick_fire.jpg'},
}
water: {
fire: {damage: 0, image: 'brick_smoking.jpg'}
}
},
//... a lot more of this ...
}
class Material
{
public var damage:int = 0;
public var image:String = '';
private var properties:Object;
private var state:String;
public function Material(properties)
{
this.properties = properties;
}
public function apply(effect:String):void
{
if(properties[effect])
{
if(properties[effect][state])
{
update(properties[effect][state]);
}
else if(properties[effect]['normal'])
{
update(properties[effect]['normal']);
}
}
state = effect;
}
private function update(properties):void
{
damage += properties.damage;
image = properties.image;
}
}
var brick = new Material(materialProperties.brick);
brick.apply('fire');
brick.apply('water');
Do you have custom classes setup? To me, this sounds like an ideal solution.
Once you map out each classes properties and abilities, object management should be trivial.
ie a Brick class which has certain states [burning, melting] and reacts differently [function calls] when it interacts [collides] with another class [Water Class].
I hope I'm not barking up the wrong tree.... If you can provide a bit more on what your looking for, im sure someone smarter than me will jump in ;)
Short answer because I believe Mr Linquist does a great job of explaining it - but it sounds to me like a job for the visitor pattern. In a nutshell, your elements (brick, concrete, etc) all allow visitors (fire, ice, acid, etc) to come and 'visit' them and apply their effects.
Hope this helps!

Is it okay to put game logic in a draw function?

I am making a game, and I have finally finished the gameplay aspect of it, but now it's time for me to create a menu and a high scores screen. I'm not entirely sure how to do it, the game will be in a different state (MENU_STATE, GAMEPLAY_STATE, SCORESCREEN_STATE) and in each state I want to draw different things to the screen, is it okay for me to do something like this then?
draw function()
{
if MENU_STATE
draw menu
if GAMEPLAY_STATE
draw game
if SCORESCREEN_STATE
draw scores
}
I've been following a strictly no logic in the draw function and it's been good so far, but I really can't figure out a different way to do this.
You could use separate classes for the three states, implementing a common interface, and rather than setting a constant for state, set an instance of one of the classes:
interface IState {
void draw();
}
class Menu implements IState {
void draw() {
// Draw menu
}
}
class Game implements IState {
void draw() {
// Draw game
}
}
void draw() {
state.draw();
}
This still isn't ideal (you don't really want drawing code in your state, you want something a bit more separate), but the abstraction is a common one and could be relevant (and it's hard to advise further without knowing more of your architecture).
You are calling some drawing functions in that routine but that doesn't mean
you have to name it draw.
Perhaps this is more appropriate in your case:
// pseudocode
on_game_state function(state)
{
select (state):
MENU_STATE:
draw menu
GAMEPLAY_STATE:
draw game
SCORESCREEN_STATE:
draw scores
}
Using a statemachine would make this simpler. Each state will have its own set of update and draw functions that are called when it is on top of the state stack. Instead of having one draw function with internal state switches you would have Game_Draw(), Menu_Draw(), HighScoreScreen_Draw() etc. Similarly your update functions could be separated out.
static void StateMachine_DrawTopState()
{
switch(stateMachine_topState)
{
case STATE_GAMEPLAY:
{
Gameplay_Draw();
}
break;
case STATE_MENU:
{
Menu_Draw();
}
break;
}
}
Similar to Andrew Aylett's answer and assuming an object-oriented language, perhaps you could do something like:
Interface IState {
void init();
void update();
void draw();
}
class GameplayScene implements IState {
void init() {
// initialize gameplay
}
void update() {
// update game logic
}
void draw() {
// draw game
}
}
class MenuScene implements IState {
void init() {
// initialize menu
}
void update() {
// update menu logic
}
void draw() {
// draw menu
}
}
class ScoresScene etc...
class TitleScene etc...
// Somewhere else, probably in the Game class
void Main() {
// Init game
Scene currentScene = new TitleScene;
while (Scene != null) {
Scene.init();
Scene.update();
Scene.draw();
}
// Exit game
}
You would also need to think about how to handle transition between scenes. You could have each scene class have a member variable called something like nextScene and the main function queries it at the start of the loop to switch to the proper scene.
If you don't have the luxury of using an object-oriented programming language (like C++, Java, C#, Python, etc.), both Colin's and Nick D's answers might help, although I'd try to have the switch statement in one place (say one big game_update function) to allow adding new states by making a change in one place. Alternatively, you could build on the Colin's state machine design to make something more generic and that doesn't explicitly require a hard-coded switch statement. (although to be honest I can't think of a good way to do it at the moment)
It is absolutely not ok to put game logic in a draw function.
However, if it makes your life easier in this specific case, it's ok anyway.
You can always change it later if it becomes a mess.
Yes it's fine, game programmers are allowed to bend the rules for performance gains. The view and the model of a game world are quite often one and the same thing to avoid latency created by decoupling the view and the model.
There's no reason why you can't make the menu and highscores objects part of your game world, it's been done before in quite a few games.