diff --git a/app/ecs-components/plant.js b/app/ecs-components/plant.js new file mode 100644 index 0000000..dd8fe93 --- /dev/null +++ b/app/ecs-components/plant.js @@ -0,0 +1,58 @@ +import Component from '@/ecs/component.js'; +import Script from '@/util/script.js'; + +export default class Plant extends Component { + instanceFromSchema() { + const {ecs} = this; + const Instance = super.instanceFromSchema(); + return class PlantInstance extends Instance { + mayGrow() { + return this.mayGrowScriptInstance.evaluateSync(); + } + grow() { + const {Ticking} = ecs.get(this.entity); + Ticking.addTickingPromise(this.growScriptInstance.tickingPromise()); + } + }; + } + async load(instance) { + // heavy handed... + if ('undefined' !== typeof window) { + return; + } + const {readAsset} = this.ecs; + await readAsset(instance.growScript) + .then(async (code) => { + if (code.byteLength > 0) { + const context = { + ecs: this.ecs, + plant: instance, + }; + instance.growScriptInstance = await Script.fromCode((new TextDecoder()).decode(code), context); + } + }); + + await readAsset(instance.mayGrowScript) + .then(async (code) => { + if (code.byteLength > 0) { + const context = { + ecs: this.ecs, + plant: instance, + }; + instance.mayGrowScriptInstance = await Script.fromCode((new TextDecoder()).decode(code), context); + } + }); + } + // heavy handed... + markChange() {} + static properties = { + growScript: {type: 'string'}, + growth: {type: 'uint16'}, + mayGrowScript: {type: 'string'}, + stage: {type: 'uint8'}, + stages: { + type: 'array', + subtype: {type: 'uint16'}, + }, + }; +} diff --git a/app/ecs-systems/plant-growth.js b/app/ecs-systems/plant-growth.js new file mode 100644 index 0000000..868b3a4 --- /dev/null +++ b/app/ecs-systems/plant-growth.js @@ -0,0 +1,27 @@ +import {System} from '@/ecs/index.js'; + +export default class PlantGrowth extends System { + + static queries() { + return { + default: ['Plant'], + }; + } + + tick(elapsed) { + for (const {Plant} of this.select('default')) { + if (65535 === Plant.growth || !Plant.mayGrow()) { + continue; + } + const stage = Math.floor(Plant.stage); + Plant.growth = Math.min( + Plant.growth + (((Math.random() + 0.5) * elapsed) / Plant.stages[stage]) * 65535, + 65535, + ); + if (65535 === Plant.growth) { + Plant.grow(); + } + } + } + +} diff --git a/app/engine.js b/app/engine.js index 5c86e63..66e6324 100644 --- a/app/engine.js +++ b/app/engine.js @@ -118,11 +118,39 @@ export default class Engine { ], }, }); + const plant = { + Plant: { + growScript: '/assets/tomato-plant/grow.js', + mayGrowScript: '/assets/tomato-plant/may-grow.js', + stages: [300, 300, 300, 300, 300], + }, + Sprite: { + anchor: {x: 0.5, y: 0.75}, + animation: 'stage/0', + frame: 0, + frames: 1, + source: '/assets/tomato-plant/tomato-plant.json', + speed: 0, + }, + Ticking: {}, + VisibleAabb: {}, + }; + const promises = []; + for (let y = 0; y < 10; ++y) { + for (let x = 0; x < 10; ++x) { + promises.push(ecs.create({ + ...plant, + Position: {x: 8 + x * 16, y: 8 + y * 16}, + })); + } + } + await Promise.all(promises); const defaultSystems = [ 'ResetForces', 'ApplyControlMovement', 'ApplyForces', 'ClampPositions', + 'PlantGrowth', 'FollowCamera', 'CalculateAabbs', 'UpdateSpatialHash', diff --git a/public/assets/tomato-plant/grow.js b/public/assets/tomato-plant/grow.js new file mode 100644 index 0000000..f6eea88 --- /dev/null +++ b/public/assets/tomato-plant/grow.js @@ -0,0 +1,13 @@ +const {Sprite} = ecs.get(plant.entity); + +if (plant.stage < 3) { + plant.stage += 1 +} +if (4 === plant.stage) { + plant.stage = 3 +} +if (3 !== plant.stage) { + plant.growth = 0 +} + +Sprite.animation = ['stage', plant.stage].join('/') diff --git a/public/assets/tomato-plant/may-grow.js b/public/assets/tomato-plant/may-grow.js new file mode 100644 index 0000000..dc36c3b --- /dev/null +++ b/public/assets/tomato-plant/may-grow.js @@ -0,0 +1 @@ +3 !== plant.stage diff --git a/public/assets/tomato-plant/tomato-plant.json b/public/assets/tomato-plant/tomato-plant.json new file mode 100644 index 0000000..13e165f --- /dev/null +++ b/public/assets/tomato-plant/tomato-plant.json @@ -0,0 +1 @@ +{"animations":{"stage/0":["tomato-plant/tomato-plant/0"],"stage/1":["tomato-plant/tomato-plant/1"],"stage/2":["tomato-plant/tomato-plant/2"],"stage/3":["tomato-plant/tomato-plant/3"],"stage/4":["tomato-plant/tomato-plant/4"]},"frames":{"tomato-plant/tomato-plant/0":{"frame":{"x":0,"y":0,"w":16,"h":32},"spriteSourceSize":{"x":0,"y":0,"w":16,"h":32},"sourceSize":{"w":16,"h":32}},"tomato-plant/tomato-plant/1":{"frame":{"x":16,"y":0,"w":16,"h":32},"spriteSourceSize":{"x":0,"y":0,"w":16,"h":32},"sourceSize":{"w":16,"h":32}},"tomato-plant/tomato-plant/2":{"frame":{"x":32,"y":0,"w":16,"h":32},"spriteSourceSize":{"x":0,"y":0,"w":16,"h":32},"sourceSize":{"w":16,"h":32}},"tomato-plant/tomato-plant/3":{"frame":{"x":48,"y":0,"w":16,"h":32},"spriteSourceSize":{"x":0,"y":0,"w":16,"h":32},"sourceSize":{"w":16,"h":32}},"tomato-plant/tomato-plant/4":{"frame":{"x":64,"y":0,"w":16,"h":32},"spriteSourceSize":{"x":0,"y":0,"w":16,"h":32},"sourceSize":{"w":16,"h":32}}},"meta":{"format":"RGBA8888","image":"./tomato-plant.png","scale":1,"size":{"w":80,"h":32}}} \ No newline at end of file diff --git a/public/assets/tomato-plant/tomato-plant.png b/public/assets/tomato-plant/tomato-plant.png new file mode 100644 index 0000000..de7985b Binary files /dev/null and b/public/assets/tomato-plant/tomato-plant.png differ