How can i get a function to use any movie clip? - function

I'm a little lost in understanding this kind of function, i get the feeling this has been asked a thousand times but cannot find an explanation of what the code is doing.
Basically i just want a movie clip with instance name box to do something, then reuse the function for other movie clips afterwards
a little like this, but working.
Many Thanks
//my function to be used on "instance name" box
myfunc (box);
function myfunc ();
{
while (this is happening);
{
//in this case box.x = goes where ever i put it
.x = goes here
.y = goes here
}
}
Sorry it's not quite English, my communication skills are terrible

Sure you can do that. You give the function a parameter, then refer to a parameter to change its properties. With such a simple movement function it could accept a DisplayObject - a distant superclass of a MovieClip and thus a superclass to many other possible classes of those objects that can be displayed by Flash.
function myfunc(param:DisplayObject):void {
// no semicolon after declaring the function!
while (somethingIsHappening(param)) {
// why not call a query on that object?
param.x+=1; // move right by 1 pixel
}
}
You might want to look at this manual on ActionScript 3 syntax, and the following pages on variables, functions and classes, to learn more.

Related

Check the existence of an object instance

I'm surprised I don't know how to do this, but as it turns out I really don't; simply put, I'm trying to make a side-scrolling shooter game, a basic one and in it, I have 50 stars spawned on-screen through a "for" loop upon the game starting. There is a function which does this and a listener is at the beginning. Problem is, when you lose the game and go back to main menu, 50 more stars would be spawned, which isn't what I want. So, I'm trying to make an "if" statement check at the beginning, so that the game checks whether there is an instance/movie clip of the star object/symbol before determining whether the function that spawns stars should be called out with a listener. So, how do I do this? I looked through some other checks and they didn't help as the codes presented were vastly different there and so I'm just getting errors.
Let me know if a better explanation is needed or if you would like to see some of the code. Note that the game overall already has a lot of code, so just giving all of it would probably not be helpful.
I suggest you rethink your approach. You're focusing on whether stars have been instantiated. That's ok but not the most basic way to think about it.
I would do this instead
private function setup():void{
loadLevel(1);
addListeners();
loadMusic();
// etc...
// call all functions that are needed to just get the app up and running
}
private function loadLevel(lev:int):void{
addStars();
// call all functions that are needed each time a new level is loaded
}
private function restartLevel():void{
// logic for restarting level,
// but this *won't* include adding star
// because they are already added
}
There are other ways to do this but this makes more sense to me than your approach. I always break my game functions into smaller bits of logic so they can be reused more easily. Your main workhorse functions should (IMHO) primarily (if not exclusively) just call other functions. Then those functions do the work. By doing it this way, you can make a function like resetLevel by assembling all the smaller functions that apply, while excluding the part about adding stars.
Here's what I did to solve my problem... Here's what I had before:
function startGame():void
{
starsSpawn();
//other code here
}
This is what I changed it to:
starsSpawn();
function startGame():void
{
//other code here
}
when you said existance, so there is a container, i named this container, (which contain stars , and stars was added to it) as starsRoot, which absolutely is a DisplayObject (right?)
now, to checking whole childrens of a DisplayObject, we have to do this :
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
}
then, how to check if that child is really star!?
as you said
whether there is an instance/movie clip of the star
so your stars's type is MovieClip, and they don't have any identifier (name), so how to find them and make them clear from other existing movieclips. my suggestion :
define a Linkage name for stars from library, thats a Class name and should be started with a capital letter, for example Stars
now, back to the code, this time we can check if child is an instance of Stars
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
if (child is Stars) {
// test passed, star exist
break;
}
}

Possible to have multiple timelines? (separate part without affecting the keyframes of other layers) AS3

http://i.snag.gy/eu7iz.jpg
So im doing this generator/designer on flash. It has different features on it so the keyframes clashes with other features considering a lot of the action scripts deal with nextframes and gotos. Its getting confusing once i add little features.
Like right now i wanna add next buttons for the design part. I can do it easily with a blank stage, i can easily click next and back, but when applied to my project, its getting a little dizzying.
This is the script for the first frame:
stop();
small.addEventListener(MouseEvent.CLICK,play1);
function play1(event:MouseEvent):void{
gotoAndStop("3");
}
medium.addEventListener(MouseEvent.CLICK,play2);
function play2(event:MouseEvent):void{
gotoAndStop("6");
}
large.addEventListener(MouseEvent.CLICK,play3);
function play3(event:MouseEvent):void{
gotoAndStop("8");
}
item_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragTheObject);
item_mc.addEventListener (MouseEvent.MOUSE_UP, itemRelease);
item_mc1.addEventListener(MouseEvent.MOUSE_DOWN, dragTheObject);
item_mc1.addEventListener (MouseEvent.MOUSE_UP, itemRelease);
item_mc2.addEventListener(MouseEvent.MOUSE_DOWN, dragTheObject);
item_mc2.addEventListener (MouseEvent.MOUSE_UP, itemRelease);
function dragTheObject(event:MouseEvent):void {
var item:MovieClip=MovieClip(event.target);
item.startDrag();
var topPos:uint=this.numChildren-1;
this.setChildIndex(item, topPos);
}
function itemRelease(event:MouseEvent):void {
var thisItem:MovieClip=MovieClip(event.target);
thisItem.stopDrag();
};
This is the fla file: https://www.dropbox.com/s/77euop1luqjreos/FINAL.fla
MovieClips have their own timeline.You may want to modularize your program into Movieclip components and export for Actionscript manipulation that you can instantiate at run time as necessary. Now that is one way to do it to avoid code spread across one single timeline.But If you still want to stick to your way (use of single timeline), You still could achieve your next/previous implementation without affecting frame logic at any rate.A simple way to do this goes like this:
Encapsulate all logic into functions and put these functions solely on frame 1 and nothing else.
This keeps logic clean and separate from the components.Also, the logic layer in principal should not have nothing else.Why on Frame 1?. Well, we want to expose and keep in memory first the logic, so that whatever component related code that follows on the subsequent frames should be aware of the previous logic and hence throw no run time errors when interacting frame 1 logic.
Spread your components and related code across the subsequent frames respectively.
Put only component related code on a frame that has the component in question. registering event listeners could have targets as their dependency. define event listeners and put them on frame 1 as part of the logic and simply put code for registering listeners on the component frames as per demand.
Example:
//On Frame 1
function onAMouseClick(event:Event):void
{
//implement logic
}
function onBMouseClick(event:Event):void
{
//implement logic
}
//Implemented function for next/back buttons
//Also on Frame 1
function navigate(event:Event):void
{
var frame:int;
switch(event.target.name)
{
case "nextBtn":
frame=currenFrame<numFrames?+1:numFrames;
gotoAndStop(frame);
break;
case "backBtn":
frame=currenFrame>2?-1:currentFrame;
gotoAndStop(frame);
break;
}
}
//On Frame 2 for A component
A.addEventListener(MouseEvent.CLICK, onAMouseClick)
//On Frame 3 for B component
B.addEventListener(MouseEvent.CLICK, onAMouseClick)
Put Next/Back button components on a single layer spreading from frame 2 all the way to the end of the last frame where you want the buttons to be visible. Then implement related code having its visibility spanning across between frame 2 and the last frame as the following shows:
//navigate handler is declared and implemented on **frame 1**
nextBtn.addEventListener(MouseEvent.Click, navigate)
nextBtn.addEventListener(MouseEvent.Click, navigate)
Well, that is your way of doing things (Single timeline scripting). Not bad for simple timeline scripting.You may try the other way also of instantiating Movieclips (exported for action scripiting)
at run time and the add these to the display list as per demand as on clicks next/back buttons.In doing so you will not only have one single point of logic but will have MC code encapsulated in each individual component.
Hope the foregoing helps. Thanks.
Do not be scared to change code! Let alone afraid to run into errors! That's way forward you want to learn to fix things that's a beauty of it!
.....cheers!.

Is my class-less AS2 programming close to OOP in spirit?

So I'm a flash game developer trying to make the transition from AS2 to AS3+OOP, only 3 years or so after everybody else did. There's a plethora of free, very helpful material to go through and I've been spending 2-3 days wrapping my head around some of it, but by now I feel like I just want to start and try it out and learn the harder stuff as I go (just like I did with AS2).
I get the benefits of (most aspects of) OOP and I was once forced to learn to do a couple of games in Processing which had me write a few classes and I really liked the whole inheritance thing, which is the biggest reason I'm keen to move on, I think.
I just wanted to ask about game structure - is my current way of AS2 programming (see the example below, with some pseudo code) close to the way you'd organize things in OOP, or are there some big flaws in my game logic/structure that I can't see? The way I understand I would have to do differently in AS3/OOP is to have a class for moving stuff such as the player, hero, missiles etc, then have an enemy class that extends that class, then have classes for each enemy that extends the enemy class, unlike now where each "class" is instead an object and a function called from the main game loop, and sub-classes are instead "if"-clauses in each function. But except for that, is my programming style on the right track or do I need to re-think the logic behind my code for it to work effectively in an AS3/OOP setting?
Any advice will be much appreciated!
function initializeF() {
initializeVariablesF();
startGameF();
}
function initializeVariablesF() {
enemyO = new Object(); //which will contain each enemy instance
enemyA = new Array(); //which will be a list of all the enemies, maybe superfluous?
playerShotsA=new Array();
//and so on...
enemyDataO = new Object();
enemyDataO.goblin = new Object();
//and then some vars relating to the goblin, sort of a class without methods, right?
}
function startGameF() {
this.onEnterFrame = function() { //my game loop
checkKeysF(); //checks which keys are pressed, saves it to a global object
playerMovementF(); //moves the player about depending on which keys are pressed
playerShotsF(); //deals with the missiles/shots/lasers the player has shot
enemyCreatorF(); //decides when to create a new enemy
enemyF(); //deals with all enemies in the enemyA
enemyShotsF(); //deals with the missiles/etc the enemies have created
};
}
function enemyCreatorF(){
//randomly creates an enemy through a "factory" function:
if (random(20)==1){
attachEnemyF(enemyDataO.goblin, ...and some values like position etc)
}
}
function attachEnemyF(a_enemyType, ... a bunch of values like position){
//create a new enemy object
var enemy=enemyO[new unique enemy name]
enemy.enemyType=a_enemyType
enemy.clip=attachMovie(a_enemyType,"clip", [values like x and y passed on])
enemyA.push(enemy)
}
function playerShotsF(){
for (every shot in playerShotsA){
//move it about
for (every enemy in enemyA){
//if it hits an enemy, add damage to the enemy
}
}
}
function enemyF() {
for (every enemy in enemyA) {
//check if it's dead/less health than zero, if so remove it from the array, remove it's clip, null it's object
//if it's not, move it about, maybe have it shoot
//if it touches the player, decrease the player's health
//different behavior depending on the enemy's type by "if" or "switch" statements
}
}
I'm not sure the question is a good fit for SO as it's mostly asking for opinions, but anyway:
Having a base class with basic functions such as "move", "hitTest", "render", etc. is indeed what you should do. Then have the player's avatar, enemies, etc. inherit from this class.
The F suffix (and even O and A suffixes) are quite superfluous, since any good AS3 editor will already tell you whether the class member is a function, or an array, object, etc.
You don't need to store your enemies in both an array and an object, it's going to make it unnecessary complicated to remove or add an enemy. Instead, just store them all in an array and use simple loops to inspect their properties.

Game logic and game loops in ActionScript 3

I am making a Shooting game in flash actionscript 3 and have some questions about the flow of logic and how to smartly use the OOPs concepts.
There are mainly 3 classes:
Main Class: Initializes the objects on the screen.
Enemy Class: For moving the enemies around on the screen.
Bullet Class: For shooting.
What I want to do is find out if the Enemy has been hit by a bullet and do things which must be done as a result ...
What I am doing right now is that I have a ENTER_FRAME event in which i check collision detection of each enemy unit (saved in an array) with the bullet instance created, and if it collides then perform all the necessary actions in the Main class .. clogging the Main class in the process ..
Is this the right technique ? or are there better solutions possible ?
Try to think more OOP, what is every object responsible for?
We have the enemies wich we can hit:
class Enemy : extends NPC implements IHittable {
. . .
function update(delta) {
// move, shoot, etc.
}
function handleHit(bullet) {
// die
}
}
A hittable object:
interface IHittable {
function handleHit(bullet);
}
The bullet is suppose to move and hit things:
class Bullet : {
function update(delta) {
// update position
}
function checkHits(world:World) {
for each(var hittable:IHittable in world.objects) { // might want to cluster objects by location if you're handling lots of objects / bullets)
if (isColidingWith(hittable))
o.handleHit(bullet);
}
}
}
And then we have the world with everything inside:
class World {
var npcs: Array ...
var bullets: Array ...
var hittables: Array ...
function update(delta) {
foreach(var c:NPC in npcs)
c.update(delta);
foreach(var b:Bullet in bullets) {
b.update(delta);
b.checkCollisions(world);
}
}
}
And your main loop is just simple as that:
var lastTime:int;
function onEnterFrame(...) {
var now:int = getTimer(); // FlashPlayer utility function to get the time since start (in ms)
world.update(now - lastTime);
lastTime = now;
}
A few other notes:
try to do all the computation based on a delta of time, otherwise the game's speed will vary with the framefrate.
what happens when a character dies? bullet disappear? Well, you could do it several ways:
fire an event, like EnemyDied and remove it from the world
implement an interface CanDie that has a (get dead():Boolean property) and use that to cleanup the world at every update.
but don't write the code to remove the enemy in the Enemy class, because then you will be polluting the class with code that should be handled by the World, and that will be hard to maintain later.
Sorry for the long answer, but I couldn't help myself :)
Was clogging the Main class the problem, or finding out what bullet hit what enemy the problem? If it was the bullet, you need to describe the bullet behavior - can it hit multiple enemies, how fast does it move (is it possible that when testing using "enterFrame" the bullet will first appear in front of the enemy, and, on the second frame, it will appear behind the enemy?). May enemy be simplified to some basic geometrical shape like circle or rectangle, or do you need pixel-perfect precision? Finally, how many bullets and how many enemies are you planning to have at any one time? It could be too expensive to have a display object per bullet, if you are going to have hundreds of them, and then it could make more sense to draw them into single shape / bitmapdata.
If the problem is that the Main class is too long, there are several possibilities here.
A nobrainer answer to this problem - use inheritance to simply put parts of the code in separate files. Not the best way, but a lot of people do it.
If you did the first, then you'd realize that there are certain groups of functions you put into superclass and subclasses - this will help you split the "clogged" class into several smaller independent pieces that have more particular specialization.
After you did the second, you may find out that there is certain dependency between how you split the big class into smaller classes, so you can try generating those smaller classes by a certain pattern.
And then you write the clogged code that generalizes those parts you just managed to split.
Above is basically the cycle from more concrete to more generic code. In the process of perfecting the last step, you'll write some concrete code again. And that will move you to the step 1. Lather, rinse, repeat :) In fact, you don't want to write OO code, or procedure code or anything that fashion of the day tells you to do. You want to write good code :) And you do it by moving from more generic to more specific and back to more generic, until it's perfect :P
Probably not the best answer, but you must admit, you didn't give much info to give you more precise answer.

as3 Access to undefined property?

Can someone help me to find out why I'm getting the error message "Access to undefined property: removeChild(goBack)" on the following snipped?
BTW, this is for flash CS4
function nameOfFunction() {
var goBack:backButton_mc = new backButton_mc();
goBack.x = 10;
goBack.y = 700;
goBack.back_text.text = myXML.*[buildingName].NAME;
goBack.name = "backBtn";
goBack.buttonMode = true;
addChild(goBack);
goBack.addEventListener(MouseEvent.CLICK, anotherFunction);
}
function anotherFunction(e:MouseEvent):void {
removeChild(goBack);
}
You are wrong with the scope. (surprise :-D)
The variable goBack is just defined inside of "nameOfFunction", when you try to access this from a another function like "anotherFunction" it will not exists anymore (even if it is on the display list)
There are different possibilities to solve this problem:
function anotherFunction(e:MouseEvent):void {
removeChild(e.currentTarget);
}
Or the best way would be: promote goBack as a class member of the class holding both functions. (Or if you don't use classes make goBack "global".)
Hippo is correct, but I feel it is important to explain a little more.
You created a local variable, i.e. var someVariable:DataType; within a function. This means that that variable will only be available to objects in the scope (inside) of the function (local to), and it will only last for the lifetime of the function. Soon as that function has ran the code is gone until ran again. It looks like you are probable programming directly inside the flash IDE on the time-line, which is fine, but, if you were using a document class, you could merely declare you variable in the Class scope just above the constructor function, and then set the value in the same function that your using now. This way, the reference to the variable doesn't exist within the function, it is merely set from within. This will allow that variable to be accessed from anywhere in the same class even if set to private.
This may help:
//Frame 1, Actions layer
//Slap goBack right onto the root / stage
var goBack:MovieClip;
/*
I noticed you had this data-typed differently,
i prefer to type to an interface, not an implementation.
Since your class is a movieclip in the library it extends
MovieClip and therefor IS A MovieClip, but ok either way.
*/
function nameOfFunction():void
{
goBack = new backButton_mc();
goBack.x = 10;
goBack.y = 700;
goBack.back_text.text = myXML.*[buildingName].NAME;
goBack.name = "backBtn";
goBack.buttonMode = true;
addChild(goBack);
goBack.addEventListener(MouseEvent.CLICK, anotherFunction);
}
function anotherFunction(e:MouseEvent):void
{
removeChild(goBack);
}
Scope is very important and after a while very easy to tackle. Stick with it, experiment, read up on conventions and standards that can help your development and get to loving the DocumentClass becuase even though it may be daunting to some at first, once you learn it and get used to it, it so hard to go back to programming in the flash IDE on the timeline, where I believe only display objects and audio have any place being.