Page 1 of 2 12 LastLast
Results 1 to 15 of 16

Thread: Dynamic Enemies!

  1. #1

    Dynamic Enemies!

    Hello all,

    I've run into sort of a problem. I'm building up a framework for a game, and I want to have a really flexible, simple way of adding different enemy types. So I've got a basic enemy class with a variety of variables (startx, starty, vx, vy, ax, ay, etc). From my main class, I create a few different enemy types, and have them appear in their appropriate levels based on a timer.

    The problem I'm running into, is that some of the variables I have for each enemy can't be fixed - for example, I have a couple enemy types that spawn in at a dynamic location, like say the right edge of the screen, but at the hero's y position. I'm trying to think of the best way to handle this, because I'm declaring my enemy types before the game loop is running, and when i say enemy1.starty = hero.y, it places every enemy of that type at the same y position, opposed to at the hero's changing y position when the game is running.

    Is there some way to just store dynamic formulas until i'm ready for them, when the game loop is running instead of having them calculated when I initially declare my enemy types? I've been staring at this for a long time, perhaps there is another approach I'm just missing right now
    Last edited by therobot; July 24th, 2008 at 12:01 PM.
    you = function(){
    setEnabled( true );
    live();
    setEnabled( false );
    }

  2. #2
    attach the enemy on screen only when it's inside the "Active Area"(the "AA"),
    the AA can be a code created empty movie clip with minX, minY, maxX and maxY
    these can have the values you want

    store the properties you set in your enemy's into an "enemy object array"
    run through the array and spawn those who are in the AA

    at this point I think you will need the spawnEnemy function and the validPosition function
    they will be something like:
    Code:
    _root.spawnEnemy = function(obj){
        var i;
        var enemy= _root.attachMovie(obj.type, obj.type+i++, 10000+i);
        enemy._x = obj.startx;
        enemy._y = obj.starty;
        ... and so on...
    }
    
    // function to test if the object is in the AA
    _root.validPosition = function(obj){
        if(_root.ActiveArea.minX < obj.startx < _root.ActiveArea.maxX){
            if(_root.ActiveArea.minY < obj.starty < _root.ActiveArea.maxY){
                return true;
            }
        }
        return false;
    }
    then you will test the vars in something like:
    Code:
    for(var i=0; i< enemyArray.length; i++){
        if(_root.validPosition(enemyArray[i])){
            // spawn!
            _root.spawnEnemy(enemyArray[i]));
            // thou shaw only spawn once, and not in every loop while in screen!
            enemyArray[i] = undefined;
        }
    }
    I hope you like this approach
    I know it's like the old '90 games
    but ActiveArea works!

    i'm here to help

    "A human can interpret missing logic but a computer can't." - wkt
    "That goes into the 'too bad' box." - TOdorus
    "This is a three year old thread, there's no reason to post here..." - flyingmonkey456
    "Despite beeing the oposite, they look very similar to me." - SparK

  3. #3
    Smee's Avatar
    637
    posts
    Registered User
    So you want the enemies to lock on to the player's vertical position? Like, when the player moves up, the enemies move with him?

  4. #4
    Hey, thanks for the reply.

    I guess I should be more specific.

    Code:
    			
    // I run this bit of code before the game loop runs.
    function buildLevels ():void
    {
    
    	// Create all enemy types here.
    	// new enemy( Name:String, distr:String, frequency:int, VX:int, VY:int, startX:int, startY:int, 
    	//AX:int, AY:int, BMD:BitmapData, BAD:Boolean, pts:int ):void
    	en1 = new enemy( "pellet", "even", 200, -10, 0, right - 1, hero.y, 0, 0, greyParticles[0], true, 10 );
    	en2 = new enemy( "boulder", "even", 2000, -1, 1, right * Math.random(), 1, 0, 0, greyParticles[2], true, 30 );
    
    
    	// Create level object.
    	level1.enemies = [en1, en2];
    	level1.name = "level1";
    
    	levels.push ( level1 );
    
    
    }
    So each enemy spawns in based upon a timer. For this, I use a custom Timer that can receive parameters that are accessible when a TimerEvent is fired. I use the DataTimer class, a really handy snippet of code I found Here.

    The real problem is in the code above, not below. Take en1, for example. I want its starty to be the hero's y position. Ideally, that would be calculated in my timerCallBack function, since the hero's y position will always be changing. But I can't think of a good way to do this

    Code:
    // Prepare the level based on level1 object.
    var theLevel:Object = levels[ currentLevel ];
    
    for (var i in theLevel.enemies)
    {
    
    	var e:enemy = theLevel.enemies[i];
    
    	// the data timer class extends the timer class.
    	// it's basically a timer that can receive parameters on TimerEvents
    	var myTimer:DataTimer = new DataTimer( e.freq, 0 );
    
    	// In this instance, the TimerEvent receives an instance of each enemy object 'e'
    	myTimer.data.enemyData = e;
    
    	// Let's start this enemy's timer and add a listener to it.
    	myTimer.addEventListener (TimerEvent.TIMER, timerCallBack);
    	myTimer.start ();
    
    	// Add the timer to an array of like-minded timers so we can manipulate them later.
    	enemyTimers.push ( myTimer );
    }
    Code:
    function timerCallBack (event:TimerEvent):void
    {
    	// An enemy timer is ready,
    	// Extract the data from the DataTimer
    	var tmr:DataTimer = event.currentTarget as DataTimer;
    	var e = tmr.data.enemyData;
    
    	// And transpose extracted data onto a new enemy clip.
    	var myEn:p = new p();
    	myEn.name = e.name;
    	
    	// So, this is the problem,
    	// e.startx and e.starty were already calculated...
    	// in this example, en1's starty position is hero.y,
    	// which should change as the game loop runs.
    	// but here it is completely static since it's calculated
    	// before the game loop starts.
    	myEn.x = e.startx; // THIS IS WHERE THE PROBLEM IS.
    	myEn.y = e.starty; // THIS IS WHERE THE PROBLEM IS.
    	myEn.vx = e.vx;
    	myEn.vy = e.vy;
    	myEn.bad = e.bad;
    	myEn.bmd = e.bmd;
    	
    	// Add new enemy to enemiesArray
    	ez.push ( myEn );
    }

    Hopefully that makes more sense now.
    you = function(){
    setEnabled( true );
    live();
    setEnabled( false );
    }

  5. #5
    Smee's Avatar
    637
    posts
    Registered User
    You want the y position of the enemy to equal the y position of the player when the enemy spawns? Where you have 'myEn.y = e.starty', can you put 'myEn.y = hero.y'?

  6. #6
    Quote Originally Posted by Smee View Post
    You want the y position of the enemy to equal the y position of the player when the enemy spawns? Where you have 'myEn.y = e.starty', can you put 'myEn.y = hero.y'?
    Yeah, but some of my enemy types won't spawn at the hero.y...I'd like to be able to declare all my enemy types in one spot, and have a universal function that processes them all, like what I have here. I just need to figure out a good way to organize my variables. I might make some of these variables objects instead with more information than a numerical starting point. Tis probably my best/only bet - I was just feeling a bit lazy
    you = function(){
    setEnabled( true );
    live();
    setEnabled( false );
    }

  7. #7
    Smee's Avatar
    637
    posts
    Registered User
    Can you write a method for the enemies that will set them up based on a 'target' property? So when you create them all at once, just set their 'target' to 'hero'. Then, when you need an enemy, which I think would be in your timerCallBack function, you just run the 'enemy.setup()' method or whatever and it will set it's y position to the position of it's target. That would closer to an OOP method.

  8. #8
    207
    posts
    Registered User
    Yeah, this is a great example of where I would use OOP and polymorphism. Extend the enemy class and override the constructor.

  9. #9
    In my game, the game piece object ( enemy, in your case ) had a setter for position.

    When I create the pieces, it would have default starting point (and AI) but when I put that particular piece into the game board, I would run a function that randomized the x, y coordinate and used the setter to set the piece.

    I would imagine you can also call a function right before you make that enemy available so that its starting position gets updated based on the player's y value.

    Note that my game already had set number of pieces when 'stage' starts... all I had to do was call the setLocationUpdate method right before I let users see it.

  10. #10
    Just some sort of general advice:
    I would recommend you not starting with a framework, as you probably won't grasp all possible prerequisites for your final game entities (after all, they might be changing half-way through). I've tried doing that several times now and never succeeded (despite publishing several games!). Instead, I look for patterns in my projects and extract common classes or algorithms (similar to "refactoring to patterns", but instead of trying to use certain predetermined patterns I try to identify them). That mostly results in a work flow like "Make working code -> make elegant code -> abstract and extract for further use".

  11. #11
    Problem solved.

    I just added a target property like Smee suggested. I was kind of thinking of doing that all along, but I somehow lost track of where I was at. It was one of those things where you spend so long thinking of really complex workarounds, but the answer is usually there, right in front of your face. Oh well. Gotta love that about programming

    Thanks everybody for your input.
    you = function(){
    setEnabled( true );
    live();
    setEnabled( false );
    }

  12. #12
    I know i'm late but...
    putting hero.y in quotes and using
    eval(e.starty) in the callback would work too...

    "A human can interpret missing logic but a computer can't." - wkt
    "That goes into the 'too bad' box." - TOdorus
    "This is a three year old thread, there's no reason to post here..." - flyingmonkey456
    "Despite beeing the oposite, they look very similar to me." - SparK

  13. #13
    Quote Originally Posted by SparK_BR View Post
    I know i'm late but...
    putting hero.y in quotes and using
    eval(e.starty) in the callback would work too...
    Hey Spark_BR,

    I think Adobe took eval() out for AS3. I've never had any experience using eval with AS2, but it's good to know it's out there
    you = function(){
    setEnabled( true );
    live();
    setEnabled( false );
    }

  14. #14
    you use eval when the wanted var name is in the value of the other XD
    it's kinda useful when you use duplicate movie clip, but as I learned attach movie... no more eval for me

    "A human can interpret missing logic but a computer can't." - wkt
    "That goes into the 'too bad' box." - TOdorus
    "This is a three year old thread, there's no reason to post here..." - flyingmonkey456
    "Despite beeing the oposite, they look very similar to me." - SparK

  15. #15
    1,627
    posts
    hugeExplosions = true;
    I'd imagine eval() to be a bit slower than referencing through an object ref, anyone done any benchmarks to that effect?
    MS Paint FTW!


Page 1 of 2 12 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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

Home About kirupa.com Meet the Moderators Advertise

 Link to Us

 Credits

Copyright 1999 - 2012