diff options
author | elioat <elioat@tilde.institute> | 2024-12-28 17:24:34 -0500 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2024-12-28 17:24:34 -0500 |
commit | b4bbc90048e9cbcfeda046a41b347f655c0690e6 (patch) | |
tree | 1551ff8b55a09ead3cf8846893de23fbad815ef1 | |
parent | 5e712f625536390a28bbf66829bd26f3f84a189c (diff) | |
download | tour-b4bbc90048e9cbcfeda046a41b347f655c0690e6.tar.gz |
*
-rw-r--r-- | html/rogue/assets/home/goblin-01.png | bin | 0 -> 11889 bytes | |||
-rw-r--r-- | html/rogue/assets/home/goblin-02.png | bin | 0 -> 11875 bytes | |||
-rw-r--r-- | html/rogue/assets/home/goblin.json | 617 | ||||
-rw-r--r-- | html/rogue/index.html | 1 | ||||
-rw-r--r-- | html/rogue/js/animation.js | 53 | ||||
-rw-r--r-- | html/rogue/js/config.js | 4 | ||||
-rw-r--r-- | html/rogue/js/game.js | 6 | ||||
-rw-r--r-- | html/rogue/js/player.js | 79 |
8 files changed, 750 insertions, 10 deletions
diff --git a/html/rogue/assets/home/goblin-01.png b/html/rogue/assets/home/goblin-01.png new file mode 100644 index 0000000..c70d2fd --- /dev/null +++ b/html/rogue/assets/home/goblin-01.png Binary files differdiff --git a/html/rogue/assets/home/goblin-02.png b/html/rogue/assets/home/goblin-02.png new file mode 100644 index 0000000..19411c8 --- /dev/null +++ b/html/rogue/assets/home/goblin-02.png Binary files differdiff --git a/html/rogue/assets/home/goblin.json b/html/rogue/assets/home/goblin.json new file mode 100644 index 0000000..8b0e418 --- /dev/null +++ b/html/rogue/assets/home/goblin.json @@ -0,0 +1,617 @@ +{ + "__projectHeader": "pppppp_v1", + "timestamp": "2024-12-28T22:11:34.632Z", + "data": { + "gridWidth": 16, + "gridHeight": 16, + "cellSize": 29.296875, + "colorHistory": [ + "#eeb243", + "#ffbe47", + "#ff5eeb", + "#ff5feb", + "#9db13a", + "#000000", + "#e7ad41", + "#f5fff6", + "#af2866", + "#a87d2e" + ], + "currentColor": "#9db13a", + "canvases": [ + { + "grid": [ + [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + [ + null, + null, + null, + "#000000", + "#000000", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#99b213", + "#000000", + null, + null, + null, + null, + null, + null, + null, + "#000000", + "#000000", + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#ff5feb", + "#99b213", + "#000000", + "#000000", + "#000000", + "#000000", + null, + null, + "#000000", + "#99b213", + "#000000", + null + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#000000", + null, + "#000000", + "#99b213", + "#000000", + null + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#000000", + "#c00f68", + "#c00f68", + "#b07b12", + "#000000" + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#000000", + "#000000", + "#99b213", + "#f5fff6", + "#f5fff6", + "#99b213", + "#000000", + "#c00f68", + "#c00f68", + "#b07b12", + "#000000" + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#000000", + "#99b213", + "#000000", + "#c00f68", + "#c00f68", + "#000000", + null + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#000000", + "#99b213", + "#000000", + "#c00f68", + "#c00f68", + "#000000", + null + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#000000", + "#000000", + "#99b213", + "#99b213", + "#f5fff6", + "#99b213", + "#000000", + "#c00f68", + "#c00f68", + "#b07b12", + "#000000" + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#000000", + "#c00f68", + "#c00f68", + "#b07b12", + "#000000" + ], + [ + null, + "#000000", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#99b213", + "#000000", + null, + "#000000", + "#99b213", + "#000000", + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#ff5feb", + "#99b213", + "#000000", + "#000000", + "#000000", + "#000000", + null, + null, + "#000000", + "#99b213", + "#000000", + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#99b213", + "#000000", + null, + null, + null, + null, + null, + null, + null, + "#000000", + "#000000", + null + ], + [ + null, + null, + null, + "#000000", + "#000000", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ] + ], + "offsetX": 143.1015625, + "offsetY": 218.625, + "hasPixels": false + }, + { + "grid": [ + [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + [ + null, + null, + null, + "#000000", + "#000000", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#9db13a", + "#000000", + null, + null, + null, + null, + null, + "#000000", + "#000000", + null, + null, + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#ff5eeb", + "#9db13a", + "#000000", + "#000000", + "#000000", + "#000000", + null, + "#000000", + "#9db13a", + "#000000", + null, + null + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#000000", + "#9db13a", + "#000000", + "#000000", + null + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#af2866", + "#af2866", + "#a87d2e", + "#000000" + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#000000", + "#9db13a", + "#f5fff6", + "#f5fff6", + "#9db13a", + "#000000", + "#af2866", + "#af2866", + "#a87d2e", + "#000000" + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#9db13a", + "#000000", + "#af2866", + "#af2866", + "#000000", + null + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#9db13a", + "#000000", + "#af2866", + "#af2866", + "#000000", + null + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#000000", + "#9db13a", + "#9db13a", + "#f5fff6", + "#9db13a", + "#000000", + "#af2866", + "#af2866", + "#a87d2e", + "#000000" + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#af2866", + "#af2866", + "#a87d2e", + "#000000" + ], + [ + null, + "#000000", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#9db13a", + "#000000", + "#000000", + "#9db13a", + "#000000", + "#000000", + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#ff5eeb", + "#9db13a", + "#000000", + "#000000", + "#000000", + "#000000", + null, + "#000000", + "#9db13a", + "#000000", + null, + null + ], + [ + null, + null, + "#000000", + "#9db13a", + "#9db13a", + "#000000", + null, + null, + null, + null, + null, + "#000000", + "#000000", + null, + null, + null + ], + [ + null, + null, + null, + "#000000", + "#000000", + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ] + ], + "offsetX": 641.1484375, + "offsetY": 218.625, + "hasPixels": false + } + ], + "isPaletteVisible": true, + "globalOffsetX": -87.890625, + "globalOffsetY": 0 + } +} \ No newline at end of file diff --git a/html/rogue/index.html b/html/rogue/index.html index 47ad50f..655c4cb 100644 --- a/html/rogue/index.html +++ b/html/rogue/index.html @@ -20,6 +20,7 @@ <body> <canvas id="gameCanvas"></canvas> <script src="js/config.js"></script> + <script src="js/animation.js"></script> <script src="js/hex.js"></script> <script src="js/camera.js"></script> <script src="js/fow.js"></script> diff --git a/html/rogue/js/animation.js b/html/rogue/js/animation.js new file mode 100644 index 0000000..d682b01 --- /dev/null +++ b/html/rogue/js/animation.js @@ -0,0 +1,53 @@ +const Animation = { + // Track loaded images with their paths as keys + images: new Map(), + + // Load an image and return a promise + loadImage(path) { + if (this.images.has(path)) { + return Promise.resolve(this.images.get(path)); + } + + return new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => { + this.images.set(path, img); + resolve(img); + }; + img.onerror = () => reject(new Error(`Failed to load image: ${path}`)); + img.src = path; + }); + }, + + // Animation class to handle sprite animations + createAnimation(frames, frameTime) { + return { + frames, + frameTime, + currentFrame: 0, + lastFrameTime: 0, + + update(currentTime) { + if (currentTime - this.lastFrameTime >= this.frameTime) { + this.currentFrame = (this.currentFrame + 1) % this.frames.length; + this.lastFrameTime = currentTime; + } + return this.frames[this.currentFrame]; + } + }; + }, + + // Add this new method to scale sprites to fit within bounds + scaleToFit(image, maxWidth, maxHeight) { + const scale = Math.min( + maxWidth / image.width, + maxHeight / image.height + ); + + return { + width: image.width * scale, + height: image.height * scale, + scale + }; + } +}; \ No newline at end of file diff --git a/html/rogue/js/config.js b/html/rogue/js/config.js index efe8cbf..6ed925f 100644 --- a/html/rogue/js/config.js +++ b/html/rogue/js/config.js @@ -43,7 +43,9 @@ const Config = { player: { MOVE_SPEED: 0.1, SIZE_RATIO: 1/3, - VISION_RANGE: 3 + VISION_RANGE: 3, + SPRITE_SCALE: 0.8, + ANIMATION_SPEED: 500 }, camera: { diff --git a/html/rogue/js/game.js b/html/rogue/js/game.js index 427fab2..48133d8 100644 --- a/html/rogue/js/game.js +++ b/html/rogue/js/game.js @@ -7,11 +7,11 @@ const state = { ctx: null }; -function init() { +async function init() { state.canvas = document.getElementById('gameCanvas'); state.ctx = state.canvas.getContext('2d'); - player.init(); + await player.init(); Debug.init(); function resize() { @@ -118,4 +118,4 @@ function handleClick(event) { } } -init(); \ No newline at end of file +init().catch(console.error); \ No newline at end of file diff --git a/html/rogue/js/player.js b/html/rogue/js/player.js index 3c1c383..efecbdf 100644 --- a/html/rogue/js/player.js +++ b/html/rogue/js/player.js @@ -7,12 +7,30 @@ const player = { moveSpeed: Config.player.MOVE_SPEED, // Movement speed (0 to 1 per frame) inventory: [], + // Animation properties + animation: null, + sprites: [], + // Initialize player - init() { + async init() { this.position = { q: 0, r: 0 }; this.target = null; this.path = []; this.inventory = []; + + // Load sprites + try { + const [sprite1, sprite2] = await Promise.all([ + Animation.loadImage('assets/home/goblin-01.png'), + Animation.loadImage('assets/home/goblin-02.png') + ]); + + this.sprites = [sprite1, sprite2]; + this.animation = Animation.createAnimation(this.sprites, 500); // 500ms per frame + } catch (error) { + console.error('Failed to load player sprites:', error); + } + return this; }, @@ -151,14 +169,63 @@ const player = { const screenX = pixelPos.x - camera.x; const screenY = pixelPos.y - camera.y; - ctx.fillStyle = Config.colors.PLAYER; - ctx.beginPath(); - ctx.arc(screenX, screenY, HEX_SIZE * Config.player.SIZE_RATIO, 0, Math.PI * 2); - ctx.fill(); + if (this.animation && this.sprites.length > 0) { + // Get current sprite from animation + const currentSprite = this.animation.update(performance.now()); + + // Scale sprite to fit within hex + // Use slightly smaller than hex size to ensure it fits visually + const hexInnerSize = HEX_SIZE * 0.8; // 80% of hex size + const { width, height, scale } = Animation.scaleToFit( + currentSprite, + hexInnerSize * 2, // width + hexInnerSize * Math.sqrt(3) // height (hex height) + ); + + // Calculate position to center the sprite in the hex + const spriteX = screenX - width / 2; + const spriteY = screenY - height / 2; + + // Save context state + ctx.save(); + + // Optional: add a small bounce effect when moving + if (this.target) { + const bounce = Math.sin(performance.now() / 100) * 2; + ctx.translate(spriteX, spriteY + bounce); + } else { + ctx.translate(spriteX, spriteY); + } + + // Draw the sprite + ctx.drawImage( + currentSprite, + 0, 0, + width, + height + ); + + // Restore context state + ctx.restore(); + + // Debug: draw hex bounds if debug is enabled + if (Debug.isEnabled) { + ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)'; + ctx.beginPath(); + HexGrid.drawHexPath(ctx, screenX, screenY, HEX_SIZE * 0.8); + ctx.stroke(); + } + } else { + // Fallback to circle if sprites aren't loaded + ctx.fillStyle = Config.colors.PLAYER; + ctx.beginPath(); + ctx.arc(screenX, screenY, HEX_SIZE * Config.player.SIZE_RATIO, 0, Math.PI * 2); + ctx.fill(); + } // Draw path if needed if (this.path.length > 0) { - ctx.strokeStyle = Config.colors.PLAYER + '4D'; // 30% opacity version of player color + ctx.strokeStyle = Config.colors.PLAYER + '4D'; ctx.beginPath(); let lastPos = this.target || this.position; this.path.forEach(point => { |