Last active
September 3, 2019 09:05
-
-
Save amatiasq/2af7e9b20ca6930e0dcf92e0ea246ab2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const a = new Life(); | |
| a.pos = new Vector(10, 10); | |
| a.setParameter(Parameter.ENERGY, 100); | |
| a.setParameter(Parameter.WEIGHT, 1); | |
| a.setParameter(Parameter.FOOD, x => x.hasParameter(Parameter.IS_PLANT)); | |
| a.addSense(new Sight({ radius: 10, angle: 270, precision: 1 })) | |
| a.addSense(new Hearing({ radius: 1, angle: 360, }) | |
| a.addBehaviour(new FlockingBehaviour(), { intensity: 0.5 }); | |
| a.addBehaviour(new PredatorBehaviour(), { intensity: 1 }); | |
| a.addBehaviour(new PeopleBehaviour(), { intensity: 0.2 }); | |
| a.tick(world); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type ConstructorOf<T> = new() => T; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface IBehaviour { | |
| tick(event: TickEvent); | |
| reset(); // kind of Tick destructor, to remove any cache for the tick | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface ISense { | |
| sense(at: IVector, world: IWorld): Life[]; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface IVector { | |
| readonly x: number; | |
| readonly y: number; | |
| multiply(value: number): IVector; | |
| merge(other: IVector): IVector; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface IWorld { | |
| getEntitiesAt(center: IVector, radius: number): Life[]; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Life { | |
| pos: IVector; | |
| acceleration: IVector; | |
| private readonly parameters = new Map<Parameter, any>(); | |
| private readonly senses: ISense[] = []; | |
| private readonly behaviours = new Map(); | |
| setParameter(param: Parameter, value: any) { | |
| this.parameters.set(param, value); | |
| } | |
| getParameter<T>(param: Parameter) { | |
| return this.parameters.get(param) as T; | |
| } | |
| addSense(sense: ISense) { | |
| this.senses.push(sense); | |
| } | |
| getSenses() { | |
| return this.senses; | |
| } | |
| addBehaviour(behaviour: IBehaviour, { intensity }: { intensity: number } = { intensity: 1 }) { | |
| this.behaviours.set(behaviour.constructor, { | |
| implementation: behaviour, | |
| intensity | |
| }); | |
| } | |
| getBehaviour<T>(Class: ConstructorOf<T>): T { | |
| const entry = this.behaviours.get(Class); | |
| return entry && entry.implementation; | |
| } | |
| shove(force) { | |
| this.acceleration = this.acceleration.merge(force); | |
| } | |
| tick(world: IWorld) { | |
| // Can be cached | |
| const event = new TickEvent(this, world); | |
| this.behaviours.forEach(({ implementation, intensity }) => { | |
| event.intensity = intensity; | |
| implementation.tick(event); | |
| }); | |
| const force = event.getWillForce(); | |
| if (force) { | |
| this.shove(force); | |
| } | |
| } | |
| reset() { | |
| this.behaviours.forEach(({ implementation }) => implementation.reset()); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| enum Parameter { | |
| ENERGY, | |
| WEIGHT, | |
| FOOD, | |
| IS_PLANT, | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class FlockingBehaviour implements IBehaviour { | |
| private _isFlocking = false; | |
| get isFlocking() { | |
| return this._isFlocking; | |
| } | |
| tick(event: TickEvent) { | |
| const neighbors = event.useSenses(); | |
| const flockings = neighbors | |
| .map(x => x.getBehaviour(FlockingBehaviour)) | |
| .filter(Boolean); | |
| if (flockings.some(x => x.isFlocking)) { | |
| this._isFlocking = true; | |
| ... | |
| event.setWill(flockingDirection); | |
| } | |
| } | |
| reset() { | |
| this._isFlocking = false; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class TickEvent { | |
| intensity = 1; | |
| private readonly pushes: IVector[] = []; | |
| constructor( | |
| private readonly self: Life, | |
| private readonly world: IWorld | |
| ) {} | |
| useSenses(): Life[] { | |
| const senses = this.self.getSenses(); | |
| return senses.flatMap(x => x.sense(this.self.pos, this.world)); | |
| } | |
| setWill(force: IVector) { | |
| this.pushes.push(force.multiply(this.intensity)); | |
| } | |
| getWillForce() { | |
| return this.pushes.reduce((a, b) => a.merge(b)); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment