Code edit (3 edits merged)
Please save this source code
Code edit (9 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: isDragging is not defined' in or related to this line: 'if (!isDragging) {' Line Number: 405
Code edit (3 edits merged)
Please save this source code
User prompt
before creating the screen, ask the player if they want low or high resolution.
User prompt
Optimize this
Code edit (1 edits merged)
Please save this source code
User prompt
flip the y axis control when upside down
User prompt
flip the y axis control when upside down
Code edit (1 edits merged)
Please save this source code
User prompt
Draw lines on each edges
/**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0 }); /**** * Game Code ****/ // Game constants for the screen var SELECTED_RESOLUTION = null; var resolutionSelected = false; // Cache children array reference var screen = game.children; // Pre-allocate reusable arrays to avoid garbage collection var tempRotatedTriangle = [0, 0, 0, 0, 0, 0, 0, 0, 0]; var tempCenteredTriangle = [0, 0, 0, 0, 0, 0, 0, 0, 0]; var tempProjectedTriangle = [0, 0, 0, 0, 0, 0]; var tempVertex1 = [0, 0, 0]; var tempVertex2 = [0, 0, 0]; var tempVertex3 = [0, 0, 0]; // Optimized screen clearing - only clear visible pixels var visiblePixels = []; function clearScreen() { var len = visiblePixels.length; for (var i = 0; i < len; i++) { visiblePixels[i].tint = 0; } visiblePixels.length = 0; } function putPixel(x, y, color) { if (x >= 0 && x < SCREEN_SIZE && y >= 0 && y < SCREEN_SIZE) { var pixel = screen[x + y * SCREEN_SIZE]; pixel.tint = color; visiblePixels.push(pixel); } } // Line drawing function using Bresenham's line algorithm function drawLine(x0, y0, x1, y1, color) { var dx = x1 - x0; var dy = y1 - y0; var adx = dx < 0 ? -dx : dx; var ady = dy < 0 ? -dy : dy; var sx = dx < 0 ? -1 : 1; var sy = dy < 0 ? -1 : 1; var err = adx - ady; var x = x0; var y = y0; while (true) { putPixel(x, y, color); if (x === x1 && y === y1) { break; } var e2 = 2 * err; if (e2 > -ady) { err -= ady; x += sx; } if (e2 < adx) { err += adx; y += sy; } } } function drawTriangle(triangle, color, wireframe) { if (wireframe === undefined) { wireframe = false; } // Extract triangle vertices var x1 = triangle[0]; var y1 = triangle[1]; var x2 = triangle[2]; var y2 = triangle[3]; var x3 = triangle[4]; var y3 = triangle[5]; // Draw the three sides of the triangle only if wireframe is true if (wireframe) { drawLine(x1, y1, x2, y2, color); // Side 1-2 drawLine(x2, y2, x3, y3, color); // Side 2-3 drawLine(x3, y3, x1, y1, color); // Side 3-1 } else { // Helper to interpolate x between two points at a given y // Sort vertices by y (ascending) - reuse pre-allocated array if (!drawTriangle.verts) { drawTriangle.verts = [{ x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }]; } var verts = drawTriangle.verts; verts[0].x = x1; verts[0].y = y1; verts[1].x = x2; verts[1].y = y2; verts[2].x = x3; verts[2].y = y3; var interpX = function interpX(y, x0, y0, x1, y1) { if (y1 === y0) { return x0; } return x0 + (x1 - x0) * (y - y0) / (y1 - y0); }; // Fill bottom flat triangle (v0, v1, v2) if v1.y != v0.y verts.sort(function (a, b) { return a.y - b.y; }); var v0 = verts[0]; var v1 = verts[1]; var v2 = verts[2]; if (v1.y !== v0.y) { var yStart = Math.ceil(v0.y); var yEnd = Math.ceil(v1.y); for (var y = yStart; y < yEnd; y++) { var xA = interpX(y, v0.x, v0.y, v2.x, v2.y); var xB = interpX(y, v0.x, v0.y, v1.x, v1.y); var xStart = xA < xB ? Math.ceil(xA) : Math.ceil(xB); var xEnd = xA > xB ? Math.floor(xA) : Math.floor(xB); for (var x = xStart; x <= xEnd; x++) { putPixel(x, y, color); } } } // Fill top flat triangle (v1, v2, v0) if v2.y != v1.y if (v2.y !== v1.y) { var yStart = Math.ceil(v1.y); var yEnd = Math.ceil(v2.y); for (var y = yStart; y < yEnd; y++) { var xA = interpX(y, v0.x, v0.y, v2.x, v2.y); var xB = interpX(y, v1.x, v1.y, v2.x, v2.y); var xStart = xA < xB ? Math.ceil(xA) : Math.ceil(xB); var xEnd = xA > xB ? Math.floor(xA) : Math.floor(xB); for (var x = xStart; x <= xEnd; x++) { putPixel(x, y, color); } } } } } var colorIndex = 0; // Resolution selection UI var resolutionTitle = new Text2('Choose Resolution', { size: 120, fill: 0xFFFFFF }); resolutionTitle.anchor.set(0.5, 0.5); resolutionTitle.x = 2048 / 2; resolutionTitle.y = 2732 / 2 - 300; game.addChild(resolutionTitle); var lowResText = new Text2('Low Resolution (64x64)', { size: 80, fill: 0x00FF00 }); lowResText.anchor.set(0.5, 0.5); lowResText.x = 2048 / 2; lowResText.y = 2732 / 2 - 100; game.addChild(lowResText); var highResText = new Text2('High Resolution (96x96)', { size: 80, fill: 0x0066FF }); highResText.anchor.set(0.5, 0.5); highResText.x = 2048 / 2; highResText.y = 2732 / 2 + 100; game.addChild(highResText); // Add touch handlers for resolution selection lowResText.down = function (x, y, obj) { SELECTED_RESOLUTION = 'low'; SCREEN_SIZE = 64; PIXEL_SIZE = 2048 / SCREEN_SIZE; var offset = 2732 / 2 - SCREEN_SIZE * PIXEL_SIZE / 2; resolutionSelected = true; // Remove UI elements game.removeChild(resolutionTitle); game.removeChild(lowResText); game.removeChild(highResText); // Create the screen of pixels for (var y = 0; y < SCREEN_SIZE; y++) { for (var x = 0; x < SCREEN_SIZE; x++) { // Get an instance of our pixel asset var pixel = LK.getAsset('pixel', { x: x * PIXEL_SIZE, y: y * PIXEL_SIZE + offset, tint: 0 }); game.addChild(pixel); } } }; highResText.down = function (x, y, obj) { SELECTED_RESOLUTION = 'high'; SCREEN_SIZE = 96; PIXEL_SIZE = 2048 / SCREEN_SIZE; var offset = 2732 / 2 - SCREEN_SIZE * PIXEL_SIZE / 2; resolutionSelected = true; // Remove UI elements game.removeChild(resolutionTitle); game.removeChild(lowResText); game.removeChild(highResText); // Create the screen of pixels using high res asset for (var y = 0; y < SCREEN_SIZE; y++) { for (var x = 0; x < SCREEN_SIZE; x++) { // Get an instance of our pixel asset var pixel = LK.getAsset('pixelHighRes', { x: x * PIXEL_SIZE, y: y * PIXEL_SIZE + offset, tint: 0 }); game.addChild(pixel); } } }; function translateTriangle(triangle, dx, dy, dz, result) { // triangle: [x1, y1, z1, x2, y2, z2, x3, y3, z3] // Translate each vertex by dx, dy, dz - use provided result array for (var i = 0; i < 9; i += 3) { result[i] = triangle[i] + dx; result[i + 1] = triangle[i + 1] + dy; result[i + 2] = triangle[i + 2] + dz; } return result; } function rotateTriangle(triangle, angleX, angleY, angleZ, result) { // triangle: [x1, y1, z1, x2, y2, z2, x3, y3, z3] // angleX, angleY, angleZ in radians // Precompute sines and cosines var cosX = Math.cos(angleX), sinX = Math.sin(angleX); var cosY = Math.cos(angleY), sinY = Math.sin(angleY); var cosZ = Math.cos(angleZ), sinZ = Math.sin(angleZ); // Inline rotation for better performance - rotate each vertex directly for (var i = 0; i < 9; i += 3) { var x = triangle[i]; var y = triangle[i + 1]; var z = triangle[i + 2]; // Rotate around Y axis (Yaw) var x1 = x * cosY + z * sinY; var z1 = -x * sinY + z * cosY; // Rotate around X axis (Pitch) var y2 = y * cosX - z1 * sinX; var z2 = y * sinX + z1 * cosX; // Rotate around Z axis (Roll) var x3 = x1 * cosZ - y2 * sinZ; var y3 = x1 * sinZ + y2 * cosZ; result[i] = x3; result[i + 1] = y3; result[i + 2] = z2; } return result; } function projectTriangle(triangle, result) { // triangle: [x1, y1, z1, x2, y2, z2, x3, y3, z3] // Perspective projection parameters var fov = 80; // Focal length (distance from camera to projection plane) var cx = SCREEN_SIZE / 2; var cy = SCREEN_SIZE / 2; // Inline projection for better performance for (var i = 0; i < 9; i += 3) { var x = triangle[i]; var y = triangle[i + 1]; var z = triangle[i + 2]; // Avoid division by zero var zz = z === 0 ? 0.0001 : z; var projIdx = i / 3 * 2; result[projIdx] = Math.round(cx + (x - cx) * (fov / (fov + zz))); result[projIdx + 1] = Math.round(cy + (y - cy) * (fov / (fov + zz))); } return result; } function shadeTriangleColor(triangle, baseColor) { // Calculate face normal in view space (after rotation, before projection) // Get the three vertices in view space var v1 = triangle.slice(0, 3); var v2 = triangle.slice(3, 6); var v3 = triangle.slice(6, 9); // Compute vectors var ax = v2[0] - v1[0], ay = v2[1] - v1[1], az = v2[2] - v1[2]; var bx = v3[0] - v1[0], by = v3[1] - v1[1], bz = v3[2] - v1[2]; // Cross product (normal) var nx = ay * bz - az * by; var ny = az * bx - ax * bz; var nz = ax * by - ay * bx; // Normalize normal var nlen = Math.sqrt(nx * nx + ny * ny + nz * nz); if (nlen > 0) { nx /= nlen; ny /= nlen; nz /= nlen; } // Camera looks down -Z, so light direction is (0,0,-1) var dot = nz; // dot(normal, [0,0,-1]) = nz // Clamp dot to [0,1] for brightness (facing camera = 1, edge = 0) var brightness = dot + 0.25; if (brightness < 0) { brightness = 0; } if (brightness > 1) { brightness = 1; } // Darken color by brightness (simple shading) var r = (baseColor >> 16 & 0xFF) * brightness; var g = (baseColor >> 8 & 0xFF) * brightness; var b = (baseColor & 0xFF) * brightness; return Math.round(r) << 16 | Math.round(g) << 8 | Math.round(b); } function isBackfacing(projectedTriangle) { // Check winding order using cross product of projected triangle // projectedTriangle: [x1, y1, x2, y2, x3, y3] var x1 = projectedTriangle[0]; var y1 = projectedTriangle[1]; var x2 = projectedTriangle[2]; var y2 = projectedTriangle[3]; var x3 = projectedTriangle[4]; var y3 = projectedTriangle[5]; // Calculate cross product to determine winding order var crossProduct = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1); // If cross product is negative, triangle is clockwise (backfacing) return crossProduct < 0; } // Drag variables var isDragging = false; var dragStartX = 0; var dragStartY = 0; var dragStartAngleX = 0; var dragStartAngleY = 0; var angleX = Math.PI / 4; var angleY = Math.PI / 4; var momentumX = 0; var momentumY = 0; var lastAngleX = 0; var lastAngleY = 0; // Initialize cube rendering after resolution is selected function initializeCubeRendering() { // Touch/mouse down: start drag game.down = function (x, y, obj) { if (!resolutionSelected) { return; } dragStartX = x; dragStartAngleY = angleY; dragStartY = y; dragStartAngleX = angleX; isDragging = true; }; // Touch/mouse up: end drag game.up = function (x, y, obj) { if (!resolutionSelected) { return; } isDragging = false; }; // Touch/mouse move: update angles if dragging game.move = function (x, y, obj) { if (!resolutionSelected) { return; } if (isDragging) { // Horizontal drag for Y-axis rotation var dx = x - dragStartX; angleY = dragStartAngleY - dx / 2048 * (2 * Math.PI); // Vertical drag for X-axis rotation var dy = y - dragStartY; angleX = dragStartAngleX + dy / 2732 * (2 * Math.PI); } }; game.update = function () { if (!resolutionSelected) { return; } // Center the cube by translating to the middle of the screen var centerX = SCREEN_SIZE / 2; var centerY = SCREEN_SIZE / 2; var centerZ = 16; // Move slightly back for better perspective if (SELECTED_RESOLUTION == 'high') { var triangles = [[-24, -24, -24, 24, -24, -24, -24, 24, -24], [-24, 24, -24, 24, -24, -24, 24, 24, -24], [24, -24, -24, 24, -24, 24, 24, 24, -24], [24, 24, -24, 24, -24, 24, 24, 24, 24], [-24, -24, 24, -24, 24, 24, 24, -24, 24], [-24, 24, 24, 24, 24, 24, 24, -24, 24], [-24, -24, 24, -24, -24, -24, -24, 24, 24], [-24, 24, 24, -24, -24, -24, -24, 24, -24], [24, -24, 24, 24, -24, -24, -24, -24, -24], [-24, -24, -24, -24, -24, 24, 24, -24, 24], [-24, 24, -24, 24, 24, 24, -24, 24, 24], [24, 24, 24, -24, 24, -24, 24, 24, -24]]; } else { var triangles = [[-16, -16, -16, 16, -16, -16, -16, 16, -16], [-16, 16, -16, 16, -16, -16, 16, 16, -16], [16, -16, -16, 16, -16, 16, 16, 16, -16], [16, 16, -16, 16, -16, 16, 16, 16, 16], [-16, -16, 16, -16, 16, 16, 16, -16, 16], [-16, 16, 16, 16, 16, 16, 16, -16, 16], [-16, -16, 16, -16, -16, -16, -16, 16, 16], [-16, 16, 16, -16, -16, -16, -16, 16, -16], [16, -16, 16, 16, -16, -16, -16, -16, -16], [-16, -16, -16, -16, -16, 16, 16, -16, 16], [-16, 16, -16, 16, 16, 16, -16, 16, 16], [16, 16, 16, -16, 16, -16, 16, 16, -16]]; } var COLOR_ARRAY = [0xFF0000, // Red 0xFF7F00, // Orange 0xFFFF00, // Yellow 0x00FF00, // Green 0x0000FF, // Blue 0x4B0082 // Indigo ]; // If not dragging, apply momentum to angles if (!isDragging) { angleX += momentumX; angleY += momentumY; // Apply friction to slow down over time momentumX *= 0.96; momentumY *= 0.96; // Clamp very small values to zero to avoid drift if (Math.abs(momentumX) < 0.00001) { momentumX = 0; } if (Math.abs(momentumY) < 0.00001) { momentumY = 0; } } //Start of the 3d renderer clearScreen(); for (var i = 0; i < triangles.length; i++) { var triangle = triangles[i]; rotateTriangle(triangle, angleX, angleY, 0, tempRotatedTriangle); translateTriangle(tempRotatedTriangle, centerX, centerY, centerZ, tempCenteredTriangle); projectTriangle(tempCenteredTriangle, tempProjectedTriangle); // Only draw triangle if it's not backfacing if (!isBackfacing(tempProjectedTriangle)) { var shadedColor = shadeTriangleColor(tempRotatedTriangle, COLOR_ARRAY[Math.floor(i / 2)]); drawTriangle(tempProjectedTriangle, shadedColor); drawTriangle(tempProjectedTriangle, 0, true); } } // Update momentum based on last frame's angle change if (isDragging) { var deltaX = angleX - lastAngleX; var deltaY = angleY - lastAngleY; // Smooth momentum using an exponential moving average for a more natural feel. momentumX = momentumX * 0.5 + deltaX * 0.5; momentumY = momentumY * 0.5 + deltaY * 0.5; } lastAngleX = angleX; lastAngleY = angleY; }; } // Initialize cube rendering immediately initializeCubeRendering();
===================================================================
--- original.js
+++ change.js
@@ -380,10 +380,10 @@
}
// Center the cube by translating to the middle of the screen
var centerX = SCREEN_SIZE / 2;
var centerY = SCREEN_SIZE / 2;
- var centerZ = 8; // Move slightly back for better perspective
- if (resolutionSelected == 'high') {
+ var centerZ = 16; // Move slightly back for better perspective
+ if (SELECTED_RESOLUTION == 'high') {
var triangles = [[-24, -24, -24, 24, -24, -24, -24, 24, -24], [-24, 24, -24, 24, -24, -24, 24, 24, -24], [24, -24, -24, 24, -24, 24, 24, 24, -24], [24, 24, -24, 24, -24, 24, 24, 24, 24], [-24, -24, 24, -24, 24, 24, 24, -24, 24], [-24, 24, 24, 24, 24, 24, 24, -24, 24], [-24, -24, 24, -24, -24, -24, -24, 24, 24], [-24, 24, 24, -24, -24, -24, -24, 24, -24], [24, -24, 24, 24, -24, -24, -24, -24, -24], [-24, -24, -24, -24, -24, 24, 24, -24, 24], [-24, 24, -24, 24, 24, 24, -24, 24, 24], [24, 24, 24, -24, 24, -24, 24, 24, -24]];
} else {
var triangles = [[-16, -16, -16, 16, -16, -16, -16, 16, -16], [-16, 16, -16, 16, -16, -16, 16, 16, -16], [16, -16, -16, 16, -16, 16, 16, 16, -16], [16, 16, -16, 16, -16, 16, 16, 16, 16], [-16, -16, 16, -16, 16, 16, 16, -16, 16], [-16, 16, 16, 16, 16, 16, 16, -16, 16], [-16, -16, 16, -16, -16, -16, -16, 16, 16], [-16, 16, 16, -16, -16, -16, -16, 16, -16], [16, -16, 16, 16, -16, -16, -16, -16, -16], [-16, -16, -16, -16, -16, 16, 16, -16, 16], [-16, 16, -16, 16, 16, 16, -16, 16, 16], [16, 16, 16, -16, 16, -16, 16, 16, -16]];
}