Extending a class that is not defined during compile time - actionscript-3

I'm working on a bot in actionscript for a flash game, with some success. My actionscript basically loads the game, finds the functions it needs and calls it to do stuff. For example, ExternalLoadedGame.Game.Action.MoveNorth() to take a step up.
However, some functions are defined as protected, and I can only get access if I can extend that class, but when I try to do that, my compiler tells me that the class is not Compile time consistent and it doesn't work. And if I copy the definition, the game functions don't accept my version of the class, even though it's literally they share literally the same class definition.
I need to specifically override some of the class functions that are called by the game, without access to modify the game files.
Is there any way to extend, make public, or anything similar without modifying the game's SWF file beforehand?

Related

FlashDevelop Actionscript 3 development environment inquiry

I'm puzzled by the FlashDevelop environment. I'm working through the tutorial at:
http://prototyprally.com/making-games-in-actionscript-3-using-flashdevelop-part-1-the-setup/
I'm doing things exactly the way he describes. However, once I add the class Enemy I am not able to establish communication between Main and Enemy. Obviously I'm missing something basic, but I get compile time errors no matter what I do.
I'm using the latest version of FlashDevelop (4.5.2.5). How do I get two different files (both under the same package) to communicate with each other?
You instantiate 'Enemy' in 'Main.' Then you refer to it by its instance name.
So, for instance inside of 'Main' you might say var enemy1:MovieClip = new Enemy.You can then add it to the display list if you choose. Meanwhile, of course, you have a class called 'Enemy.as' that holds the code for your enemy, whatever that is. It MIGHT be a graphic MovieClip in your .fla library. If that's the situation and you don't need any or much code you could add the library enemy directly from 'Main.' Just make sure to refer to it by its AS Linkage name.
OK, I figured it out. The import statement needs to be:
import com.grapefrukt.tutorial.supergame.enemies.Enemy
Looks like the size of the display in the tutorial chopped that off.

AS3 How can one detect that a display object is subject to a motion tween?

I guess this is a question for real gurus only..
I'm using the Flash Authoringtool to create MovieClips, yet I play them using my own engine (which behaves better for mobile).
Yet, for proper behaviour, given a DisplayObject, I need to know if its parent is tweening it inside the MovieClip it is part of.
I've already come up with Brute-force and non-elegant ways to do that:
In the authoring tool, add a prefix to the name of any movieclip that is subject to tweening. That name prefix can be checked lateron at any moment. Of course, as this prefixing is a manual process, it's easy to forget or mistype one.
In the code, play each sub-movieclip of the main movieclip for all of its frames, and for all of its children, detect if the transformation matrix changes at any of these frames. If so, automatically prefix their names. Although automized, this solution may take up noticable time for larger movieclips.
So what I'm hoping for is that some other way exists like:
if((dpo.parent) as MovieClip) != null)
{
bDpoIsBeingTweened = ((dpo.parent) as MovieClip).someProperty;
}
Looking forward to any elegant solution.
The solution is quite simple: stop using Adobe's tweening library.
Use TweenLite which is hundreds of times faster, easier to code, and has many other benefits. For example being able to use isTweening to determine if some object is being tweened or not.
Here's the documentation.
To include external libraries in the Flash IDE you can do it in 2 ways.
1) Copy the folder of the external library in your project folder (where your .fla file is)
2) Define a folder in "File > Actionscript settings" where you want to put external libraries files in your hard disk.
Then in your code you just need to import those classes with import. For example:
import com.greensock.TweenLite;

Is Code On The Timeline Easier Or Harder For Hackers To Steal/Decompile?

Can anyone tell me whether code on the timeline is harder or easier to steal/decompile?
Or is it all just the same?
There's no real difference. A dedicated programmer can always get to and reverse engineer your ActionScript. Bear in mind it's not just 3rd party apps like Sothink that can be used. Even Adobe have a tool for 'inspecting' a swf: http://labs.adobe.com/technologies/swfinvestigator/.
If your code is genuinely special enough to warrant stealing, then you would want to use a platform other than Flash (or put your sensitive code into an external C/C++ assembly and run that using something like Alchemy).
Are you really doing something so unique that people are going to try to steal it, though? Is it so special they couldn't just figure out what you've done and copy it?
The difference is essentially nil. In AS3, timeline code will end up inside classes anyway. The code for the main timeline will appear in *filename*_fla.MainTimeline. The code for Symbol1 will appear in *filename*_fla.Symbol1, and so on.
Timeline code can be slightly easily to understand, since variables not explicitly declared as local variables will become class variables. The names of class variables are preserved in a SWF, whereas local variables are not.
Check out my online ActionScript dissembler if you're curious about how your code is stored inside a SWF.

How should I substitute an image in a larger animation using AS3?

We're making a Flash browser game with a few reasonably complex animations. Our designer is making the animations in Flash Professional while I'm wiring everything up and adding some logic through AS3 (using FlashDevelop).
In one of our more complex animations a "bonus item" moves around the screen. It tweens hither and tither, there special effects and as such, it disappears for a few frames and then reappears later.
From AS3 we want to be able to dynamically decide which bonus item (say a mushroom or a star) to include in the animation. We don't want to have to ask our designer to replicate the entire animation for each of our bonus items.
This is what we've tried:
Created a two frame (1 mushroom frame, 1 star frame) "BonusItem" movieclip in FlashPro and Exported for ActionScript.
Created the complex animation movieclip in FlashPro and added the BonusItem movieclip to the relevant frames. Gave the BonusItem instance an instance name on all necessary KeyFrames. Exported entire movieclip for ActionScript (exported as "ComplexAnimation").
Intention:
The intention was to be able to do this:
var complexAnimation:ComplexAnimation = new ComplexAnimation();
complexAnimation.bonusItem.gotoAndStop("star"); // Frame labels have been added in FlashPRo.
this.addChild(complexAnimation);
This would play the complex animation with the star and we could easily call gotoAndStop("mushroom") to play the same animation with the mushroom.
Problems:
The first problem was that complexAnimation.bonusItem was null on line 02 above. I solved this by handling ADDED_TO_STAGE for complexAnimation and putting line 02 above in the handler.
The next problem was that each time the bonusItem movieclip started tweening, or if it was not present in some frames and was subsequently re-added the complexAnimation.bonusItem attribute/reference was reassigned to a new bonusItem instance. I then had to find a way to know when this was happening and call gotoAndStop("star") on the new instance.
I've found two ways to do this:
1) Listen for ADDED events on complexAnimation with a target.name of "bonusItem". It's a bit crap in a strongly typed language to have to resort to matching strings, but this works. Btw, when the ADDED event is fired new frame object references are still null.
2) Listen for FRAME_CREATED events. This happens later than ADDED at a point where new frame references have been initialized. As such I can check if complexAnimation.bonusItem is non-null at then call gotoAndStop("star") on it. One problem with this is that calling gotoAndStop actually triggers another FRAME_CREATED event to fire, so I need to guard against infinite looping. Again, it works but I don't have a great feeling about it.
Conclusion:
Well I don't really have a conclusion other than I feel like I'm working really hard to do something relatively simple. I'm hoping there's an easier & more robust approach. I have a strong feeling that I'm going crazy. Anyone know a better way to do this?
If you have an object that exists on a timeline and it has an instance name, and you need to be able to maintain a reference to it through the duration of the timeline, then it must exist on every frame (and in the same layer!) of the movieclip. I grant you, your workarounds get the job done but you have already experienced the pain involved in doing so.
The path of least resistance is to just have the object exist at all times. If the user shouldn't "see" it, just hide it offscreen somewhere. Just make sure it always exists, contiguously, on that timeline layer from frame 1 all the way to the final frame.
The other thing I'd suggest is to stop deeply nesting movieclips in the hopes of using those nested clips as state representations. This is one of the things that sadly was very easy to do in the AS2 days, but has been rendered impractical to the point of madness in AS3. Anything deeper than 1 layer is getting into some dicey territory. 3 layers deep and you need to rethink your strategy. Perhaps instantiating different movieclip instances from the library and adding/removing dynamically instead of relying on frames.
I thought I'd update this post with our current (and hopefully long-term) solution.
First of all, I made an error in the above post:
The next problem was that each time the bonusItem movieclip started tweening ... the complexAnimation.bonusItem attribute/reference was reassigned to a new bonusItem instance.
This was incorrect. Flash was indeed assigning a new instance of BonusItem, but it was caused by a Mask layer keyframe rather than the tween.
I had been keen to try to avoid having any logic which relied on string comparisons, but in the end I swallowed my pride to make life easier.
Our designer gives all relevant objects (stuff that we'll need to access from AS3) instance names on each keyframe in the timeline. If the object is nested within other objects our designer must assign those parent objects instance names too. We must coordinate those instance names so that dev know what the accessors are called - we would've had to do all this anyway. Our designer also still has to "Export For Actionscript" a class for each relevant movieclip (e.g. BonusItem).
In AS3 we're using Robotlegs for dependency injection and as the basis of our MVC framework. Robotlegs suggests that application-specific logic should be separated from view-specific logic. It allows us to specify a logic class (called a Mediator) to be associated with each and any of our views. As such we can do the following mapping:
BonusItem -> BonusItemMediator
This means that every time Flash creates a BonusItem on the timeline Robotlegs somehow knows about it and creates a new instance of BonusItemMediator (which we write ourselves and have full control over). In addition, Robotlegs can easily give us a reference from our BonusItemMediator to its associated view instance (the BonusItem instance). So inside my BonusItemMediator I can ask the view reference what its instance name is. I also walk up its parents to the stage and record each of their names to generate a resultant string of instance names that uniquely specified this instance of the BonusItem.
e.g.
"game.complexAnimation.bonusItem"
Once I know this I can ensure that the bonusItem is showing the correct image (star or mushroom) with the following code:
var frameLabelName:String myGameModel.whatTheHellShouldThisBeShowing("game.complexAnimation.bonusItem");
this.view.gotoAndStop(frameLabelName); // where view is the BonusItem instance
So now regardless of how or when Flash seemingly randomly decides to destroy and recreate my bonusItem I'll hear about it and can ensure that that new BonusItem instance is displaying on the correct frame.
The main weakness with this solution is that we're relying on string comparisons. Our designer could easily mistype an instance name and we wouldn't hear about it until that code was hit at runtime. Of course tests mitigate that risk, but I still feel that it's a shame that I'm using a strongly typed language, but then not making use of the compile time type checking.

Problem using Flash Components in multiple SWC files

[Edit: Short version - how do you properly handle namespace collisions in SWC files if one SWC has fewer classes from that namespace than another?]
I have a rather large Flash application which I'm building in Flash Builder (because coding/debugging in the Flash IDE is... not good) and I've got a ton of external SWC files which I'm linking in to my application. This has worked well so far - the file size is on the large side, but it's a lot simpler than loading in SWFs, especially since I am extending most of the classes in each SWC and adding custom code that way (it's a very design-heavy app.) The problem I'm having is when I have Flash Components, like ComboBox or TextInput, in more than one SWC. Whichever SWC was compiled last will work fine, but the others will fail with errors like the following:
TypeError: Error #1034: Type Coercion failed: cannot convert flash.display::MovieClip#1f21adc1 to fl.controls.TextInput.
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at com.company.design.login::LoginForm()
at com.company.view::Login()[/Users/ken/Workspace/src/com/company/view/Login.as:22]
at com.company.view::Main/showLogin()[/Users/ken/Workspace/src/com/company/view/Main.as:209]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at com.company.view::Navigation/handleUIClick()[/Users/ken/Workspace/src/com/company/view/Navigation.as:88]
I've been researching components, ComponentShim, etc. but I'm running up against a brick wall. I thought it might be the fact that some of the components had their skins modified in the source FLA, so I tried replacing them with the default skins, but that didn't seem to help. How can I ensure that I have the components imported and available to all my classes, yet still be able to skin them and include them in my various FLAs? (I am never creating new instances of them, they are all laid out by my designer.)
I dunno if this will help you, but I had a similar problem with an asset in a SWC library that was the visual representation for a class in my main project. What I ended up doing was having the visual asset be a Flash-created class that extended the class in my project rather than having the same name.
For example, my asset and the class were both com.blah.TitleBackground. To fix the issue I made the visual asset have teh class of com.blah.TitleBackgroundAsset and set the base class for the component to com.blah.TitleBackground. That fixed this particular issue for me. I still have more to wade through, but your post sparked the idea for the solution to get around the name conflicts.
I can't find the detailed fix (apparently, the work email I used at the time was trashing older messages without my knowledge!) but the short answer is to create one FLA that has all the components you want to use in it, set those components (and the ComponentShim) to 'Export for Runtime Sharing'. Then, in your other FLAs, whenever you want a component, drag it from the components FLA library (it should show up in your main library with 'Import for Runtime Sharing' turned on.) Make sure you don't have a ComponentShim in your main library. You'll need the compiled component SWF file in the same folder as your FLAs.
What this does is keep all the component code, including skins, in one central place, so when you compile (be it as a SWF or a SWC, though this problem mainly crops up when using SWCs) there are no conflicts.