A Flash Developer Resource Site

Results 1 to 10 of 10

Thread: Any way to expect 3 diffrent classes?

  1. #1
    Member
    Join Date
    Jul 2009
    Posts
    56

    Any way to expect 3 diffrent classes?

    Hi.
    so to the point:
    I have 3 diffrent types of bullets that are being shot.
    On collision or go off screen, I need to delete this bullet from my Array of bullets.

    Now, with 1 bullet, its all easy, I envoke the bullet removing function from within the bullet class itself, passing the param "this", therfore thats some identifying means.
    the removing function then compares what was passed to all the bullets the array contains, on a a match, removes it from the array.

    all simple.

    HOWEVER ( dun dun dun! )
    I have 3 diffrent bullet types, each with their own class. ( its not just the graphic of the bullet, its also speed and what it does ).
    So therfore, I cant expect to be passed Bullet, because it could be Bullet2 or Bullet3.

    any way to work around this problem?

  2. #2
    AS2 intolerant person
    Join Date
    Jan 2009
    Location
    Swansea
    Posts
    352
    All sounds very complicated :P still not sure whats your doing, but it obviously involves treating different data types in the same way.

    If your bullets classes extend MovieClip or Sprite, then create a class that extends them in actionscript (not in the library). then create any functions and properties you need to allow for all bullet types, and in the library, make the bullets extend that new class.

  3. #3
    Total Universe Mod jAQUAN's Avatar
    Join Date
    Jul 2000
    Location
    Honolulu
    Posts
    2,429
    Ok, two separate issues here. I'll give you one popular OOP approach, but better game devs might have a different view.

    Keep your bullets dumb. Your bullet class should just do bullet like things like move forward. You should have a management class that in addition to updating other things, checks on all the bullets during each tick/game loop and do stuff to them, ie. destroy, move forward, show bang animation. This separation of duties allows you keep your bullet classes small, logical and easy to edit. The bullets themselves should not be looping over all the other bullets, they shouldn't even know about each other. If you have each bullet checking on every other bullet, that's tons of extra processes and lots of repetition. A management loops over the array of bullets once and is done with it.

    Now, as far as similar classes, there are two approaches. Interfaces and Abstract classes. Interfaces are just lists of functions a class must have but doesn't say what they should do. They're helpful when you have to react to similar events in different ways. Say you had a class that loaded thumbnails from Flickr and another that loaded thumbs from Youtube. You'd want both classes to report when they are done but they might do that in different ways. If both classes implement an interface that defines a reportWhenDone() method, you're sure to be able to use both classes without breaking the larger app. However, this doesn't really help when the different classes do nearly the same thing like bullets that each move forward.

    This is where you want to use abstract classes. AS3 does not define an Abstract class type but you can make one work that way. Basically its a generic class that defines the common ground. You never actually create an instance of it, instead, you sub-class it with the specific or "concrete" versions.
    So you could have an AbstractBullet class that defines a moveForward() method. You could sub-class that with SmallBullet, BigBullet, BlueBullet and so on. Since they all subclass AbstractBullet, you can call moveForward() on any one of them and they'll do the same thing without actually having to write moveForward in each class. A subclass inherits all code from its parent class.

    Just a quick sample

    Actionscript Code:
    package{
      public class AbstractBullet extends Sprite{
        public var moveSpeed:int = 3;
        public function AbstractBullet(){

        }

        public function moveForward():void{
           // do move forward stuff using moveSpeed
           x += moveSpeed;
        }
      }
    }


    // a subclass of AbstractBullet
    package{
      public class FastBullet extends AbstractBullet{
        public function FastBullet(){

        }
      }
    }

    // now in your main, you'd create FastBullet and set its speed
    var myFastBullet = new FastBullet();
    myFastBullet.moveSpeed = 6;

    // then later, when your loop tells all bullets to move forward, they each move at their own speed
    myFastBullet.moveForward();
    Last edited by jAQUAN; 06-21-2011 at 05:52 AM.

  4. #4
    Member
    Join Date
    Jul 2009
    Posts
    56
    Quote Originally Posted by jAQUAN View Post
    Ok, two separate issues here. I'll give you one popular OOP approach, but better game devs might have a different view.

    Keep your bullets dumb. Your bullet class should just do bullet like things like move forward. You should have a management class that in addition to updating other things, checks on all the bullets during each tick/game loop and do stuff to them, ie. destroy, move forward, show bang animation. This separation of duties allows you keep your bullet classes small, logical and easy to edit. The bullets themselves should not be looping over all the other bullets, they shouldn't even know about each other. If you have each bullet checking on every other bullet, that's tons of extra processes and lots of repetition. A management loops over the array of bullets once and is done with it.

    Now, as far as similar classes, there are two approaches. Interfaces and Abstract classes. Interfaces are just lists of functions a class must have but doesn't say what they should do. They're helpful when you have to react to similar events in different ways. Say you had a class that loaded thumbnails from Flickr and another that loaded thumbs from Youtube. You'd want both classes to report when they are done but they might do that in different ways. If both classes implement an interface that defines a reportWhenDone() method, you're sure to be able to use both classes without breaking the larger app. However, this doesn't really help when the different classes do nearly the same thing like bullets that each move forward.

    This is where you want to use abstract classes. AS3 does not define an Abstract class type but you can make one work that way. Basically its a generic class that defines the common ground. You never actually create an instance of it, instead, you sub-class it with the specific or "concrete" versions.
    So you could have an AbstractBullet class that defines a moveForward() method. You could sub-class that with SmallBullet, BigBullet, BlueBullet and so on. Since they all subclass AbstractBullet, you can call moveForward() on any one of them and they'll do the same thing without actually having to write moveForward in each class. A subclass inherits all code from its parent class.

    Just a quick sample

    Actionscript Code:
    package{
      public class AbstractBullet extends Sprite{
        public var moveSpeed:int = 3;
        public function AbstractBullet(){

        }

        public function moveForward():void{
           // do move forward stuff using moveSpeed
           x += moveSpeed;
        }
      }
    }


    // a subclass of AbstractBullet
    package{
      public class FastBullet extends AbstractBullet{
        public function FastBullet(){

        }
      }
    }

    // now in your main, you'd create FastBullet and set its speed
    var myFastBullet = new FastBullet();
    myFastBullet.moveSpeed = 6;

    // then later, when your loop tells all bullets to move forward, they each move at their own speed
    myFastBullet.moveForward();
    hmm, I think your answer didnt really aim at my question, my I didnt explain well.
    Keep in mind, what im doing is not with bullets, but the same principle.
    Thats why the bullets are being "shot" from the main class.
    Ill tell u the current way im doing it :
    Main Class - Sets everything up, then on certain intervals or events, shoots a bullet.
    It has a "create bullet" function, that:
    Chooses type of bullet between 3. ( Math.random, then saves it to a variable)
    Randomizes an angle, then gets the Sin and Cosine to be used. ( not straight up )
    Chooses What Side to start at - Left or Right.

    It then creates a bullet based on the paramaters above.
    So it will create either Bullet,Bullet2, or Bullet3, and send in the paramaters.

    Code:
    var b:Bullet = new Bullet();
    var Bullets:Array = new Array();
    Bullets.push(b);
    addChild(b);
    So as u can see, It creates a random bullet, adds it to the Array, then puts it on the display list.

    Now, each bullet class is basicly the same, but a little bit diffrent. ( speed, Graphic, rotation speed).

    Each bullet class takes the Starting Position, left or right, takes the DirectionX and DirectionY, then adds an event listener that moves it every frame ( time based ).
    on the listener, there is an "if" statement to check if its off the screen.
    Now, if it is, I want to delete of course.
    this is where I cant figure it out.

    I can remove it from the display list using removeChild.
    But before I do that, I need to remove it from the array.

    So what I did, is I made a function in the main class, that will get the bullet passed to it, and then it will compare it with each bullet in the array, and if there is a match, delete it.

    BUT
    If I have 3 different classes, I cant make the function
    Code:
    public function removeTheBullet(someBullet:Bullet) {
    }
    Because can also be Bullet2 or Bullet3.
    Hence, im stuck

  5. #5
    Senior Member
    Join Date
    Aug 2006
    Posts
    322
    What you are doing is pushing the bullets when it release from the pistol and remove if it not hits the aim or if it goes out of the stage.

    My suggestion is to push into the array only when it hits the target. Associatively if you want to track the number of bullets release from the pistol, you can store it in a variable or in an associative Array.

    Might this make sense to you.

    What happen if you not push it when it release?



    marlopax

  6. #6
    Member
    Join Date
    Jul 2009
    Posts
    56
    Quote Originally Posted by marlopax View Post
    What you are doing is pushing the bullets when it release from the pistol and remove if it not hits the aim or if it goes out of the stage.

    My suggestion is to push into the array only when it hits the target. Associatively if you want to track the number of bullets release from the pistol, you can store it in a variable or in an associative Array.

    Might this make sense to you.

    What happen if you not push it when it release?



    marlopax
    Im storing it in the Array because thats how im checking for collisions, looping through the array.

    why would I want to add it to the Array if it collides thou?

  7. #7
    Total Universe Mod jAQUAN's Avatar
    Join Date
    Jul 2000
    Location
    Honolulu
    Posts
    2,429
    Probably another reason to extend an abstract class. You could type your parameter as AbstractButton and any sub-class of it would pass. How are you finding it in the array? Direct comparison? as in:
    Actionscript Code:
    if (myArray[i] == someBullet){
    }
    ?

    If you're looping through the array and checking position, you already have the array position by way of the loop's iterant, just splice that number out.
    for instance:

    Actionscript Code:
    for (var i:int = 0; i < myArray.length; i++){
      if(AbstractBullet(myArray[i]).x > stage.stageWidth){
        myArray.splice(i, 1);
      }
    }

    For cleanliness, you'll want to remove all event listeners within the bullet to free up memory. Otherwise you risk overflowing the users stack and crashing the app. Best practice is to write a public destroy() method in the bullet classes. Have that method remove any listeners that were assigned during init.

    Actionscript Code:
    for (var i:int = 0; i < myArray.length; i++){
      if(AbstractBullet(myArray[i]).x > stage.stageWidth){
        var myBullet:AbstractBullet = myArray.splice(i, 1) as AbstractBullet;
        myBullet.destroy();
      }
    }

  8. #8
    Member
    Join Date
    Jul 2009
    Posts
    56
    Quote Originally Posted by jAQUAN View Post
    Probably another reason to extend an abstract class. You could type your parameter as AbstractButton and any sub-class of it would pass. How are you finding it in the array? Direct comparison? as in:
    Actionscript Code:
    if (myArray[i] == someBullet){
    }
    ?

    If you're looping through the array and checking position, you already have the array position by way of the loop's iterant, just splice that number out.
    for instance:

    Actionscript Code:
    for (var i:int = 0; i < myArray.length; i++){
      if(AbstractBullet(myArray[i]).x > stage.stageWidth){
        myArray.splice(i, 1);
      }
    }

    For cleanliness, you'll want to remove all event listeners within the bullet to free up memory. Otherwise you risk overflowing the users stack and crashing the app. Best practice is to write a public destroy() method in the bullet classes. Have that method remove any listeners that were assigned during init.

    Actionscript Code:
    for (var i:int = 0; i < myArray.length; i++){
      if(AbstractBullet(myArray[i]).x > stage.stageWidth){
        var myBullet:AbstractBullet = myArray.splice(i, 1) as AbstractBullet;
        myBullet.destroy();
      }
    }
    Wait so, If I extend "superBullet" to "abstractBullet", superBullet can be passed as an argument that is an "abstractBullet"?

    right now, I just merged all the classes together, making just the graphics changeable. Untill I can find the final solution, because I want to move on to other things right now.

    An yes obviously, Im removing the event listeners as well

  9. #9
    Total Universe Mod jAQUAN's Avatar
    Join Date
    Jul 2000
    Location
    Honolulu
    Posts
    2,429
    Yes, OOP uses two common descriptions for classes. "Has a..." and "Is a..." They refer to how a class got its abilities. Did is use "composition" or "inheritance". Classes that include instances of other classes "have a" instance of that class. That's composition. Classes that extend other classes "are a" instance of that class. That's inheritance. In OOP we prefer to favor composition over inheritance but inheritance is great when an undetermined member of a certain class "family" or type is expected.

    So if you had AbstractBullet then extended it to SuperBullet, WeakBullet etc, you could write this function,

    Actionscript Code:
    function doStuff(bullet:AbstractBullet):void{
      // do stuff
    }

    You could pass any subclass of AbstractBullet:
    var mySuperBullet:SuperBullet = new SuperBullet();
    var myWeakBullet:WeakBullet = new WeakBullet();

    doStuff(mySuperBullet);
    doStuff(myWeakBullet);
    because SuperBullet IS A AbstractBullet and WeakBullet IS A AbstractBullet.

    The whole point of abstraction is to put methods and properties common to all subclasses in one place and add unique features to the subclasses. You can even override methods in the abstract class.

  10. #10
    AS2 intolerant person
    Join Date
    Jan 2009
    Location
    Swansea
    Posts
    352
    in short, a variable of the base-class datatype can incorporate the properties and methods of a sub-class instance. If can still refer to it by its base class data type, but on the inside, it has already been converted to an extended object.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center