From dda2f27c8dca4ac6a0cb4bc6d92b266bf02747ec Mon Sep 17 00:00:00 2001 From: bye <bye@byecorps.com> Date: Sat, 7 Sep 2024 17:00:59 +0100 Subject: [PATCH] Forgor to update --- hampsterengine | 2 +- package.json | 2 +- src/js/extras.js | 14 +++- src/js/main.js | 14 +++- src/js/objects/player.js | 135 ++++++++++++++++++++++++++++++++++++++- src/js/rooms/game.js | 76 ++++------------------ 6 files changed, 174 insertions(+), 69 deletions(-) diff --git a/hampsterengine b/hampsterengine index dd760ba..3224534 160000 --- a/hampsterengine +++ b/hampsterengine @@ -1 +1 @@ -Subproject commit dd760ba404d7b679b0fb46aa0abaaa05f40b329c +Subproject commit 32245348ac2e1223b8742bfb60d68391e29ffe7e diff --git a/package.json b/package.json index 6b56efc..5fb32f4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "dev:js": "esbuild src/js/main.js --bundle --watch --sourcemap --format=iife --loader:.webp=dataurl --outfile=build/main.js", "dev:html": "browser-sync build src --watch --https", "build": "run-s clear build:*", - "build:js": "esbuild src/js/main.js --bundle --format=iife --loader:.webp=dataurl | terser -c -m --mangle-props keep_quoted -o build/main.js", + "build:js": "esbuild src/js/main.js --bundle --format=iife --loader:.webp=dataurl | terser -c -m --mangle-props keep_quoted | roadroller -t js - -o build/main.js", "build:html": "html-inline src/index.html -b build | html-minifier -c configs/html-minifier.json -o build/index.html", "build:zip": "zip -FS -qjX9 build/game.zip build/index.html && advzip -z -4 build/game.zip", "build:zipSize": "node utils/size.js" diff --git a/src/js/extras.js b/src/js/extras.js index 77f3731..3dfd06c 100644 --- a/src/js/extras.js +++ b/src/js/extras.js @@ -6,9 +6,21 @@ export function drawLineThroughPoint(x, y) { export const clone = structuredClone; +export const GRAVITY_X = 0; // I don't think we're going to use X gravity but i'm going to keep in the source in case i do +export const GRAVITY_Y = 450; // Per second + export const round = Math.round; export const roundToRatio = x => { - return round(x * canvas.pixelRatio) / canvas.pixelRatio + return round(x * canvas.pixelRatio * canvas.scale) / canvas.pixelRatio / canvas.scale +} + +export const easeOutCubic = (x) => { + return 1 - Math.pow(1 - x, 3); +} + +export const easeOutSine = (x) => { + return Math.sin((x * Math.PI) / 2); + } export const abs = Math.abs; diff --git a/src/js/main.js b/src/js/main.js index ededfba..a07f2cb 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -13,7 +13,7 @@ const keyboard = new Keyboard(); import SoundBox from "./sb-player-small"; // import {mus_DEMOSONG} from "./songs/DEMOSONGDONOTCOMMIT"; -// dependencies used for debugging. comment out code that uses this and they won't be included +// dependencies used for debugging. comment out code that uses this, and they won't be included // import Stats from "stats.js"; // Images @@ -29,6 +29,7 @@ import {rm_DEBUG_INCURSION} from "./rooms/debug_incursion"; import {rm_DEBUG_text} from "./rooms/debug_text"; import {rm_DEBUG_stars} from "./rooms/debug_stars"; import {rm_DEBUG_sprites} from "./rooms/debug_sprites"; +import {round} from "./extras"; // Music // There is none @@ -85,6 +86,15 @@ engine.running = false; // Game uses this as a pause state actually const GROUND_PALETTE = ['#2a6', '#964', '#853'] assets.addMiniSprite('grass', 'IIIIIIQIQQQJZQZZRZRRZRZRSSRSRZZR', 8, GROUND_PALETTE); assets.addMiniSprite('dirt', 'SSRRRZ[ZZZRRZRZZRZRRZRZRSSRSRZZR', 8, GROUND_PALETTE); +// assets.addMiniSprite('player', '@@@@@@@@@@@@@@@@@@_XCx@@@@@II@@@@@HSSA@@@@H[[A@@@@@II@@@@@@@@@@@@@`dd@@@@@dddD@@@@dddD@@@@mdlE@@@@@dD@@@@@@[C@@@@@@[C@@@@@G[[x@@', 16, [ +// '#000', '#fff', '#241F31', '#77b19d', '#FAB80C',,'pink' +// ]); +assets.addMiniSprite('player_head', '@@@C[@HIAYZJY[KHIA', 6, [ + '#000', '#fff', '#241F31' +]); +assets.addMiniSprite('body', 'HIIAIIIIIIII[II[@II@@RR@@RR@@RRB', 8, [ + '#77b19d', '#241F31', '#FAB80C' +]); engine.registerRoom(rm_mainMenu, 'mainMenu'); engine.registerRoom(rm_game, 'game'); @@ -124,7 +134,7 @@ function main() { if (debug) { canvas.drawText(`physics ticks: ${engine.physicsFrames} (~${(engine.physicsFrames/60).toFixed(1)}sec)`, 0, 0,{textBaseline:'top'}) - canvas.drawText(`camera pos: ${canvas.camera.x},${canvas.camera.y}`, 0, 8,{textBaseline:'top'}) + canvas.drawText(`camera pos: ${round(canvas.camera.x)},${round(canvas.camera.y)}`, 0, 8,{textBaseline:'top'}) canvas.drawText(`run time: ${((performance.now()-readyTime)/1000).toFixed(1)}sec`, 0, 16, {textBaseline:'top'}) canvas.drawText(`keys: ${JSON.stringify(keyboard.keys)}`, 0, 24, {textBaseline:'top'}) } diff --git a/src/js/objects/player.js b/src/js/objects/player.js index 885cd6b..df4db12 100644 --- a/src/js/objects/player.js +++ b/src/js/objects/player.js @@ -1,5 +1,6 @@ import {Entity} from "../../../hampsterengine/src/things"; -import {round, roundToRatio} from "../extras"; +import {abs, easeOutSine, GRAVITY_X, GRAVITY_Y, round, roundToRatio} from "../extras"; +import {rm_game} from "../rooms/game"; export default class Player extends Entity { constructor(props) { @@ -7,7 +8,98 @@ export default class Player extends Entity { this.jumping = false; + this.width = 4; + this.height = 8; + + this.flipped = 0; + + this.stepUp = 0; + this.lastFramePos = {x: this.x, y: this.y}; + + this.headTarget = {x:this.x, y:this.y}; + this.headPos = {x:this.x, y: this.y}; + this.headPosStart = {x:this.x, y: this.y}; + this.headTrans = 25; + this.headStartTime = performance.now(); + + this.collideRects = [ + {x:0, y:0, w: this.width, h: this.height} + ]; + } + + step() { + const elapsed = 1 / 60; + + const keys = keyboard.keys; + const keysUp = keyboard.keysUpThisFrame; + + let friction = 0.95; + const boost = keys.includes("Shift") ? 40 : 0; + + for (let key of keys) { + switch (key) { + case "ArrowLeft": + this.flipped = !0; + if (!(engine.physicsFrames % 15)) this.stepUp ^= true; + this.vx = -50-boost; + break; + case "ArrowRight": + this.flipped = 0; + if (!(engine.physicsFrames % 15)) this.stepUp ^= true; + this.vx = 50+boost; + break; + case " ": + if (!this.jumping) { + this.jumping = true; + this.vy -= 150; + } + break; + } + } + + if ((!(engine.physicsFrames % 15) && this.vx == 0) || this.vy) this.stepUp = 0; + + + const entities = engine.room.entities; + const entitiesWithoutThePlayer = [...entities].toSpliced(entities.indexOf(this), 1); + // console.debug(entitiesWithoutThePlayer); + + this.vx = Math.min(400, this.vx + (this.ax * elapsed + GRAVITY_X*elapsed)); + this.vy = Math.min(400, this.vy + (this.ay * elapsed + GRAVITY_Y*elapsed)); + this.x += this.vx * elapsed; + this.y += this.vy * elapsed; + + // Make acceleration decay + this.ax *= 0.1; + this.ay *= 0.1; + + if (abs(this.ax) < 0.01) this.ax = 0; + if (abs(this.ay) < 0.01) this.ay = 0; + + engine.room.x = this.x; + engine.room.y = this.y; + + for (const entity of entitiesWithoutThePlayer) { + if (this.checkCollision(entity)) { + friction = 0.8; + let side = this.resolveCollision(entity); + if (side === 2) this.jumping = 0; + if (side === 1 || side === 3) friction = 0.5; + } + } + + // player.vy *= friction; + this.vx *= friction; + + if (abs(this.vy) < 1) this.vy = 0; + if (abs(this.vx) < 1) this.vx = 0; + + if (player.x !== player.lastFramePos.x || player.y !== player.lastFramePos.y || !this.stepUp ) { + this.headTarget = {x: this.x, y: this.y - (this.stepUp ? 1 : 0)} + this.headPosStart = structuredClone(this.headPos); + this.headStartTime = performance.now(); + } } draw() { @@ -17,6 +109,45 @@ export default class Player extends Entity { // const interpolationY = this.vy * timeSinceLastFrame; // const interpolationX = 0; // const interpolationY = 0; - canvas.fillRect(roundToRatio(this.x),roundToRatio(this.y),this.width,this.height); + for (let rect of this.collideRects) { + console.debug(rect); + canvas.fillRect(roundToRatio(this.x + rect.x),roundToRatio(this.y + rect.y),rect.w,rect.h); + } + + canvas.tempFilter(_=>{ + const img = this.flipped ? engine.assetStore.get`body`.flipped : engine.assetStore.get`body`.sprite + canvas.drawImage( + img, + this.x - 2, + this.y - (this.stepUp ? 1 : 0), + 8, (this.stepUp ? 9 : 8) + ) + }, 'opacity(0.7)'); + + // calculate the position of the head + let distX = this.headTarget.x - this.headPosStart.x; + let distY = this.headTarget.y - this.headPosStart.y; + + const elapsed = Math.min(performance.now() - this.headStartTime, this.headTrans); + const end = this.headTrans; + const pos = easeOutSine(elapsed / end || 1); + + this.headPos.x = Math.min( + this.headTarget.x, + this.headPosStart.x + (distX * pos) + ); + this.headPos.y = Math.min( + this.headTarget.y, + this.headPosStart.y + (distY * pos) + ); + + // Draw the head + canvas.drawImage( + engine.assetStore.get`player_head`.sprite, + roundToRatio(this.headPos.x - 1), + roundToRatio(this.headPos.y - 7), + engine.assetStore.get`player_head`.size, + engine.assetStore.get`player_head`.size + ) } } diff --git a/src/js/rooms/game.js b/src/js/rooms/game.js index 60eeca4..8b5d6d1 100644 --- a/src/js/rooms/game.js +++ b/src/js/rooms/game.js @@ -5,8 +5,7 @@ import {clone, clonePlayer, abs, roundToRatio} from "../extras"; import Ground from "../objects/ground"; export const rm_game = new Room(); -const GRAVITY_X = 0; // I don't think we're going to use X gravity but i'm going to keep in the source in case i do -const GRAVITY_Y = 600; // Per second + const entities = rm_game.entities; rm_game.width = 2560; @@ -23,61 +22,8 @@ rm_game.stop = _=>{ rm_game.step = _=>{ canvas.camera.step(); - - const elapsed = 1 / 60; const player = rm_game.get('plr'); - - let friction = 0.95; - const boost = keyboard.keys.includes("Shift") ? 40 : 0; - - for (const key of keyboard.keys) { - switch (key) { - case "ArrowLeft": - player.vx = -50-boost; - break; - case "ArrowRight": - player.vx = 50+boost; - break; - case " ": - if (!player.jumping) { - player.jumping = true; - player.vy -= 150; - } - } - } - - const entitiesWithoutThePlayer = [...entities].toSpliced(entities.indexOf(player), 1); - // console.debug(entitiesWithoutThePlayer); - - player.vx = Math.min(400, player.vx + (player.ax * elapsed + GRAVITY_X*elapsed)); - player.vy = Math.min(400, player.vy + (player.ay * elapsed + GRAVITY_Y*elapsed)); - player.x += player.vx * elapsed; - player.y += player.vy * elapsed; - - // Make acceleration decay - player.ax *= 0.1; - player.ay *= 0.1; - - if (abs(player.ax) < 0.01) player.ax = 0; - if (abs(player.ay) < 0.01) player.ay = 0; - - rm_game.x = player.x; - rm_game.y = player.y; - - for (const entity of entitiesWithoutThePlayer) { - if (player.checkCollision(entity)) { - friction = 0.8; - let side = player.resolveCollision(entity); - if (side === 2) player.jumping = 0; - if (side === 1 || side === 3) friction = 0.5; - } - } - - // player.vy *= friction; - player.vx *= friction; - - if (abs(player.vy) < 1) player.vy = 0; - if (abs(player.vx) < 1) player.vx = 0; + player.step(); if (player.x !== player.lastFramePos.x || player.y !== player.lastFramePos.y) { player.lastFramePos = {x: player.x, y: player.y}; @@ -85,18 +31,19 @@ rm_game.step = _=>{ canvas.camera.goTo( Math.min(Math.max(player.x+(player.width/2)-canvas.width/2, canvas.width/8), rm_game.width-canvas.width), Math.min(Math.max(player.y-canvas.height/8, canvas.height/8), rm_game.height-canvas.height), - 100 + 150 ); } + } rm_game.draw = _ => { canvas.ctx.save(); - canvas.ctx.translate(roundToRatio(-canvas.camera.x), roundToRatio(-canvas.camera.y)); + canvas.ctx.translate(roundToRatio(-canvas.camera.x,), roundToRatio(-canvas.camera.y)); for (let thing of rm_game.entities) { thing.draw(); } - canvas.strokeRect(rm_game.x, rm_game.y, player.width, player.height); + // canvas.strokeRect(rm_game.x, rm_game.y, player.width, player.height); canvas.ctx.restore(); } @@ -115,6 +62,14 @@ rm_game.drawGui = _ => { maxWidth: canvas.width-10, size: 4 }); + canvas.drawText(`Head: x:${player.headPosStart.x} y:${player.headPosStart.y}`, 5, canvas.height-17, { + maxWidth: canvas.width-10, + size: 4 + }); + canvas.drawText(`Head Target: x:${player.headTarget.x} y:${player.headTarget.y}`, 5, canvas.height-21, { + maxWidth: canvas.width-10, + size: 4 + }); } rm_game.init = _=>{ @@ -122,8 +77,6 @@ rm_game.init = _=>{ player.x = 40; player.y = 40; - player.width = 8; - player.height = 8*(8/5); window.player = player; rm_game.push(player, 'plr'); @@ -132,6 +85,5 @@ rm_game.init = _=>{ ground.y = rm_game.height - ground.height; rm_game.push(ground); - } -- GitLab