A Flash Developer Resource Site

Results 1 to 10 of 10

Thread: Can new created objects on stage be set up as tween objects using tween animation?

  1. #1
    Junior Member
    Join Date
    Mar 2011
    Posts
    28

    Can new created objects on stage be set up as tween objects using tween animation?

    Can new created objects on stage be set up as tween objects using tween animation?
    Hi guys,

    I'm currently making my own 2D shoot' em up and I've created a simple enemy spawn state machine which allows the game to automatically keep spawning/creating new enemies on the stage.

    Before I had this spawn loop machine/code set up, I had only one single enemy which was already on the stage to test the gameplay of my game and the enemy as set up tween object using tween animation. I'm wondering if its possible to add/able tween animation on all new created enemies as appear on the stage giving them movement/ai? This is possible?

    I've experimented with some code, I'm failed to succeed withs such functionality, I just wondering where I am going wrong or if anyone knew of any alternatives to my approach?

    Actionscript Code:
    public function makeEnemies():void{
       for(var i:int = 0; i < level; i++){
         var tempEnemy:Enemy = new Enemy();
         addChild(tempEnemy);
         enemies.push(tempEnemy);
         tempEnemy.gotoAndStop(1);
         tempEnemy.addEventListener(Event.ENTER_FRAME, onEnemyMove);
       
         _tweenX = new Tween(tempEnemy, "x", Regular.easeInOut, tempEnemy.x, _randomX, 45, false);
         _tweenY = new Tween(tempEnemy, "y", Regular.easeInOut, tempEnemy.y, _randomY, 45, false)
          _tweenX.addEventListener(TweenEvent.MOTION_FINISH, onMotionFinishX);
         _tweenY.addEventListener(TweenEvent.MOTION_FINISH, onMotionFinishY);
    }
     function onMotionFinishX(event:Event){
        var tempEnemy:Enemy = new Enemy();
        var tweenObject:Tween = tempEnemy(event.currentTarget);
          //Calculate new start and finish positions
          tweenObject.begin = tempEnemy.x;
          tweenObject.finish = Math.ceil(Math.random() * 400);
          tweenObject.finish = player.x;
          //Start the Tween object playing again
          tweenObject.start();
    }
     function onMotionFinishY(event:Event){
       var tweenObject:Tween = tempEnemy(event.currentTarget as Tween);
          tweenObject.begin = tempEnemy.y;
          tweenObject.finish = Math.ceil(Math.random() * 400);
          tweenObject.finish = player.y;
          tweenObject.start();}
      }
     function onEnemyMove(event:Event):void{
         var enemy:Enemy = Enemy(event.currentTarget);
         enemy.vx = enemy.x - enemy.oldX;
         enemy.vy = enemy.y - enemy.oldY;
         enemy.oldX = enemy.x;
         enemy.oldY = enemy.y;
         enemy.gotoAndStop(1);

        if (enemy.x > stage.stageWidth){ // stage perimeters for collision
             enemy.vx *= _bounce;
             enemy.x = stage.stageWidth;}
        if (enemy.x < 0){ // stage perimeters for collision
             enemy.vx *= _bounce;
             enemy.x = 0;}
        if (enemy.y > stage.stageHeight - 35){// stage perimeters for collision
             enemy.y = stage.stageHeight - 35;
             enemy.vy *= _bounce;}
        if (enemy.y < 0){// stage perimeters for collision
             enemy.y = 0;
             enemy.vy *= _bounce;}
    }


    It doesn't seem to like this line of code -

    Actionscript Code:
    var tweenObject:Tween = tempEnemy(event.currentTarget as Tween)

    - either I get a error saying that tempEnemy is undefined method or if I change it to Enemy instead of tempEnemy I get a error 1067: Implicat coercion of value of type Enemy to an unrelated type.fl.transitions:Tween.

    Does this line make sense? Or am I'm going into the wrong direction? Thank you for your time and reading all that and any help/suggestions would be greatly appreciated.

    Thanks

    Jonesy

  2. #2
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    tempEnemy is a variable of type Enemy, and it was local to makeEnemies. You cannot cast something to a variable, and even if you could tempEnemy is undefined outside of makeEnemies.
    When you change it to Enemy, you get a cast error, because a Tween is not an Enemy. Casting doesn't magically change what something actually is, it just tells the compiler that a variable is of a more specific type than what it could figure out on its own.

    the event.currentTarget in your onMotionFinish functions will be the Tween that just finished. I don't deal with the built in Tween stuff much because TweenLite is so superior, but according to the livedocs, you can get the object being tweened through the Tween's obj property.

    Edit: I was looking at onMotionFinishY. In onMotionFinishX you do have a defined tempEnemy variable of type Enemy, but it still is meaningless to try to cast a Tween to that.
    Last edited by 5TonsOfFlax; 04-12-2011 at 10:42 AM.

  3. #3
    Junior Member
    Join Date
    Mar 2011
    Posts
    28
    OK sure, so what you would suggest? Use Tweenlite or use a alternative way to create random movement for enemies via co-ordinates perhaps?

    I looked at Tweenlite site looks like a good way to save time on coding complex AI but I would how reflexable would it be for what I want to achieve?

    Jonesy

  4. #4
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    It kinda looks like you are trying to have the enemies periodically move to where the player is or was. If you want them to continuously re-aim towards the player, I wouldn't use any sort of tween, but just move them a little towards the player each frame. If you do want them to aim at where the player was at a specific time, I'd use TweenLite. But you can use the built in Tween, still.

    Why are you setting the finish property twice? You know that the second one overwrites the first, right? How could it have two?

  5. #5
    Junior Member
    Join Date
    Mar 2011
    Posts
    28
    Basically from what i gather that you need tween Y axis and X axis functions to blend the animation motion together to make movement to use both axises at the same time seamlessly.

    I've only even coded AI/enemy movement via tween motions, so that you would code the AI movement in function onEnterFrame or onEnemyMove tracking the player position? Wouldn't you have set enemies to have global co-ordinates to track the player? Or could you set enemy movemenet to be
    x = -5 per frame = x.player position?

    In other words, do you have any code suggestions? Thanks again

    Jonesy

  6. #6
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    You've put all your functions inside makeEnemies again. There's no reason to do that. It only complicates things.

    You're also moving your enemies in onEnemyMove and giving them conflicting animations through Tweens. They can't do both. Or rather, they can, but the Tween will screw up the other stuff.

    Let's say you wanted each enemy to advance by some number, n, pixels in each dimension towards the player each frame:

    Code:
    private var maxEnemyStep:int = 3
    
    public function makeEnemies():void{
       for(var i:int = 0; i < level; i++){
         var tempEnemy:Enemy = new Enemy();
         addChild(tempEnemy);
         enemies.push(tempEnemy);
         tempEnemy.gotoAndStop(1);
         tempEnemy.addEventListener(Event.ENTER_FRAME, onEnemyMove);
       }
    }
    
    public function onEnemyMove(event:Event):void{
         var enemy:Enemy = Enemy(event.currentTarget);
         var xDiff:Number = player.x - enemy.x;
         var yDiff:Number = player.y - enemy.y;
         //if they are further than maxEnemyStep away in x
         if (Math.abs(xDiff) > maxEnemyStep){
            if (xDiff < 0){
              xDiff = -maxEnemyStep;
            }else{
              xDiff = maxEnemyStep;
            }
         }
         //if they are further than maxEnemyStep away in y
         if (Math.abs(yDiff) > maxEnemyStep){
            if (yDiff < 0){
              yDiff = -maxEnemyStep;
            }else{
              yDiff = maxEnemyStep;
            }
         }
         enemy.x += xDiff;
         enemy.y += yDiff;
    
         enemy.gotoAndStop(1);
    
        if (enemy.x > stage.stageWidth){ // stage perimeters for collision
             enemy.x = stage.stageWidth;
        }else if (enemy.x < 0){ // stage perimeters for collision
             enemy.x = 0;
        }
        if (enemy.y > stage.stageHeight - 35){// stage perimeters for collision
             enemy.y = stage.stageHeight - 35;
        }else if (enemy.y < 0){// stage perimeters for collision
             enemy.y = 0;
        }
    }
    I also took out all the velocity code, because we are directly setting the position each time. You could do something more sophisticated and alter the velocity according to the direction to the player.

  7. #7
    Junior Member
    Join Date
    Mar 2011
    Posts
    28

    Great :) Thank you - works very well

    Great Thank you - works very well. I'm currently experimenting with their movement perimeters/properies because they over lap each other as they follow the same path. I'm thinking to either try to randomise their movement patterns or create AI perimeter so they just stay away from each other (don't overlap, they don't have any collision setup among as themselves enemies but only for the player).

    I've attempted this code from your previous code for enemies to say away from other enemies:

    Actionscript Code:
    }
    if (Math.abs(enemy.x - tempEnemy.x) < 20){ //// if 20 pixels X axis away
        if(Math.abs(enemy.y - tempEnemy.y) < 20){ //// or if 20 pixels Y axis away
           enemy.x += -enemy.xDiff;
           enemy.y += -enemy.yDiff;
           enemy.XDiff *= -1; /// applying friction so should slow down/stop
           enemy.YDiff *= -1; /// applying friction so should slow down/stop
         }

    This should work but surely I don't need create another loop? Also I have the problem with identifying between enemy and tempEnemy, when they appear the stage they are var type called enemies, not tempEnemy right?

    Thanks again

    Jonesy

  8. #8
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Where did you put that code? I suspect that either or both of enemy and tempEnemy are undefined there.

    Also, xDiff and yDiff are not properties of an Enemy, so I'm not sure what you're trying to use them for there.

    Similarly, XDiff and YDiff are also not properties of an Enemy. Be sure to keep your cases consistent, even when you're making up stuff that doesn't exist.

    -1 is not a damping fraction. That would just completely invert the values. To damp, you'd need to multiply by something between 0 and 1.

    If you want to keep all the enemies away from each other, then you will have to check each enemy against all the other enemies. This can be done with a nested loop.

    Code:
    for (var i:int = 0; i < enemies.length -1; i++){
      for (var j:int = i+1; j < enemies.length; j++){
        var enemy1:Enemy = enemies[i];
        var enemy2:Enemy = enemies[j];
        //do something with two enemies, like test their distance, or apply a repulsive force.
      }
    }
    Edit: I think you mean "parameter", not "perimeter". And you definitely still mean "properties", not "properies".

  9. #9
    Junior Member
    Join Date
    Mar 2011
    Posts
    28

    Sorry typing too quickly - too much coffee

    I placed that code within function onEnemyMove, just below your code
    Actionscript Code:
    var enemy:Enemy = Enemy(event.currentTarget);
         var xDiff:Number = player.x - enemy.x + 3;
         var yDiff:Number = player.y - enemy.y + 3;
       
        //if they are further than maxEnemyStep away in x
         if (Math.abs(xDiff) > maxEnemyStep){
            if (xDiff < 0){
              xDiff = -maxEnemyStep;
            }else{
              xDiff = maxEnemyStep;
            }
         }  /////etc

    Oh I just realised that maxEnemyStep defines the enemy's VX and VY movement, not yDiff or xDiff. yDiff or xDiff are distance between player and enemy, right? So if you can't use them, what other alternatives is there code wise to keep enemies away from each other?

  10. #10
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    onEnemyMove is called once per frame, per enemy. This is not the best place to put enemy-enemy interaction because if you iterate over all the enemies within onEnemyMove, you will test each pair both ways (enemy A vs B as well as B vs A), which is twice as much work as you have to do.

    I'd put in a separate ENTER_FRAME handler for the game as a whole, and do the optimized nested loop as I described above. You can calculate distance between enemies the same way we did distance between enemy and player. But really all you want to do is detect whether they're touching and if so move them to be not-touching. Unless you want them to keep some distance from each other, but that's just a small change.

    So in the nested loop, get the distances from one to the other. If they are too close, move one or both. Of course, moving one might move it to be near another one, but then that would be caught on the next frame. You may or may not be satisfied with the visual results of that approach.

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