Boids: natural flight movement and behavior

Post your example zscripts/ACS scripts/etc here.
Forum rules
The Projects forums are only for projects. If you are asking questions about a project, either find that project's thread, or start a thread in the General section instead.

Got a cool project idea but nothing else? Put it in the project ideas thread instead!

Projects for any Doom-based engine (especially 3DGE) are perfectly acceptable here too.

Please read the full rules for more details.
User avatar
eharper256
Posts: 1038
Joined: Sun Feb 25, 2018 2:30 am
Location: UK
Contact:

Re: Boids: natural flight movement and behavior

Post by eharper256 »

Seems to be fine to me. If the boid is not going to do anything with the player or monsters, you could add the +NOINTERACTION flag to make it need less attention from the game engine. If you want to give it sprites for an actual bird you'll need to add some states as well.

If you look at the main boid class, there are quite a few parameters you can change:

Code: Select all

	Action Void BoidFlight(
		Class<Actor> BoidActor = "HXA_Boid",	//This is the class type that boid will follow and try to match velocities with
		double MaxVelocity = 20,				//This is the max speed that it will go
		double VelocityAcceleration = .2,		//This is how fast the increases its speed
		double WallDetectionDistance = 6,		//How far away the Boid will detect walls.  WallDetectionDistance * velocity, so the distance increases the faster it goes
		Bool CloseToMaster = FALSE,				//Will remain near master pointer if TRUE
		double DistanceFromMaster = 400,		//Max distance from master pointer
		Bool CloseToTarget = FALSE,				//Will remain near target pointer if TRUE.  Overrides Close to master.
		double DistanceFromTarget = 400,		
		double MinDistanceToBoid = 150,			//Will try to move away from boids within this distance
		double MaxDistanceToBoid = 900,			//Will try to move toward boids if further than this distance
		double BoidCohesion = 3,				//How hard the boid will try to remain with other boids and match their velocities
		double MinDistanceBeacon = 100,			//Creates a beacon to move toward at least this far away
		double MaxDistanceBeacon = 300,			//Creates a beacon to move toward at most this far away
		double MaxAngleBeacon = 100,			//Creates a beacon at an angle at most this far from its current velocity
		double MaxRandomMoveAngle = 120,		//The max angle that the boid will randomly create a vector to move toward
		double HorizonNormalizer = 1,			//Adjusts all vectors in the array to turn toward the horizon.  Higher than 1 moves them to horizontal faster, less than 1 lessens the effect
		Bool UsePropertyValues = TRUE			//If this is true and the default arguments have not changed, then the arguments will use the values of the actor's properties.
												//Otherwise will force the use of the given argument values.
You can use something like HorizonNormalizer = 3, placed after DistanceFromMaster in the BoidFlight argument, if you want to level off erratic Z movement a bit, but keep in mind that 200 is quite a small area and this might cause it some pathing issues, so you might also want to fiddle with the other parameters, and allow it place closer beacons with a higher max angle or use a lower velocity.
User avatar
Enjay
 
 
Posts: 26534
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland
Contact:

Re: Boids: natural flight movement and behavior

Post by Enjay »

Thanks for the info and the sanity check. :D

I'll mess around with those parameters to get something that I like. I forgot about the NOINTERACTION flag, that should come in handy too.
[edit]NOINTERACTION gives a very noticeable improvement when the boids first spawn if the spawner is set to spawn them in large numbers.[/edit]

I do plan on making it look like a bird. Writing the states is no problem but I'm struggling to find decent bird sprites ATM. Rather, I can get some quite nice ones but all the good-looking ones I've found so far are usually just single-angle ones and not even the front angle (usually the side). Even the crow on Realm667 is like that.

[edit2] A bit more cutesy than I wanted but it will do for the moment, at least as a place-holder. It has 4 angles and a 4 frame flight animation too. Image[/edit2]
[edit3]Doh! Googling "crow sprites" turned up a link to this very forum and some nice sprites by Neoworm.
Image[/edit3]
User avatar
4page
Posts: 120
Joined: Tue Aug 06, 2019 5:08 pm
Location: American Pacific Northwest

Re: Boids: natural flight movement and behavior

Post by 4page »

Just to add on, what you have would work ok, but the line HXA_Boid.BoidActor "NJBoider"; isn't QUITE right. This property is a little unclear I suppose, but what you're doing with this is telling your little Boids to ONLY follow and flock with the thing that spawned them. So they won't really flock with each other, but they'll stick around the spawner, since they're programmed to be close to them. Which could be a reason for their erratic behavior.

What you should do is make the spawner inherit from HXA_Boid, set its HXA_Boid.FlockID property to a random number, then have the spawned boids copy that FlockID to their own, And set their HXA_Boid.BoidActor NJBoid. This way they'll follow each other, and won't interfere with other flocks with different IDs.
Something like-

Code: Select all

Class NJBoider : HXA_Boid
{
    Default
    {
         +NOGRAVITY;
        HXA_Boid.FlockID random(0,255);
    }
    ....................
}

Class NJBoid : HXA_Boid
{
    Override void PostBeginPlay()
    {
        if(master)
        {
            FlockID = HXA_Boid(master).FlockID;
        }
    }
    Default
    {
        HXA_Boid.BoidActor NJBoid;
        +NOINTERACTION;
    }
    .........................
}
It's not foolproof, since you're relying on a random number to be different, but at the moment it's the simplest way to get what you want. I'll make a note to add a function for a boid to copy its master's FlockID number. And see if I can make a function to generate a new unused FlockID number.
User avatar
Enjay
 
 
Posts: 26534
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland
Contact:

Re: Boids: natural flight movement and behavior

Post by Enjay »

Thanks for the input - and the fact that I've made the boids stick close to the spawning actor rather than the flock would explain what I am seeing. However, when I include your lines I get:

Code: Select all

Script error, "BoidLib.Pk3:z_hxa/njboid.zsc" line 19:
Invalid global identifier 'NJBoid'
Line 19 is HXA_Boid.BoidActor NJBoid;

and I also get:

Code: Select all

BoidLib.Pk3:z_hxa/njboid.zsc, line 59: @property@HXA_Boid.FlockID: non-constant parameter
Line 59 is HXA_Boid.FlockID random(0,255);

Both actors now inheriting from HXA_Boid.

[edit]Slightly modified code to remove commented out stuff (so line numbers are no longer the same as the error messages)

Code: Select all

Class NJBoid : HXA_Boid
{
        Override void PostBeginPlay()
        {
            if(master)
            {
                FlockID = HXA_Boid(master).FlockID;
            }
        }
    
    Default
    {
        HXA_Boid.BoidActor NJBoid;
        +NOINTERACTION;
    }
        
    States
    {
        Spawn:
            TNT1 A 0 A_SetScale (frandom(0.8,1.2));
        Spawn2:    
            BIRB AB 2;
            BIRB DCD 3;
            Loop;
        Death:
            TNT1 A 1;
            Stop;
    }    
}

Class NJBoider : HXA_Boid
{

        Default
        {
             +NOGRAVITY;
            HXA_Boid.FlockID random(0,255);
        }
    
    States
    {
    Spawn:
    POSS A 0;
    POSS A 0 A_JumpIf(args[0] == 0, "BoidsIsNull");
    //
    SpawnBoids:
    POSS A 1 Bright A_SetArg(4, args[0]);
    SpawnBoids2:
    POSS A 0 Bright A_JumpIf(args[4] == 0, "NoMoreBoids");
    POSS A 0 Bright A_SpawnItemEx("NJBoid",20,0,40,0,0,0,0,SXF_SETMASTER|SXF_NOCHECKPOSITION);
    POSS A 0 Bright A_SetArg(4, args[4] - 1);
    Goto SpawnBoids2;
    
    
    BoidsIsNull:
     CPOS A 1 A_SetArg(0, 8);
     goto SpawnBoids;


    NoMoreBoids:
    SPOS A -1;
    Stop;
    }
}
User avatar
4page
Posts: 120
Joined: Tue Aug 06, 2019 5:08 pm
Location: American Pacific Northwest

Re: Boids: natural flight movement and behavior

Post by 4page »

Ok, I'm going to blame tired brain instead of my own ineptitude on this one.
Line 19: HXA_Boid.BoidActor "NJBoid"; "NJBoid" Should have quotes around it.
Line 59: I was afraid this would happen and was just hoping it wouldn't.
instead of that line you can do a postbeginplay override:

Code: Select all

        Override void PostBeginPlay()
        {
            FlockID = random(0,255);
        }
I wish it were a bit easier to do, so I'll try to put out an update in a few days, when I get a chance to work on it.
User avatar
Enjay
 
 
Posts: 26534
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland
Contact:

Re: Boids: natural flight movement and behavior

Post by Enjay »

Thanks again for the input. It starts now but the spawned NJBoids just sit stationary at the location of the NJBoider that spawned them.

Have I made the changes correctly?

Code: Select all

Class NJBoid : HXA_Boid
{
        Override void PostBeginPlay()
        {
            if(master)
            {
                FlockID = HXA_Boid(master).FlockID;
            }
        }
    
    Default
    {
        HXA_Boid.BoidActor "NJBoid";
        +NOINTERACTION;
    }
        
    States
    {
        Spawn:
            TNT1 A 0 A_SetScale (frandom(0.8,1.2));
        Spawn2:    
            BIRB AB 2;
            BIRB DCD 3;
            Loop;
        Death:
            TNT1 A 1;
            Stop;
    }    
}

Class NJBoider : HXA_Boid
{

        Override void PostBeginPlay()
        {
            FlockID = random(0,255);
        }

        Default
        {
             +NOGRAVITY;
        }
    
    States
    {
    Spawn:
    POSS A 0;
    POSS A 0 A_JumpIf(args[0] == 0, "BoidsIsNull");
    //
    SpawnBoids:
    POSS A 1 Bright A_SetArg(4, args[0]);
    SpawnBoids2:
    POSS A 0 Bright A_JumpIf(args[4] == 0, "NoMoreBoids");
    POSS A 0 Bright A_SpawnItemEx("NJBoid",20,0,40,0,0,0,0,SXF_SETMASTER|SXF_NOCHECKPOSITION);
    POSS A 0 Bright A_SetArg(4, args[4] - 1);
    Goto SpawnBoids2;
    
    
    BoidsIsNull:
     CPOS A 1 A_SetArg(0, 8);
     goto SpawnBoids;


    NoMoreBoids:
    SPOS A -1;
    Stop;
    }
} 
User avatar
neoworm
Posts: 1743
Joined: Fri Sep 23, 2005 9:17 am
Location: Czech Republic

Re: Boids: natural flight movement and behavior

Post by neoworm »

Enjay wrote:[edit3]Doh! Googling "crow sprites" turned up a link to this very forum and some nice sprites by Neoworm.
Image[/edit3]
I was thinking about trying the boids script with this. Let me know how it works out.
User avatar
eharper256
Posts: 1038
Joined: Sun Feb 25, 2018 2:30 am
Location: UK
Contact:

Re: Boids: natural flight movement and behavior

Post by eharper256 »

neoworm wrote:
Enjay wrote:[edit3]Doh! Googling "crow sprites" turned up a link to this very forum and some nice sprites by Neoworm.
Image[/edit3]
I was thinking about trying the boids script with this. Let me know how it works out.
I've already used these sprites as a placeholder for my Raven Familiar (basically using these and making them a bit more buff) and they work perfectly fine (just swooping around and firing wind blades right now, but I might add some more logic to it soon). Should be in the next Walpurgis version for the Druid.
User avatar
4page
Posts: 120
Joined: Tue Aug 06, 2019 5:08 pm
Location: American Pacific Northwest

Re: Boids: natural flight movement and behavior

Post by 4page »

Enjay, you still need the Tick override for the NJBoid actors. Otherwise they're not calling the boidflight function.
User avatar
Enjay
 
 
Posts: 26534
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland
Contact:

Re: Boids: natural flight movement and behavior

Post by Enjay »

Aha! Thank you. That's the kind of stuff that catches me out because I'm not familiar enough with ZScript to realise issues like that. All these various overrides etc are still something of a dark art to me but I'm getting there (slowly).

Anyway, adding that back in does now indeed allow the game to start without warnings and my various boid flocks to stick together.



I don't suppose a screenshot provides much information but each of the shotgun sergeant sprites above mark the location of a boid spawner and you can see that each one has its own flock flying near it (there are different numbers of boids per flock because the spawners have their arguments set differently).

I have also added a bit of randomness to the boids so that they don't all flap their wings at the same time. With my original code, they were all syncronised - which looked odd (especially in large numbers).


As an aside, the more random flight pattern that I was getting earlier (where the boids didn't flock together, but merely flew near their spawner independently from each other) might also be useful as a decoration. So I might use that ability too because the flight is pretty natural looking. It could work for non-flocking birds, bats, insects...

But, anyway, with the help provided, I got there and now have something that does pretty much what I set out to achieve. All I have to do now is a bit of tweaking. Thanks very much to those who helped and, of course, for the original library.


To answer neoworm's question - the boids are flying very nicely as a flock of decorative bird actors, so I'd say its working out pretty well. I added an additional frame with the wings outstretched and I am using that as a "gliding" frame (although my edit is not really up to the standard of the originals). I set the actor to have a low(ish) chance of gliding for a few tics every time it goes through its flight wingbeat. That helped to randomise things.

The animation from the original sprite set is good, but I feel that one more frame could be useful. The first two frames look very similar, then the wings go to the fully down position in frame 3 and finally to a recovery position in frame 4. I feel that either the second frame having the wings a bit lower, or there being another frame between 2 and 3 would help a bit. Using the existing frames, however, I got a pretty reasonable looking flap by using the sequence:

Code: Select all

BIRB AB 2;
BIRB DCD 3;
I'm a bit busy with work stuff today and for the rest of the week but if I get something finalised, I can post what I have as an additional working example.
User avatar
Enjay
 
 
Posts: 26534
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland
Contact:

Re: Boids: natural flight movement and behavior

Post by Enjay »

Meh! Might as well post this. It will no doubt still need some polish but it seems to be working.

Load the attached file on top of BoidLib.Pk3 from the first post.

[edit]File removed - see post on next page.[/edit]

The spawners are set up to spawn quite a few boids (and the map is a big open area, though not at all detailed).



It works fine on my system, but it may have a performance hit on slower machines. If this is the case on your machine, just skip to another map and type the following at the console to spawn a single item that will spawn one flock of eight boids.

summon NJ_FlockSpawner
(Fun fact, you can copy text from any program and paste it into the GZDoom console - on windows at least. No idea about Linux/Macs.)


The switch in the middle of the map allows you to toggle the spawners between active and inactive. They initially spawn as active (and thereby spawn a flock of boids) and deactivating them removes any boids spawned by the spawner that has been deactivated (in this map, the script deactivates them all). Hitting the switch once removes the boids. Hitting it again spawns new ones.

I have made no attempt to tweak the spawers so that setting their arguments can affect the tightness/speed/whatever of the flock. However, setting arg0 will determine how many boids spawn. If the arg is left blank, it defaults to spawning 8 boids.
User avatar
eharper256
Posts: 1038
Joined: Sun Feb 25, 2018 2:30 am
Location: UK
Contact:

Re: Boids: natural flight movement and behavior

Post by eharper256 »


Here's Turul the Falcon in action, using this (will be in the 0.96 version of Walpurgis!).
User avatar
4page
Posts: 120
Joined: Tue Aug 06, 2019 5:08 pm
Location: American Pacific Northwest

Re: Boids: natural flight movement and behavior

Post by 4page »

Awesome! Love seeing the things people have done already!
User avatar
Enjay
 
 
Posts: 26534
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland
Contact:

Re: Boids: natural flight movement and behavior

Post by Enjay »

eharper256 wrote:Here's Turul the Falcon in action, using this
Looks fantastic.


Can I ask, does DistanceFromMaster respect the vertical distance? The reason I'm asking is that in a tall sector, the boids seem to swoop from very high to very low (and vice versa) quite a lot. So I am looking for a way to reduce this behaviour (via DistanceFromMaster or by some other parameter).

With my flock spawner ideally I would like to, for example, be able to place it in the air quite high up near the top of some cliffs or something and have the boids circling around the spawner at high altitude rather than diving right the way down and back up again all the time.
User avatar
4page
Posts: 120
Joined: Tue Aug 06, 2019 5:08 pm
Location: American Pacific Northwest

Re: Boids: natural flight movement and behavior

Post by 4page »

It's supposed to, but it doesn't seem to be super effective at it. I'll look into why it seems to prefer to maintain its vertical momentum so much, but that's also what the HorizonNormalizer parameter is for. Try setting that to about 40 and it should work a bit better.
Post Reply

Return to “Script Library”