diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7230965 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +dist +.git +.DS_Store +npm-debug.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a49d5ed --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM node:22-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +FROM nginx:1.27-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html +EXPOSE 80 +HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=5 \ + CMD wget -q -O /dev/null http://127.0.0.1/health || exit 1 diff --git a/README.md b/README.md index 9b23ce4..84804ec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,46 @@ -# squirrel-forest-deploy +# Squirrel Forest -Public deployment mirror for the Squirrel Forest Phaser prototype. \ No newline at end of file +A small 2D adventure-platformer prototype about a squirrel exploring a living woodland full of unusual flora, fauna and mushrooms. + +## Prototype loop + +- Explore a continuous side-scrolling forest. +- Run and jump across roots and branches. +- Collect acorns while searching for five unusual mushrooms. +- Pass through named woodland areas with ferns, flowers, frogs and butterflies. +- Find all five forest caps to awaken the Moonlit Grove. +- Follow the fireflies to complete the prototype trail. + +Everything in the first prototype uses Phaser-generated textures, so there are no external art dependencies yet. + +## Controls + +- **Move:** A/D or Left/Right +- **Jump:** W, Up or Space +- **Touch:** on-screen left/right/jump controls + +## Run + +```bash +npm install +npm run dev +``` + +Production build: + +```bash +npm run build +``` + +## Direction + +The intended feel is a cosy exploratory woodland adventure: dense layers of forest, lots of discoverable species, small traversal secrets and environmental storytelling rather than combat-first progression. + +Good next slices: + +1. replace generated graphics with a hand-painted squirrel animation set; +2. add climbable trunks and branch-to-branch movement; +3. introduce a field-guide journal for discovered plants, fungi and animals; +4. split the forest into richer biome pockets such as birch grove, damp hollow, old oak canopy and moonlit marsh; +5. add tiny NPC animals and lightweight quests; +6. add ambient audio, leaf particles, weather and a day/night cycle. diff --git a/index.html b/index.html new file mode 100644 index 0000000..cedc6e4 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Squirrel Forest + + +
+ + + diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..c52884b --- /dev/null +++ b/nginx.conf @@ -0,0 +1,16 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + location = /health { + access_log off; + add_header Content-Type text/plain; + return 200 'ok'; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e99c624 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "squirrel-forest", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "vite build", + "preview": "vite preview --host 0.0.0.0" + }, + "dependencies": { + "phaser": "^3.90.0" + }, + "devDependencies": { + "vite": "^7.1.7" + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..5abfab4 --- /dev/null +++ b/src/main.js @@ -0,0 +1,608 @@ +import Phaser from 'phaser'; +import './style.css'; + +const WORLD_WIDTH = 5600; +const WORLD_HEIGHT = 720; +const GROUND_Y = 628; + +class ForestScene extends Phaser.Scene { + constructor() { + super('forest'); + this.acorns = 0; + this.mushrooms = 0; + this.totalMushrooms = 5; + this.touch = { left: false, right: false, jump: false }; + } + + create() { + this.physics.world.setBounds(0, 0, WORLD_WIDTH, WORLD_HEIGHT); + this.cameras.main.setBounds(0, 0, WORLD_WIDTH, WORLD_HEIGHT); + this.cameras.main.setBackgroundColor('#8fc7a2'); + + this.createTextures(); + this.createBackdrop(); + this.createWorld(); + this.createPlayer(); + this.createCollectibles(); + this.createFauna(); + this.createHud(); + this.createControls(); + + this.cameras.main.startFollow(this.player, true, 0.08, 0.08, 0, 70); + this.cameras.main.setDeadzone(180, 110); + this.cameras.main.fadeIn(700, 16, 37, 29); + + this.physics.add.collider(this.player, this.platforms); + this.physics.add.collider(this.acornGroup, this.platforms); + this.physics.add.collider(this.mushroomGroup, this.platforms); + + this.physics.add.overlap(this.player, this.acornGroup, (_, acorn) => { + acorn.disableBody(true, true); + this.acorns += 1; + this.acornText.setText(`Acorns ${this.acorns}`); + this.tweens.add({ + targets: this.acornText, + scale: 1.15, + duration: 90, + yoyo: true + }); + }); + + this.physics.add.overlap(this.player, this.mushroomGroup, (_, mushroom) => { + mushroom.disableBody(true, true); + this.mushrooms += 1; + this.mushroomText.setText(`Forest caps ${this.mushrooms} / ${this.totalMushrooms}`); + this.showDiscovery(mushroom.getData('name')); + + if (this.mushrooms === this.totalMushrooms) { + this.objectiveText.setText('The moonlit grove is awake — follow the fireflies east'); + this.revealGrove(); + } + }); + + this.physics.add.overlap(this.player, this.groveTrigger, () => { + if (this.mushrooms < this.totalMushrooms || this.finished) return; + this.finished = true; + this.player.setVelocityX(0); + this.player.setTint(0xfff2bd); + this.showEnding(); + }); + } + + createTextures() { + const g = this.make.graphics({ add: false }); + + g.clear(); + g.fillStyle(0x6e482b, 1); + g.fillEllipse(24, 30, 35, 24); + g.fillStyle(0x9c6840, 1); + g.fillEllipse(30, 25, 28, 20); + g.fillStyle(0x6e482b, 1); + g.fillCircle(42, 20, 10); + g.fillTriangle(39, 13, 43, 3, 47, 14); + g.fillStyle(0xf3d5a0, 1); + g.fillCircle(46, 21, 3); + g.fillStyle(0x2c2018, 1); + g.fillCircle(48, 19, 1.5); + g.fillStyle(0x8c5b35, 1); + g.fillEllipse(9, 25, 22, 38); + g.lineStyle(5, 0x8c5b35, 1); + g.beginPath(); + g.arc(7, 20, 16, Math.PI * 0.6, Math.PI * 1.65); + g.strokePath(); + g.fillStyle(0x4d321f, 1); + g.fillRect(17, 38, 7, 12); + g.fillRect(33, 38, 7, 12); + g.generateTexture('squirrel', 58, 56); + + g.clear(); + g.fillStyle(0x8f5a2b, 1); + g.fillEllipse(10, 13, 15, 13); + g.fillStyle(0x4f341c, 1); + g.fillRect(6, 2, 8, 5); + g.generateTexture('acorn', 20, 22); + + g.clear(); + g.fillStyle(0xf4ddba, 1); + g.fillRoundedRect(12, 14, 7, 18, 3); + g.fillStyle(0xb94846, 1); + g.fillEllipse(16, 14, 28, 17); + g.fillStyle(0xffe8c8, 1); + g.fillCircle(10, 10, 2); + g.fillCircle(18, 8, 2); + g.fillCircle(23, 13, 2); + g.generateTexture('mushroom-red', 32, 34); + + g.clear(); + g.fillStyle(0xe8dbba, 1); + g.fillRoundedRect(12, 14, 7, 18, 3); + g.fillStyle(0x76528f, 1); + g.fillEllipse(16, 14, 28, 17); + g.fillStyle(0xdcccf0, 1); + g.fillCircle(10, 10, 2); + g.fillCircle(20, 9, 2); + g.generateTexture('mushroom-purple', 32, 34); + + g.clear(); + g.fillStyle(0xe0cfaa, 1); + g.fillRoundedRect(12, 13, 7, 19, 3); + g.fillStyle(0xe1a53a, 1); + g.fillEllipse(16, 13, 28, 16); + g.fillStyle(0xffefaa, 1); + g.fillCircle(10, 10, 2); + g.fillCircle(21, 10, 2); + g.generateTexture('mushroom-gold', 32, 34); + + g.clear(); + g.fillStyle(0x35684b, 1); + for (let i = 0; i < 5; i++) { + g.fillEllipse(17 + i * 2, 22 - i * 4, 9, 25, -0.7 + i * 0.25); + } + g.fillStyle(0x6aa56d, 1); + for (let i = 0; i < 4; i++) { + g.fillEllipse(12 + i * 6, 25 - (i % 2) * 6, 7, 19, 0.6 - i * 0.25); + } + g.generateTexture('fern', 42, 44); + + g.clear(); + g.fillStyle(0xe8b7c7, 1); + for (let i = 0; i < 5; i++) { + const a = (Math.PI * 2 * i) / 5; + g.fillCircle(9 + Math.cos(a) * 5, 9 + Math.sin(a) * 5, 4); + } + g.fillStyle(0xf5d067, 1); + g.fillCircle(9, 9, 3); + g.fillStyle(0x477654, 1); + g.fillRect(8, 14, 2, 14); + g.generateTexture('flower', 18, 30); + + g.clear(); + g.fillStyle(0x6c4429, 1); + g.fillRoundedRect(32, 0, 28, 120, 10); + g.fillStyle(0x244f39, 1); + g.fillCircle(22, 15, 28); + g.fillCircle(52, 12, 35); + g.fillCircle(70, 30, 28); + g.fillCircle(32, 42, 33); + g.fillStyle(0x35684b, 1); + g.fillCircle(10, 35, 22); + g.fillCircle(55, 50, 28); + g.generateTexture('tree', 92, 120); + + g.clear(); + g.fillStyle(0x393024, 1); + g.fillRoundedRect(0, 0, 140, 22, 10); + g.fillStyle(0x567645, 1); + g.fillRect(0, 0, 140, 7); + g.generateTexture('branch', 140, 22); + + g.clear(); + g.fillStyle(0xb4d9f2, 0.9); + g.fillEllipse(8, 8, 12, 7, -0.45); + g.fillEllipse(16, 8, 12, 7, 0.45); + g.fillStyle(0x3b3130, 1); + g.fillEllipse(12, 9, 4, 10); + g.generateTexture('butterfly', 24, 18); + + g.clear(); + g.fillStyle(0xffef95, 1); + g.fillCircle(6, 6, 3); + g.fillStyle(0xffef95, 0.18); + g.fillCircle(6, 6, 6); + g.generateTexture('firefly', 12, 12); + + g.clear(); + g.fillStyle(0x517a4e, 1); + g.fillEllipse(15, 16, 24, 16); + g.fillStyle(0x75995b, 1); + g.fillCircle(18, 10, 8); + g.fillStyle(0x1e2c22, 1); + g.fillCircle(15, 8, 1.5); + g.fillCircle(21, 8, 1.5); + g.generateTexture('frog', 30, 24); + + g.destroy(); + } + + createBackdrop() { + this.add.rectangle(WORLD_WIDTH / 2, 270, WORLD_WIDTH, 540, 0x8fc7a2).setScrollFactor(0.05); + + const far = this.add.graphics().setScrollFactor(0.12); + far.fillStyle(0x719f78, 1); + for (let x = -100; x < WORLD_WIDTH + 300; x += 170) { + far.fillCircle(x, 350 + (x % 3) * 8, 180); + } + + const mist = this.add.graphics().setScrollFactor(0.22); + mist.fillStyle(0xd9ead6, 0.28); + for (let x = 0; x < WORLD_WIDTH; x += 500) { + mist.fillEllipse(x, 480 + (x % 2) * 20, 520, 120); + } + + const canopy = this.add.graphics().setScrollFactor(0.35); + canopy.fillStyle(0x315f45, 0.95); + for (let x = -120; x < WORLD_WIDTH + 300; x += 150) { + canopy.fillCircle(x, 140 + ((x / 150) % 3) * 28, 110); + } + + for (let x = 200; x < WORLD_WIDTH; x += 720) { + this.add.image(x, 455, 'tree').setScale(2.5).setAlpha(0.58).setScrollFactor(0.55).setOrigin(0.5, 1); + } + } + + createWorld() { + this.platforms = this.physics.add.staticGroup(); + + const ground = this.add.rectangle(WORLD_WIDTH / 2, GROUND_Y + 46, WORLD_WIDTH, 100, 0x263c2d); + this.physics.add.existing(ground, true); + this.platforms.add(ground); + + this.add.rectangle(WORLD_WIDTH / 2, GROUND_Y + 2, WORLD_WIDTH, 20, 0x55714a); + + const branchPositions = [ + [520, 520], [900, 445], [1320, 525], [1680, 415], [2050, 505], + [2470, 430], [2910, 515], [3370, 405], [3800, 500], [4230, 425], + [4680, 520], [5100, 430] + ]; + + branchPositions.forEach(([x, y], index) => { + const branch = this.platforms.create(x, y, 'branch'); + branch.setScale(index % 3 === 0 ? 1.35 : 1); + branch.refreshBody(); + }); + + for (let x = 90; x < WORLD_WIDTH - 120; x += 105) { + const n = Math.sin(x * 0.013) + Math.cos(x * 0.021); + if (n > -0.15) { + this.add.image(x, GROUND_Y - 10, 'fern') + .setOrigin(0.5, 1) + .setScale(0.65 + ((x % 70) / 160)) + .setAlpha(0.85); + } + + if (x % 315 < 130) { + this.add.image(x + 34, GROUND_Y - 5, 'flower') + .setOrigin(0.5, 1) + .setScale(0.7 + ((x % 50) / 170)); + } + } + + const zones = [ + { x: 430, label: 'Hazel Hollow' }, + { x: 1720, label: 'Fernfall' }, + { x: 3070, label: 'Foxglove Rise' }, + { x: 4380, label: 'Old Root Wood' }, + { x: 5260, label: 'Moonlit Grove' } + ]; + + zones.forEach(zone => { + this.add.text(zone.x, 270, zone.label, { + fontFamily: 'Georgia, serif', + fontSize: '28px', + color: '#f2edd9', + stroke: '#24372c', + strokeThickness: 5 + }).setOrigin(0.5).setAlpha(0.75); + }); + + this.groveGlow = this.add.circle(5260, 500, 130, 0xffe3a0, 0.05); + this.groveGlow.setVisible(false); + this.groveTrigger = this.add.zone(5260, 520, 260, 220); + this.physics.add.existing(this.groveTrigger, true); + } + + createPlayer() { + this.player = this.physics.add.sprite(160, 520, 'squirrel'); + this.player.setScale(1.12); + this.player.setCollideWorldBounds(true); + this.player.setDragX(900); + this.player.setMaxVelocity(330, 760); + this.player.body.setSize(34, 47); + this.player.body.setOffset(12, 7); + } + + createCollectibles() { + this.acornGroup = this.physics.add.group({ allowGravity: true }); + [ + [330, 540], [520, 460], [760, 560], [900, 385], [1180, 555], + [1320, 465], [1540, 560], [1680, 355], [1900, 555], [2050, 445], + [2280, 555], [2470, 370], [2730, 555], [2910, 455], [3150, 555], + [3370, 345], [3610, 555], [3800, 440], [4050, 555], [4230, 365], + [4470, 555], [4680, 460], [4910, 555], [5100, 370] + ].forEach(([x, y], i) => { + const acorn = this.acornGroup.create(x, y, 'acorn'); + acorn.setBounce(0.2); + acorn.setData('phase', i * 0.4); + }); + + this.mushroomGroup = this.physics.add.group({ allowGravity: true }); + const mushrooms = [ + [720, 575, 'mushroom-red', 'Scarlet bonnet'], + [1700, 360, 'mushroom-purple', 'Amethyst veil'], + [2860, 575, 'mushroom-gold', 'Honey lantern'], + [4170, 370, 'mushroom-red', 'Foxfire cap'], + [4860, 575, 'mushroom-purple', 'Moon gill'] + ]; + + mushrooms.forEach(([x, y, texture, name]) => { + const mushroom = this.mushroomGroup.create(x, y, texture); + mushroom.setData('name', name); + mushroom.setBounce(0.1); + this.tweens.add({ + targets: mushroom, + y: y - 6, + duration: 900 + (x % 400), + yoyo: true, + repeat: -1, + ease: 'Sine.inOut' + }); + }); + } + + createFauna() { + const butterflies = [ + [850, 330], [1450, 300], [2300, 350], [3520, 280], [4550, 315] + ]; + + butterflies.forEach(([x, y], i) => { + const b = this.add.image(x, y, 'butterfly').setScale(0.85); + this.tweens.add({ + targets: b, + x: x + (i % 2 ? -90 : 90), + y: y - 35, + duration: 2600 + i * 210, + yoyo: true, + repeat: -1, + ease: 'Sine.inOut' + }); + }); + + [1120, 2600, 3980].forEach((x, i) => { + const frog = this.add.image(x, GROUND_Y - 8, 'frog').setOrigin(0.5, 1); + this.tweens.add({ + targets: frog, + y: GROUND_Y - 20, + duration: 220, + delay: 2300 + i * 900, + yoyo: true, + repeat: -1, + repeatDelay: 3000 + i * 500 + }); + }); + + this.fireflies = []; + for (let i = 0; i < 24; i++) { + const f = this.add.image(5100 + (i % 6) * 55, 360 + Math.floor(i / 6) * 48, 'firefly'); + f.setAlpha(0.12); + this.fireflies.push(f); + this.tweens.add({ + targets: f, + x: f.x + Phaser.Math.Between(-28, 28), + y: f.y + Phaser.Math.Between(-22, 22), + duration: Phaser.Math.Between(1000, 2200), + yoyo: true, + repeat: -1, + ease: 'Sine.inOut' + }); + }); + } + + createHud() { + const panel = this.add.rectangle(18, 18, 300, 112, 0x17271f, 0.78) + .setOrigin(0) + .setScrollFactor(0) + .setDepth(20) + .setStrokeStyle(1, 0xc9d6bd, 0.3); + + this.acornText = this.add.text(34, 31, 'Acorns 0', { + fontFamily: 'Georgia, serif', + fontSize: '20px', + color: '#f1d39a' + }).setScrollFactor(0).setDepth(21); + + this.mushroomText = this.add.text(34, 59, `Forest caps 0 / ${this.totalMushrooms}`, { + fontFamily: 'Georgia, serif', + fontSize: '18px', + color: '#dfd3ed' + }).setScrollFactor(0).setDepth(21); + + this.objectiveText = this.add.text(34, 89, 'Find the five unusual mushrooms hidden through the wood', { + fontFamily: 'Georgia, serif', + fontSize: '13px', + color: '#dbe5d7', + wordWrap: { width: 270 } + }).setScrollFactor(0).setDepth(21); + + this.discovery = this.add.text(this.scale.width / 2, 150, '', { + fontFamily: 'Georgia, serif', + fontSize: '25px', + color: '#fff3cf', + stroke: '#1a2a21', + strokeThickness: 6 + }).setOrigin(0.5).setScrollFactor(0).setDepth(30).setAlpha(0); + + this.scale.on('resize', gameSize => { + this.discovery.setPosition(gameSize.width / 2, 150); + this.positionTouchControls(gameSize.width, gameSize.height); + }); + } + + createControls() { + this.cursors = this.input.keyboard.createCursorKeys(); + this.keys = this.input.keyboard.addKeys('A,D,W,SPACE'); + + const makeButton = (x, y, label, onDown, onUp) => { + const circle = this.add.circle(x, y, 34, 0x15261e, 0.55) + .setScrollFactor(0) + .setDepth(40) + .setStrokeStyle(2, 0xe0eadb, 0.35) + .setInteractive(); + + const text = this.add.text(x, y - 2, label, { + fontFamily: 'Arial, sans-serif', + fontSize: '24px', + color: '#edf4e9' + }).setOrigin(0.5).setScrollFactor(0).setDepth(41); + + circle.on('pointerdown', onDown); + circle.on('pointerup', onUp); + circle.on('pointerout', onUp); + return { circle, text }; + }; + + this.leftBtn = makeButton(68, this.scale.height - 70, '‹', + () => { this.touch.left = true; }, + () => { this.touch.left = false; } + ); + + this.rightBtn = makeButton(146, this.scale.height - 70, '›', + () => { this.touch.right = true; }, + () => { this.touch.right = false; } + ); + + this.jumpBtn = makeButton(this.scale.width - 74, this.scale.height - 70, '↑', + () => { this.touch.jump = true; }, + () => { this.touch.jump = false; } + ); + + this.input.keyboard.on('keydown-UP', () => this.tryJump()); + this.input.keyboard.on('keydown-W', () => this.tryJump()); + this.input.keyboard.on('keydown-SPACE', () => this.tryJump()); + } + + positionTouchControls(width, height) { + if (!this.leftBtn) return; + this.leftBtn.circle.setPosition(68, height - 70); + this.leftBtn.text.setPosition(68, height - 72); + this.rightBtn.circle.setPosition(146, height - 70); + this.rightBtn.text.setPosition(146, height - 72); + this.jumpBtn.circle.setPosition(width - 74, height - 70); + this.jumpBtn.text.setPosition(width - 74, height - 72); + } + + tryJump() { + if (!this.player?.body) return; + if (this.player.body.blocked.down || this.player.body.touching.down) { + this.player.setVelocityY(-470); + this.player.setAngularVelocity(this.player.flipX ? -25 : 25); + this.time.delayedCall(180, () => this.player?.setAngularVelocity(0)); + } + } + + showDiscovery(name) { + this.discovery.setText(`Discovered: ${name}`); + this.discovery.setAlpha(0).setY(158); + this.tweens.add({ + targets: this.discovery, + alpha: 1, + y: 142, + duration: 260, + yoyo: true, + hold: 950 + }); + } + + revealGrove() { + this.groveGlow.setVisible(true); + this.tweens.add({ + targets: this.groveGlow, + alpha: 0.28, + scale: 1.35, + duration: 1300, + yoyo: true, + repeat: -1, + ease: 'Sine.inOut' + }); + + this.fireflies.forEach((f, i) => { + this.tweens.add({ + targets: f, + alpha: 0.9, + duration: 500 + i * 35 + }); + }); + } + + showEnding() { + const title = this.add.text(this.scale.width / 2, this.scale.height / 2 - 42, + 'The Moonlit Grove remembers you.', { + fontFamily: 'Georgia, serif', + fontSize: '34px', + color: '#fff1bf', + stroke: '#15241d', + strokeThickness: 7, + align: 'center' + }).setOrigin(0.5).setScrollFactor(0).setDepth(50).setAlpha(0); + + const sub = this.add.text(this.scale.width / 2, this.scale.height / 2 + 16, + `You found ${this.mushrooms} forest caps and ${this.acorns} acorns.\nPrototype trail complete.`, { + fontFamily: 'Georgia, serif', + fontSize: '18px', + color: '#e0eadb', + align: 'center', + lineSpacing: 8 + }).setOrigin(0.5).setScrollFactor(0).setDepth(50).setAlpha(0); + + this.tweens.add({ targets: [title, sub], alpha: 1, duration: 900 }); + } + + update(time) { + if (!this.player?.body || this.finished) return; + + const left = this.cursors.left.isDown || this.keys.A.isDown || this.touch.left; + const right = this.cursors.right.isDown || this.keys.D.isDown || this.touch.right; + + if (left && !right) { + this.player.setAccelerationX(-1050); + this.player.setFlipX(true); + } else if (right && !left) { + this.player.setAccelerationX(1050); + this.player.setFlipX(false); + } else { + this.player.setAccelerationX(0); + } + + if (this.touch.jump) { + this.tryJump(); + this.touch.jump = false; + } + + const grounded = this.player.body.blocked.down || this.player.body.touching.down; + if (grounded) { + this.player.setAngle(0); + } else { + this.player.setAngle(Phaser.Math.Clamp(this.player.body.velocity.x * 0.025, -8, 8)); + } + + this.acornGroup.children.iterate(acorn => { + if (!acorn?.active) return; + acorn.setAngle(Math.sin(time * 0.003 + acorn.getData('phase')) * 10); + }); + } +} + +const config = { + type: Phaser.AUTO, + parent: 'game', + width: 1280, + height: 720, + backgroundColor: '#10251d', + physics: { + default: 'arcade', + arcade: { + gravity: { y: 1180 }, + debug: false + } + }, + scale: { + mode: Phaser.Scale.RESIZE, + autoCenter: Phaser.Scale.CENTER_BOTH + }, + render: { + antialias: true, + pixelArt: false + }, + scene: [ForestScene] +}; + +new Phaser.Game(config); diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..a3ada45 --- /dev/null +++ b/src/style.css @@ -0,0 +1,20 @@ +html, +body, +#game { + width: 100%; + height: 100%; + margin: 0; + overflow: hidden; + background: #10251d; +} + +body { + font-family: Georgia, "Times New Roman", serif; + touch-action: none; +} + +canvas { + display: block; + width: 100%; + height: 100%; +}