I am trying to come up with an efficient way to organize clickable menus for the objects in my game. I made a Menu class, from which all possible menus inherit:
class_name Menu extends Control
#contains functions (for buttons) that all menus have in common
func open_menu():
pass
func close_menu():
pass
To make a menu specific to buildings, I inherit all functionalities from the Menu class:
class_name BuildingMenu extends Menu
# contains functions specific to all buildings
func upgrade_building():
pass
func delete_building():
pass
# ... many more ...
Now here's the problem: My HQ is literally just another building with a few extras and the main difference that it can't be deleted, so I'm thinking of inheriting from BuildingMenu. Is there a way to disable the inherited delete_building() function in the HQMenu script?
class_name HQMenu extends BuildingMenu
func delete_building():
# overwriting inherited function like this does not work...
# ... some HQ specific stuff here ...
I could just inherit from Menu and then copy paste everything from BuildingMenu except the delete_building() method, but this seems somewhat clumsy because now I have to edit two files if I want to change/add any building functions.
What is the correct way to do this?
SOLUTION:
Thanks to the suggestion by Thearot I've decided to move the delete_building() function into a new class from which all the regular (non HQ) buildings inherit:
Now here's the problem: My HQ is literally just another building with a few extras and the main difference that it can't be deleted, so I'm thinking of inheriting from BuildingMenu. Is there a way to disable the inherited delete_building() function in the HQMenu script?
This sounds like a violation of Liskov Substitution Principle. From a purely object oriented point of view, it would be preferible to make another class for a subset of buildings with what they have in common, than to have one building inherit from another if it has to disable some methods.
If your base class for all buildings implies that some buildings have to disable some methods, then it does not really have the methods common for all building, it has some extra ones.
To be clear, here I'm suggesting to add another extra intermediary class, and that way you don't have to delete nor duplicate methods.
If that is not an option for you… Congratulations! you have made a mess system complex enough that some kind of component based system begins to make sense. But don't jump the line, don't fret, it is OK.
If I understand correctly you have some contextual menus that show different options depending on what is selected or what you click on, right?
That means that the options are variable. Thus, use a variable. Add an Array field that has the names of the methods that should be linked to the menu. Then have the menu system discover the options by reading that Array, and connecting to functions with the names specified there.
And how you do add or remove options? You add them or remove them form the Array. Simple. You can populate the Array in _init.
To be clear, you can check if an object has a method with has_method. You call a method by name with call, or - of course - you could connect signals to them with connect (if prefer to populate an static menu for the object instead of having a dynamic one). Yes, I'm suggesting late binding.
Related
I have a menu with five buttons. Menu is visible all the time. there is click event for each menu item. which slides corresponding movie clip from left to right. each movie clip has different nature events and respective animation and activity. for example tab 1 brings the video page. and within that movie clip I have video events like play pause volume and on complete etc. events and code. tab 2 has button group for Time and another button group Features. depending on user selection code will calculate and show value on a animated counter. tab 3 has button group for Time and button group Source. as per the user selection it will calculate and show the values as animated graph. and so on.
Right now I have all the individual tab movie clip has its own time line code for its own events. and some crossover variables and references with other tabs. Everything is working as expected. No problem. I know time line code is not the best way to do any complex project.
So, I would like to get the entire coding as one class or more classes if that is the correct way.
I am beginner as far as class logic. I have already created Main as document class and could control the general navigation of tabs and their initial look. But stuck at tab specific button events and other such unique events for the specific tab.
Any help is greatly appreciated. Thanks in advance.
any similar example or suggestions.
First of all, thanks a lot for a prompt response. It seems like I am not even a beginner. I need to read a lot and probalbly grasp all fundamental concepts thoroughly. I have gone through both the links suggested in your comments. I am trying to digest the stuff slowly. I do not have any formal informal education regarding OOP or any sort of programming. To be honest, I have hard time understanding the code you have suggeted. Not because of your code but because of my level of caliber. I will have to spend some time to make myself clearer regarding events and sequence etc. different tab contents are as movieclips to main timeline and already placed on stage. It comes and goes to its corresponding tab button click event. I am not marking your answer as yes because I still need to my own homework based on your suggestion. Thanks a lot once again. I am sure I will ask few more questions later.
This is how I would design it:
I'd have a Menu Class, which only contains the buttons and "converts" clicks on them into more specific events. That might look something like this:
public Class Menu extends Sprite {
protected var buttons:Vector. = new Vector.();
public function Menu() {
super();
var loops:int = numChildren;
for (var i:int=0; i<loops; i++) {
var button:SimpleButton = getChildAt(i) as SimpleButton;
if (button) {
buttons[buttons.length] = button;
button.addEventListener(MouseEvent.CLICK, broadcastMenuEvent);
}
}
}
public function broadcastMenuEvent(e:Event):void {
var button:DisplayObject = e.currentTarget as DisplayObject;
dispatchEvent(new Event(button.name, true));//bubbling, can catch at any level
}
}
The way this is built, you can change the events that are being dispatched simply by changing the name you give the instance of the button on stage. Note that you need to apply Menu as the Base Class and not the Class for this to work if you have "declare instances automatically" unchecked, because doing it that way allows the compiler to generate those instance names for you in a way your base Class doesn't have to know about.
At this point, you can then deal with those events in another place--whether it's your main document Class or whether you have a separate Controller.
I would define each of the Views you described as a separate Class as well. If you have objects coming and going on the stage, you can use one of the techniques described here to handle that. Otherwise, it's fairly straightforward to address your timeline instances from the base Class instead of timeline code. Again, you can listen for those events in the main document Class or a dedicated Controller--the main point is to make sure your Views are not making any important decisions and usually they should not be editing data.
You can choose to have your Main Document orchestrate how the tabs get added and removed (I'm a big fan of using the timeline with goToAndStop, but not everyone shares this preference), or, again, you can separate this logic out to a dedicated Controller. I would suggest that if it's possible to generalize how your Views work to have them implement a single Interface. That way, you can give them a single instance name and manage them all with the same getter/setter pair (assuming you go the timeline route).
Note the Flash compiler isn't terribly sophisticated in this regard, so if you do this and your Views extend different parent Classes, you'll get compiler warnings. Just ignore these--they don't mean anything.
The thing you shoud try to root out of your code completely is the part where Views are referencing each other. The only time it's acceptable for one View to know about another is when it's a parent knowing about its child. Even then, try to have as little specific knowledge as possible. Notice in the Menu View I wrote as an example, the parent only knows there may be some SimpleButtons, but it has no specific knowledge of where they are on stage, what, specifically, is in them, or even what there instance names are.
Instead of having your Views know about one another, have a third party (which, again, you can choose to use the main Document Class for or not) that transfers requests for state changes (in the form of events) from one to another.
Say I have this specific button class in Flash called cont_button and it's supposed to be used to break out of a loop, but I want to use the class more than once. Is there a way to give every instance of this class some kind of parameter so that it knows which frame it nees to go to?
Example:
I have an instance of cont_button on frame 200 and there's a loop between 200 and 210. This cont_button executes a gotoAndPlay(211). But later on I have another instance of the button on frame 315 and a loop between 315 and 325. Is there a way to make it so each instance knows which frame it specifically needs to go to via the use of a variable? Or am I going to have to make an actionscript file for each individual one?
Pretty new to ActionScript so I appreciate the help and if there are good coding references to AS3 you guys recommend, I'll gladly look those over.
Sure, this is possible. One way you can do this is make the frame numbers class variables and when the button is clicked, they reference whatever value is stored in them, rather then hardcoded numbers. To get a better idea, can you post the relevant parts of your button class?
As you say, you need to pass a parameter to each instance of the button. There are lots of different ways you could do this, but I'd be tempted to just do it via the instance names.
You could name each button loopBreakTo211, loopBreakTo326 and so on, then in your button's class have:
var breakFrame:Number = Number(name.replace("loopBreakTo", ""));
(parent as MovieClip).gotoAndPlay(breakFrame);
Admittedly that's not a very robust way of doing it (for example, it will break if a button is named incorrectly and breakFrame ends up as NaN, so you might want to add a check for that), but it keeps the parameter together with the instance instead of in the timeline somewhere.
Suppose I have a setting in NSuserdefaults that should affect a property for a lot (but not all) UIView objects, for example the font size.
The setting can also be changed from a 'main' viewcontroller and should be 'distributed' to UILabel objects that live in a UIView in a UITableviewcell inside a UITableView inside a UINavigationController inside a UISplitviewController and so on...
If I create this property on all levels of the controller and view hierarchy, and set the property when the property in the parent is set, this costs a lot of code.
Apple seems to prefer this pattern to manage the managedObjectContext by handing it to the child controller along the chain.
But this seems like overkill. Lot of code is just for passing around the value of the property, while nothing is done with it. I do however use this pattern to set properties in all subviews of a view at once (by recursively walking through all subviews).
Delegation seems to be just as bad, except maybe not if the delegate would be top level parent view controller. But then I would be passing the delegate around to all child view controllers.
Should I go with Notifications instead? I already have a controller listening to (all) changes in the NSUserDefaults via the NSUserDefaultsDidChangeNotification. Should that controller post a specific notification when my setting is changed? In that case, who should listen to it? Should it be the view controller that is responsible for the views involved?
After some more reading, I found advise in the book Cocoa Design Patterns from Buck / Yacktman, as they state:
As a general rule, use notifications when there are potentially many objects that may observe the notification. Use delegates when exactly one object is given an opportunity to influence or react to changes as they are happening.
So notifications is the answer.
How would someone go about coding a 'window'? I'm starting to make a GUI, and I want to learn how to code one. One that can be skinnable, and one that actually loops and creates itself at runtime. I understand that this might be a bit vague, so I'll add details.
One that actually 'creates' itself. Most GUI tutorials I've looked on depends on an 'image' that just gets added on the screen. I want to be able to use skins in my windows. One where my 'skin' is just a collection of 'borders'. Then when I insert window.create(50,50) where 50,50 is my height, width, It would just create that window, following the skin.
I understand that it probably follows just like when a language draws a rectangle, it just follows a different set of rules (maybe?). However, for all my Google-fu skills I cannot find a tutorial that teaches me this.
Please Help. I didn't include the language I used as you can see, because I believe I just need to know how to create one. Anyway though, I am using Actionscript 3. A tutorial would be just fine, or even A SINGLE CLASS THAT HAS THIS FUNCTIONALITY, I'll just study the code. Or if you know one, maybe a whole book about GUI and programming it :D
Pure As3.0 GUI coding is quite troublesome. I try to Googling, but not come out well. anyway for my case, i generate using a SWC, and Class Mapping and Customizing. but i'm not sure best way. in other way i use a bit101 library. this is gives me want Window, Charts, Componets easily of high abstraction. see the below image.
It can be pretty hard and complicated to do, or very easy, it just depends on how flexible your solution should be. You need firstly to design a structure of your program and approach to the problem.
I like to go from the image of how it should look like from API point of view. I think I would create a GUI element like this:
var wholeGui:MyGUI = new MyGUI();
var window:IGuiElement = new GuiWindow(dataObject, skinObject);
wholeGui.addElement(window);
So what would you need?
1) Object that would manage all GUI elements. Why? Simply because your GUI elements shouldn't be destroyed by themselves if user will click "X" on your little window. The wholeGui object would manage them and listen for any events including those that would destroy them. You may consider creating custom events for interaction between the wholeGui object and your window object if this interaction is going to be complicated.
2) Interface for your GUI objects. Some problem here is that AS3 actually doesn't have interface for Sprite, and you would like to interact with it like with extended Sprite. The workaround here is to have in this interface a declaration like this:
function asSprite():Sprite;
And your implementation in GuiWindow would look like this:
public function asSprite():Sprite {
return this;
}
And your GuiWindow class should extend Sprite of course. Then you would have access to it's Sprite properties and methods by writing for example: window.asSprite.startDrag();
This interface should give you abilities that you need to operate on your GUI element.
3) Class for your GUI element, in this example GuiWindow.
4) Class for your data that would be injected into your element. If you would load data dynamically, and from some location, you would need to deal with the situation when no data can be provided - but that logic would be inside your window.
5) Class for your skin - so you would be able to dynamically create a skin object and use it to create your window in a way you want.
That's just few thoughts to consider.
PS. It may be good idea to fill GuiWindow object with data AFTER creating it, and not in constructor, as you would be able to visualize loading process then.
I have created a custom dijit widget which contains a grid and some buttons.
What is the right way to destroy it? override uninitialize, destroy, destroyRecursive? which method and in which order?
Thanks.
Generally uninitialize is the best place to do this, since it is an extension point called within the destroy function before other teardown occurs.
That said, depending on how you are adding your child widgets, you may not actually have to do anything. For instance, if you are defining your child widgets within a template, widgets declared within a template automatically get added to an array which is iterated through in destroy.
If you wanted to be sure, for testing you could connect to the destroy methods of your child widgets to log a message when they get called.