Flocking Example
Closed this issue ยท 12 comments
Describe the example
An example for using the flocking behavior
Checklist
- I've followed all of the best practices.
- My game has a proper name in the game properties.
- My game package name behind with
com.example.
. - My game has all events unfolded.
- I've added myself as the author in the game properties.
- I've included a file called "README.md" with a description in proper English, explaining what this example is doing.
- I confirm that this game and all of its resources can be integrated to this GitHub repository, distributed and MIT licensed.
- I've cleaned unused resources.
Game folder
This is more of an extension review:
- Two number inputs are prefered for the ObjectToSpawn parameter. This way you can use the expressions. Like Fish.X() and Fish.Y().
- In spawnBoid function you hide the spawner, the creator may wish to see the spawn in their games. I suggest removing this action, this has to be led by the creator in their game.
- In onCreated function, you create a
boids
array in the object. if one day in the engine we need to useboids
you will redefine this scope.
Instead, you can create a private scope with the name of the extension:object._extensionFlocking.boids
- In spawnBoid function: you define random function, we have one in gdjs (GDevelop JavaScript api): https://docs.gdevelop.io/GDJS%20Runtime%20Documentation/modules/gdjs.html#random
gdjs
is in the global scope so you can use it everywhere in a JS Event. - Same for normalizing and a few other methods, see in gdjs. (this will reduce the size of your extension)
I'm skipping the Boid class, because of the complex math, @D8H I think this might interest you.
-
Boid.prototype.borders
no need for this, we have an extension for it: Screen Wrap:
https://wiki.gdevelop.io/gdevelop5/extensions/screen-wrap/reference - Boids is more know than Flocking, right? If yes, I think we should rename the extension Boids ๐
And in the short description you can mention it is a "Flocking swarm behaviour" - Please fill the description, version number 1.0.0, and author name if you have one ;)
This is more of an extension review:
- Two number inputs are prefered for the ObjectToSpawn parameter. This way you can use the expressions. Like Fish.X() and Fish.Y().
- In spawnBoid function you hide the spawner, the creator may wish to see the spawn in their games. I suggest removing this action, this has to be led by the creator in their game.
- In onCreated function, you create a
boids
array in the object. if one day in the engine we need to useboids
you will redefine this scope.
Instead, you can create a private scope with the name of the extension:object._extensionFlocking.boids
- In spawnBoid function: you define random function, we have one in gdjs (GDevelop JavaScript api): https://docs.gdevelop.io/GDJS%20Runtime%20Documentation/modules/gdjs.html#random
gdjs
is in the global scope so you can use it everywhere in a JS Event.- Boids is more know than Flocking, right? If yes, I think we should rename the extension Boids ๐
And in the short description you can mention it is a "Flocking swarm behaviour"- Please fill the description, version number 1.0.0, and author name if you have one ;)
- Same for normalizing and a few other methods, see in gdjs. (this will reduce the size of your extension)
I'm skipping the Boid class, because of the complex math, @D8H I think this might interest you.Boid.prototype.borders
no need for this, we have an extension for it: Screen Wrap:
https://wiki.gdevelop.io/gdevelop5/extensions/screen-wrap/reference
I'm not sure how to do that, added dependency for it tho, need help on this
Game Folder
It's impressive, very cool extension!
- The lifecycle "doStepPreEvents" can be used instead of "runBoids". It's called automatically every frame.
- The behavior should be attached to the fish directly. If you need to know other fishes, you can add them in an Array (attached to the scene) each time onCreate is called and remove them at onDestroy. Take a look at the community extension called "Recolorizer", it does something similar.
To go further:
- The some behaviors of the engine use a R-tree. I think it could greatly improve efficiently of the behavior. You can almost copy paste the Manager class from:
https://github.com/4ian/GDevelop/blob/master/Extensions/PathfindingBehavior/pathfindingobstacleruntimebehavior.ts
Boid.prototype.borders
no need for this, we have an extension for it: Screen Wrap:
https://wiki.gdevelop.io/gdevelop5/extensions/screen-wrap/referenceI'm not sure how to do that, added dependency for it tho, need help on this
I see you used it in your latest zip file ๐
I think it even could be improved by two different mechanics.
1 ) Like currently, teleport to the opposite side.
2 ) Limit the boids in the camera view by making them bounce on the border by changing the boids direction.
In the behavior properties, you can achieve that with a True/False parameter.
For a first extension, you made a solid one!
I think it even could be improved by two different mechanics. 1 ) Like currently, teleport to the opposite side. 2 ) Limit the boids in the camera view by making them bounce on the border by changing the boids direction. In the behavior properties, you can achieve that with a True/False parameter.
I think that the boid behavior should not care about warping things. It should be done by users with events outside of the extension.
It's impressive, very cool extension!
- The lifecycle "doStepPreEvents" can be used instead of "runBoids". It's called automatically every frame.
Moved the run function here
- The behavior should be attached to the fish directly. If you need to know other fishes, you can add them in an Array (attached to the scene) each time onCreate is called and remove them at onDestroy. Take a look at the community extension called "Recolorizer", it does something similar.
Added this one too
To go further:
- The some behaviors of the engine use a R-tree. I think it could greatly improve efficiently of the behavior. You can almost copy paste the Manager class from:
https://github.com/4ian/GDevelop/blob/master/Extensions/PathfindingBehavior/pathfindingobstacleruntimebehavior.ts
Hmm typescript? I used the Recolorizer shared defined classes
Boid.prototype.borders
no need for this, we have an extension for it: Screen Wrap:
https://wiki.gdevelop.io/gdevelop5/extensions/screen-wrap/reference
Fixed this one, other behaviors can modify the boids.
I see you used it in your latest zip file ๐
I think it even could be improved by two different mechanics.
1 ) Like currently, teleport to the opposite side.
2 ) Limit the boids in the camera view by making them bounce on the border by changing the boids direction. In the behavior properties, you can achieve that with a True/False parameter.
Oh no more features, I need to know the border limits where the boids can follow
For a first extension, you made a solid one!
Updated Game Folder
Accessing the behavior
There is no garentee this will work. If a user adds the behavior 2 times, it creates one named "BoidsBehaviour" and another one "BoidsBehaviour2" then the user can remove "BoidsBehaviour".
Boid.prototype.getBehavior = function() {
return this.gObject.getBehavior("BoidsBehaviour");
}
Methods from Boid
can be added to the behavior prototype directly. The prototype can be retried like this within onCreate:
const object = objects[0];
const behaviorName = eventsFunctionContext.getBehaviorName("Behavior");
const behavior = object.getBehavior(behaviorName);
const prototype = Object.getPrototypeOf(behavior);
This way this
is the behavior instance and this.owner
the object.
Typing
The code editor support documentation with typing. It helps the autocompletion.
For instance, this comment...
// Separation
// Method checks for nearby boids and steers away
Boid.prototype.separate = function(boids) {
... can be replaced by something like this:
/**
* Separation: checks for nearby boids and steers away.
* @param boids {Boid[]}
* @return {Vector} steer force
*/
Boid.prototype.separate = function(boids) {
Vector operations
I'm not sure that the operation methods of the Vector
class make the code easier to read. I guess that the goal is to avoid to repeat the formula for x and y but the operators doesn't stand out which make it difficult to read in my opinion.
Accessing the behavior
There is no garentee this will work. If a user adds the behavior 2 times, it creates one named "BoidsBehaviour" and another one "BoidsBehaviour2" then the user can remove "BoidsBehaviour".
...
Methods fromBoid
can be added to the behavior prototype directly. The prototype can be retried like this within onCreate:
...
This waythis
is the behavior instance andthis.owner
the object.
Updated the code
Typing
The code editor support documentation with typing. It helps the autocompletion.
...
Added doc blocks
Vector operations
I'm not sure that the operation methods of the
Vector
class make the code easier to read. I guess that the goal is to avoid to repeat the formula for x and y but the operators doesn't stand out which make it difficult to read in my opinion.
Can't remove this one, I need the vectors to calculate the average speed and direction of the boids
Updated Game Folder
Lgtm, this extension is nice and well made!
@D8H I let you the choice to merge or let me know.
To me, it's a go ๐
I did some changes:
https://www.dropbox.com/s/e5gk9zfgetatxt0/fish-school.zip?dl=1
New features
- Add new actions ("avoid" and "move to") to allow interactions with the boids
- Add properties to tweak the direction decision
Bug fixes
- Remove the hard-coded dimension of the fish from the calculus
- Remove the screen warp requirement property
- Fix the cohesion calculus (
return this.seek(sum);
like it was done in the source material) - Sum the intended direction instead of summing the steer forces (this allows to actually respect the speed properties and better parametriarization)
- Use
timeDelta
to evaluate the movement - Handle behavior disabling
Efficiency
- Use a R-Tree
- Remove any allocation repeated every frame
- Remove useless divisions before normalization
- Use
SqDistance
to avoid square root calculus
Best practices
- Mark it as experimental
- Rename some properties
- Rename expressions to remove the "Get" prefix
- Rename action to replace "Change" by "Set"
- Add dot in description
- Reword name and descriptions
- Reorganize groups
- Move the boids manager from
gdjs
toruntimScene
Nitpicks
- Change the background color to be easier on the eyes
- Remove the batch create action
- Change the
getPosition
to usethis
instead of a parameter - Define classes using a standard way
Just checked it out, looks very nice!
you can feed the fish :)
I went ahead and submitted the extension:
I added a scene to the example to configure the behavior properties with sliders: