about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--html/voxels/index.html22
-rw-r--r--html/voxels/js/game.js233
2 files changed, 255 insertions, 0 deletions
diff --git a/html/voxels/index.html b/html/voxels/index.html
new file mode 100644
index 0000000..4f60ff2
--- /dev/null
+++ b/html/voxels/index.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Isometric Game</title>
+    <style>
+        body {
+            margin: 0;
+            overflow: hidden;
+        }
+        canvas {
+            display: block;
+            width: 100vw;
+            height: 100vh;
+            background: #f0f0f0;
+        }
+    </style>
+</head>
+<body>
+    <canvas id="gameCanvas"></canvas>
+    <script src="js/game.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/html/voxels/js/game.js b/html/voxels/js/game.js
new file mode 100644
index 0000000..98d3476
--- /dev/null
+++ b/html/voxels/js/game.js
@@ -0,0 +1,233 @@
+class IsometricGame {
+    constructor() {
+        this.canvas = document.getElementById('gameCanvas');
+        this.ctx = this.canvas.getContext('2d');
+        
+        // Grid properties
+        this.gridSize = 10;
+        this.tileWidth = 50;
+        this.tileHeight = 25;
+        
+        // Player properties
+        this.player = {
+            x: 0,
+            y: 0,
+            targetX: 0,
+            targetY: 0,
+            size: 20,
+            path: [], // Array to store waypoints
+            currentWaypoint: null
+        };
+        
+        // Handle window resize
+        this.resizeCanvas();
+        window.addEventListener('resize', () => this.resizeCanvas());
+        
+        this.setupEventListeners();
+        this.gameLoop();
+    }
+    
+    resizeCanvas() {
+        this.canvas.width = window.innerWidth;
+        this.canvas.height = window.innerHeight;
+        
+        // Recalculate grid offset to center it
+        this.offsetX = this.canvas.width / 2;
+        this.offsetY = this.canvas.height / 3;
+        
+        // Scale tile size based on screen size
+        const minDimension = Math.min(this.canvas.width, this.canvas.height);
+        const scaleFactor = minDimension / 800; // 800 is our reference size
+        this.tileWidth = 50 * scaleFactor;
+        this.tileHeight = 25 * scaleFactor;
+        this.player.size = 20 * scaleFactor;
+    }
+    
+    toIsometric(x, y) {
+        return {
+            x: (x - y) * this.tileWidth / 2,
+            y: (x + y) * this.tileHeight / 2
+        };
+    }
+    
+    fromIsometric(screenX, screenY) {
+        // Convert screen coordinates back to grid coordinates
+        screenX -= this.offsetX;
+        screenY -= this.offsetY;
+        
+        const x = (screenX / this.tileWidth + screenY / this.tileHeight) / 1;
+        const y = (screenY / this.tileHeight - screenX / this.tileWidth) / 1;
+        
+        return { x: Math.round(x), y: Math.round(y) };
+    }
+    
+    drawGrid() {
+        for (let x = 0; x < this.gridSize; x++) {
+            for (let y = 0; y < this.gridSize; y++) {
+                const iso = this.toIsometric(x, y);
+                
+                // Draw tile
+                this.ctx.beginPath();
+                this.ctx.moveTo(iso.x + this.offsetX, iso.y + this.offsetY - this.tileHeight/2);
+                this.ctx.lineTo(iso.x + this.offsetX + this.tileWidth/2, iso.y + this.offsetY);
+                this.ctx.lineTo(iso.x + this.offsetX, iso.y + this.offsetY + this.tileHeight/2);
+                this.ctx.lineTo(iso.x + this.offsetX - this.tileWidth/2, iso.y + this.offsetY);
+                this.ctx.closePath();
+                
+                this.ctx.strokeStyle = '#666';
+                this.ctx.stroke();
+                this.ctx.fillStyle = '#fff';
+                this.ctx.fill();
+            }
+        }
+    }
+    
+    drawPlayer() {
+        // Convert player grid position to isometric coordinates
+        const iso = this.toIsometric(this.player.x, this.player.y);
+        
+        // Draw player shadow (slightly offset and darker)
+        this.ctx.beginPath();
+        this.ctx.ellipse(
+            iso.x + this.offsetX,
+            iso.y + this.offsetY + 2,
+            this.player.size * 0.8,
+            this.player.size * 0.3,
+            0,
+            0,
+            Math.PI * 2
+        );
+        this.ctx.fillStyle = 'rgba(0,0,0,0.2)';
+        this.ctx.fill();
+
+        // Draw player "body" (rectangle)
+        this.ctx.beginPath();
+        this.ctx.fillStyle = '#ff4444';
+        this.ctx.strokeStyle = '#aa0000';
+        
+        // Draw a thin rectangle for the body
+        const bodyHeight = this.player.size * 2;
+        const bodyWidth = this.player.size * 0.8;
+        
+        this.ctx.save();
+        this.ctx.translate(iso.x + this.offsetX, iso.y + this.offsetY);
+        this.ctx.scale(1, 0.5); // Apply isometric perspective
+        this.ctx.fillRect(-bodyWidth/2, -bodyHeight, bodyWidth, bodyHeight);
+        this.ctx.strokeRect(-bodyWidth/2, -bodyHeight, bodyWidth, bodyHeight);
+        this.ctx.restore();
+
+        // Draw player head (circle)
+        this.ctx.beginPath();
+        this.ctx.ellipse(
+            iso.x + this.offsetX,
+            iso.y + this.offsetY - this.player.size,
+            this.player.size,
+            this.player.size * 0.5,
+            0,
+            0,
+            Math.PI * 2
+        );
+        this.ctx.fillStyle = '#ff4444';
+        this.ctx.fill();
+        this.ctx.strokeStyle = '#aa0000';
+        this.ctx.stroke();
+    }
+    
+    findPath(startX, startY, endX, endY) {
+        // Simple pathfinding that follows grid edges
+        const path = [];
+        
+        // First move along X axis
+        if (startX !== endX) {
+            const stepX = startX < endX ? 1 : -1;
+            for (let x = startX + stepX; stepX > 0 ? x <= endX : x >= endX; x += stepX) {
+                path.push({ x: x, y: startY });
+            }
+        }
+        
+        // Then move along Y axis
+        if (startY !== endY) {
+            const stepY = startY < endY ? 1 : -1;
+            for (let y = startY + stepY; stepY > 0 ? y <= endY : y >= endY; y += stepY) {
+                path.push({ x: endX, y: y });
+            }
+        }
+
+        return path;
+    }
+    
+    updatePlayer() {
+        const speed = 0.1;
+
+        // If we don't have a current waypoint but have a path, get next waypoint
+        if (!this.player.currentWaypoint && this.player.path.length > 0) {
+            this.player.currentWaypoint = this.player.path.shift();
+        }
+
+        // Move towards current waypoint
+        if (this.player.currentWaypoint) {
+            const dx = this.player.currentWaypoint.x - this.player.x;
+            const dy = this.player.currentWaypoint.y - this.player.y;
+            
+            // Move towards waypoint
+            this.player.x += dx * speed;
+            this.player.y += dy * speed;
+
+            // Check if we're close enough to waypoint to consider it reached
+            const distance = Math.sqrt(dx * dx + dy * dy);
+            if (distance < 0.1) {
+                this.player.x = this.player.currentWaypoint.x;
+                this.player.y = this.player.currentWaypoint.y;
+                this.player.currentWaypoint = null;
+            }
+        }
+    }
+    
+    setupEventListeners() {
+        this.canvas.addEventListener('click', (e) => {
+            const rect = this.canvas.getBoundingClientRect();
+            const clickX = e.clientX - rect.left;
+            const clickY = e.clientY - rect.top;
+            
+            const gridPos = this.fromIsometric(clickX, clickY);
+            
+            // Only move if within grid bounds
+            if (gridPos.x >= 0 && gridPos.x < this.gridSize &&
+                gridPos.y >= 0 && gridPos.y < this.gridSize) {
+                
+                // Set target and calculate path
+                this.player.targetX = Math.round(gridPos.x);
+                this.player.targetY = Math.round(gridPos.y);
+                
+                // Calculate new path
+                this.player.path = this.findPath(
+                    Math.round(this.player.x),
+                    Math.round(this.player.y),
+                    this.player.targetX,
+                    this.player.targetY
+                );
+                
+                // Clear current waypoint to start new path
+                this.player.currentWaypoint = null;
+            }
+        });
+    }
+    
+    gameLoop() {
+        // Clear canvas
+        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+        
+        // Draw game elements
+        this.drawGrid();
+        this.updatePlayer();
+        this.drawPlayer();
+        
+        // Continue game loop
+        requestAnimationFrame(() => this.gameLoop());
+    }
+}
+
+// Start the game when the page loads
+window.onload = () => {
+    new IsometricGame();
+};
\ No newline at end of file