diff --git a/app/ecs-components/water.js b/app/ecs-components/water.js new file mode 100644 index 0000000..d289048 --- /dev/null +++ b/app/ecs-components/water.js @@ -0,0 +1,10 @@ +import Component from '@/ecs/component.js'; + +export default class Water extends Component { + static properties = { + water: { + type: 'map', + value: {type: 'uint8'}, + }, + }; +} diff --git a/app/ecs-systems/water.js b/app/ecs-systems/water.js new file mode 100644 index 0000000..20ba83e --- /dev/null +++ b/app/ecs-systems/water.js @@ -0,0 +1,13 @@ +import {System} from '@/ecs/index.js'; + +export default class Water extends System { + + tick(elapsed) { + const {Water} = this.ecs.get(1); + for (const tile in Water.water) { + Water.water[tile] = Math.max(0, Water.water[tile] - elapsed); + } + Water.water = {...Water.water}; + } + +} diff --git a/app/engine.js b/app/engine.js index debe448..980af9e 100644 --- a/app/engine.js +++ b/app/engine.js @@ -128,6 +128,7 @@ export default class Engine { } ], }, + Water: {water: {}}, }); const defaultSystems = [ 'ResetForces', @@ -142,6 +143,7 @@ export default class Engine { 'SpriteDirection', 'RunAnimations', 'RunTickingPromises', + 'Water', ]; defaultSystems.forEach((defaultSystem) => { const System = ecs.system(defaultSystem); @@ -162,9 +164,13 @@ export default class Engine { Forces: {}, Inventory: { slots: { - 1: { - qty: 10, - source: '/assets/potion/potion.json', + // 1: { + // qty: 10, + // source: '/assets/potion/potion.json', + // }, + 2: { + qty: 1, + source: '/assets/watering-can/watering-can.json', }, 3: { qty: 1, diff --git a/app/react-components/ecs.jsx b/app/react-components/ecs.jsx index 789d5e8..24a28df 100644 --- a/app/react-components/ecs.jsx +++ b/app/react-components/ecs.jsx @@ -9,6 +9,7 @@ import Entities from './entities.jsx'; import TargetingGhost from './targeting-ghost.jsx'; import TargetingGrid from './targeting-grid.jsx'; import TileLayer from './tile-layer.jsx'; +import Water from './water.jsx'; export default function EcsComponent() { const [ecs] = useEcs(); @@ -40,7 +41,7 @@ export default function EcsComponent() { const {Direction, Position, Wielder} = entity; const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction) const {Camera} = entity; - const {TileLayers: {layers: [layer]}} = ecs.get(1); + const {TileLayers: {layers: [layer]}, Water: {water}} = ecs.get(1); const [cx, cy] = [ Math.round(Camera.x - RESOLUTION.x / 2), Math.round(Camera.y - RESOLUTION.y / 2), @@ -51,6 +52,7 @@ export default function EcsComponent() { y={-cy} > + {projected && ( { + g.clear(); + g.beginFill(0x000000); + g.drawRect( + 0, + 0, + width, + height + ); + }, [height, width]); + return +}); + +export default function Water({tileLayer, water}) { + const [mounted, setMounted] = useState(false); + useEffect(() => { + setMounted(true); + }, []); + const waterTile = useRef(); + const waterTiles = []; + if (mounted) { + for (const tileIndex in water) { + const tileIndexNumber = parseInt(tileIndex); + const tx = tileIndexNumber % tileLayer.area.x; + const ty = (tileIndexNumber - tx) / tileLayer.area.x; + waterTiles.push( + + ); + } + } + return ( + <> + + {waterTiles} + + ); +} diff --git a/public/assets/tomato-plant/may-grow.js b/public/assets/tomato-plant/may-grow.js index 3295946..33bdcee 100644 --- a/public/assets/tomato-plant/may-grow.js +++ b/public/assets/tomato-plant/may-grow.js @@ -1 +1,20 @@ -return 3 !== plant.stage +if (3 === plant.stage) { + return false +} + +const {TileLayers, Water} = ecs.get(1); +const layer = TileLayers.layer(0) +const {Position} = ecs.get(plant.entity); +const x = (Position.x - layer.tileSize.x * 0.5) / layer.tileSize.x +const y = (Position.y - layer.tileSize.y * 0.5) / layer.tileSize.y +const tileIndex = layer.area.x * y + x +if (!Water.water[tileIndex]) { + return false +} +if (Water.water[tileIndex] < 32) { + return false +} +if (Water.water[tileIndex] > 224) { + return false +} +return true diff --git a/public/assets/watering-can/icon.png b/public/assets/watering-can/icon.png new file mode 100644 index 0000000..879b705 Binary files /dev/null and b/public/assets/watering-can/icon.png differ diff --git a/public/assets/watering-can/projection-check.js b/public/assets/watering-can/projection-check.js new file mode 100644 index 0000000..69da2b4 --- /dev/null +++ b/public/assets/watering-can/projection-check.js @@ -0,0 +1,10 @@ +const filtered = [] + +for (let i = 0; i < projected.length; ++i) { + const tile = layer.tile(projected[i]) + if ([7].includes(tile)) { + filtered.push(projected[i]) + } +} + +return filtered diff --git a/public/assets/watering-can/start.js b/public/assets/watering-can/start.js new file mode 100644 index 0000000..e285eb0 --- /dev/null +++ b/public/assets/watering-can/start.js @@ -0,0 +1,120 @@ +const {Direction, Position, Wielder} = wielder +const projected = Wielder.activeItem()?.project(Position.tile, Direction.direction) +if (projected?.length > 0) { + + const {Controlled, Emitter, Sound, Sprite} = wielder + const {TileLayers, Water} = ecs.get(1) + const layer = TileLayers.layer(0) + + Controlled.locked = 1 + const [, direction] = Sprite.animation.split(':') + Sprite.animation = ['idle', direction].join(':'); + + const waterParticles = { + behaviors: [ + { + type: 'moveAcceleration', + config: { + accel: { + x: 0, + y: 1500, + }, + minStart: 0, + maxStart: 0, + rotate: false, + } + }, + { + type: 'moveSpeed', + config: { + speed: { + list: [ + { + time: 0, + value: 30 + }, + { + time: 1, + value: 0 + } + ] + } + } + }, + { + type: 'scale', + config: { + scale: { + list: [ + { + value: 0.25, + time: 0, + }, + { + value: 0.125, + time: 1, + }, + ] + } + } + }, + { + type: 'textureSingle', + config: { + texture: 'tileset/38', + } + }, + ], + lifetime: { + min: 0.25, + max: 0.25, + }, + frequency: 0.01, + emitterLifetime: 0.25, + pos: { + x: 0, + y: 0 + }, + rotation: 0, + }; + + Sound.play('/assets/watering-can/water.wav'); + for (let i = 0; i < 2; ++i) { + for (let i = 0; i < projected.length; ++i) { + Emitter.emit({ + ...waterParticles, + behaviors: [ + ...waterParticles.behaviors, + { + type: 'spawnShape', + config: { + type: 'rect', + data: { + x: projected[i].x * layer.tileSize.x, + y: projected[i].y * layer.tileSize.y - (layer.tileSize.y * 0.5), + w: layer.tileSize.x, + h: layer.tileSize.y, + } + } + } + ] + }) + } + await wait(0.25); + } + + for (let i = 0; i < projected.length; ++i) { + const tileIndex = layer.area.x * projected[i].y + projected[i].x + let w; + if (Water.water[tileIndex]) { + w = Water.water[tileIndex] + } + else { + w = 0 + } + Water.water[tileIndex] = Math.min(255, 64 + w); + } + + Controlled.locked = 0; + +} diff --git a/public/assets/watering-can/water.wav b/public/assets/watering-can/water.wav new file mode 100644 index 0000000..a774d4c Binary files /dev/null and b/public/assets/watering-can/water.wav differ diff --git a/public/assets/watering-can/watering-can.json b/public/assets/watering-can/watering-can.json new file mode 100644 index 0000000..b6c13ea --- /dev/null +++ b/public/assets/watering-can/watering-can.json @@ -0,0 +1,11 @@ +{ + "icon": "/assets/watering-can/icon.png", + "projectionCheck": "/assets/watering-can/projection-check.js", + "projection": { + "distance": [1, 0], + "grid": [ + [1] + ] + }, + "start": "/assets/watering-can/start.js" +}