Flash Platformer Game changing between two characters - actionscript-3

So I'm new to coding as a whole and though I've messed a little with AS before I'm at an absolute loss. I've been using a pretty helpful website that gives a step-by-step on making a platformer/sidescroller, but one of the key things I want to include in my game is the ability to swap between two characters- i.e., if the player hit space or any other key, you could swap out to the other character (with different abilities and all).
My game only really has one big stage, and it's nothing complicated at all (it's something I'm trying to get done in about a little over 24 hours) which is why I decided not to make the character change for each "level"- because there's only one big one. I want the player to be able to decide when they want to play whichever character they fancy, but I have no idea how to go about it.
Uh, and if it helps clarify anything, I basically tried to follow that tutorial site as closely as I could without copying source code.
Thanks so much for taking the time.

You need to do a thing named "separate graphics from code". The tutorial says "convert your player to a Movie Clip Symbol ... create new Player(), add it to stage", then it teaches about how to control the player. You need to split your Player class into two, one remains as Player and contains code, the other is a skin class, barely a MovieClip without code. In your Player class you need to make a method to operate skins, the interface is up to you, I suggest a string lookup of a skin class, then you can tell your player to change skins both at costruction time and probably at runtime. An example:
public static const SKIN_DEFAULT:String="default";
public static const SKIN_RED:String="red";
public static const SKIN_BLUE:String="blue";
private static var SKINS:Object={
SKIN_DEFAULT:DefaultFace;
SKIN_RED:RedFace;
SKIN_BLUE:BlueFace;
}
Here, SKINS is a lookup object with keys as strings and value as Class references, these are the MovieClip symbol names an example expects to exist. Say you want a gray blob, a red angry face and a blue smiley save to be available, you name them DefaultFace, RedFace, BlueFace and put these names into this lookup object. Then, you need to make your player change skins. It's pretty easy once you get the drill.
public class Player extends Sprite {
// Sprite should do, as Player is now code-only
private var skin:MovieClip; // this will hold our player's skin
public function setSkin(newSkin:String):void {
// call this to change the skin
var newSkin:Class=SKINS[newSkin] as Class;
if (newSkin==null) return; // sanity check
if (skin) if (skin is newSkin) return;
// ^ changing skin for the same? We're that skin already!
if (skin) if (contains(skin)) removeChild(skin); // remove old skin
skin=new newSkin(); // create a new skin object
addChild(skin); // make it attached to the player
} // we're done!
// rest of code here
}
Make sure that your Player will at least put on default skin when created, or else you won't be able to see player move.
In order to trigger skin change, you can create an array of buttons, up to making them out of all possible SKINS (for this, either expose SKINS variable by declaring it public instead of private as it's now, or provide another means to get the list of classes), which will call player.setSkin() with a correct parameter.

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.

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.

Assign integer values to movie clips in ActionScript 3

I am trying to make a card game in Flash using ActionScript 3. I'm not too familiar with the language(grew up with AS2) but I considered it to be more appropriate for this project.
Bad thing about this, though, is that I ran into a problem right away: I'm treating each individual card as a movieclip, but something that I really need is to assign some integer values to the card(It's not really the case, but as an example let's say that I am working on a Poker and I want all Aces to carry the value 1 because they are the best card, 2 for the kings, etc).
I tried looking for it but all I found is how to make arrays of movieclips. I know that this question shouldn't be too hard! Can somebody help me?
(As an aside note, should I really work with movie clips or would buttons be more convenient?)
Firstly, from my point of view, never use components unless you really need to since they take longer time to draw and they're not flexible. I've had so many issues with them in the past (this question I posted being one of those).
About MovieClip's… The MovieClip class is dynamic so you can assign any virtual property to it, no problem. So yourMcInstance.someVar = 3 is perfectly valid.
One of the major changes in AS3, I think, was the introduction of Sprite class, which is basically a MovieClip without a timeline. It is much lighter and unless you're manually creating frame animations it is the class to choose for any container that can handle mouse (and many other) events. However, it is not a dynamic class so yourSpriteInstance.someVar = 3 wouldn't be valid. And that's why using custom classes is encouraged. With custom classes you have the option to extend a class and create custom properties and methods.
because Movieclips are Objects, you can actually attach variables directly to them.
var card:MovieClip = new MovieClip(); //create a blank MC
addchild(card);
card.id = 5; //You can attach vars like this
To add MovieClips to an Array:
const clips:Array = [];
function addNewCardToCardsArray(array:Array, color:String, value:int):MovieClip {
const clip:MovieClip = new MovieClip();
clip.color = color;
clip.value = value;
return array[array.length] = clip;
}

Practical way of getting a picture of a library object

I´m making a level creator for my platformer game on AS3. I´m looking for a way of getting a graphical representation of a library object on my .fla, so the user can insert that object on the world on the desired coordinate. What I mean with this is that I just want a picture of the first frame of the mc, without taking its properties and methods (without the need to make a .jpg containing that image), because that´s when problems begin to appear, and I just want the object functionality on play mode, not the level creator.
Let´s say, for example, a ball that bounces all the time by updating its location every frame. On the level creator I just want to get the ball picture to insert it on the desired location. If I take the whole ball object to the level creator it won´t stop bouncing and it will mess things up.
I hope I´m clear... I just want to know if there is a practical solution to this; if not then I´ll make a class where all the world objects would extend to, that has a init() function that initializes all the object functionality, so it´s called only on play mode and not on level creator. Thanks for reading anyway.
What you're doing wrong is adding functionality directly to the MovieClip.
Please read one of my previous answers that covers this concept in more depth.
MovieClips should be used for the display only, representing the graphics of an actual game class, for example:
public class Player
{
// Graphics that represent the Player.
protected var display:MovieClip;
// Constructor.
public function Player()
{
display = new PlayerMovieClip();
}
}
Anyways, once you fix that you can take a Bitmap sample of MovieClips using BitmapData and its draw():
// Assume that 'mc' is your MovieClip.
var sample:BitmapData = new BitmapData(mc.width, mc.height, true, 0);
sample.draw(mc);
// This is your image.
var texture:Bitmap = new Bitmap(sample);

Interaction between classes

In my main Actionscript file i have a instance of a body class that moves the person body arms legs etc. and a gun class which has methods and properties to do with the person gun.
Right now i have a function in the Main class which is called move gun and looks like this and is called everyframe to move the gun to the bodys arm. I was hoping to move this function to the guns class so i could call it like gun.moveGun(); but the body dosent exist inside the gun variable. so i wonder if i could call the body.getArm(); function from inside the gun. I know i could call the function and pass the bodys arm location to it from the main file. But don't know if this is the best way to do it.
private function moveGun():void
{
gun.x = body.getArm('left').x;
gun.y = body.getArm('left').y;
}
It seems like keeping the gun related functions inside the gun class is the best way to organise everything but i dont know how to do this.
Also depending what button someone clicks at the start the person will either have a basketBall or gun in there hand. Ive added the swf online at Here so you can see how it works. i just wanna change how its organised because the main file is very full and though i should learn how to organise things better. There are lots of other part of the program that would be organised better if i knew how to get the object to interact or what is the best way to do it. Starting to think passing the x,y coordinates to the moveGun function inside the gun Class is the best way. If so just tell me please and ill do that.
From the code you posted, I think you need to move the gun with every frame to stick to the player's arm.
The answer you're looking for is Composition, since every person gets one and only one gun, I think you better put a reference (variable) in the person class for its gun.
and here is your player (person) class:
class Person
{
private var m_gun:Gun;
public function Person()
{
this.m_gun = new Gun();
}
// a function which is called each frame
private function updateFrame()
{
// Here you can provide your own logic in Gun class
this.m_gun.doSomething();
}
}
generally, you want to communicate between classes using the built-in event listener and dispatcher system. if 'something' happens - regardless of 'where' that occurs - dispatch an event. whenever something should react, it should have a listener.
for example, from the main class you mentioned, you might want to dispatch an event:
private function moveGun():void
{
var e:Event = new Event('moveGun', true);
dispatchEvent(e);
}
then the appropriate instance (the body? - not sure how you have things set up) listen for that:
body.addEventListener('moveGun', moveGunHandler, false, 0, true);
function moveGunHandler(event:Event):void{
gun.x = body.getArm('left').x;
gun.y = body.getArm('left').y;
}
the above is obviously psuedo-code since i have no way of knowing how your display list is set up. also, i used simple string literal event types - best practice would probably be to use custom event classes with event types defined as static constants.