User prompt
create a new Face class equivalent to the SimpleFace but with a customizable number of points (min=2; max =10)
Code edit (2 edits merged)
Please save this source code
User prompt
Create a new Sphere class equivalent to the Cube class
Code edit (1 edits merged)
Please save this source code
Initial prompt
Copy 3d Cube Demo
/**** * Classes ****/ /***********************************************************************************/ /********************************** CUBE CLASS ************************************/ /***********************************************************************************/ var Cube = Container.expand(function () { var self = Container.call(this); self.z = 0; self.baseSize = 100; // Initialize cube faces using SimpleFace class self.frontFace = new SimpleFace({ w: self.baseSize, h: self.baseSize, d: self.baseSize, dx: 0, dy: 0, dz: 1, rx: 0, ry: 0, rz: 0, ti: 0xFFFFFF }); self.backFace = new SimpleFace({ w: self.baseSize, h: self.baseSize, d: self.baseSize, dx: 0, dy: 0, dz: -1, rx: Math.PI, ry: 0, rz: 0, ti: 0xFFFFFF }); self.leftFace = new SimpleFace({ w: self.baseSize, h: self.baseSize, d: self.baseSize, dx: -1, dy: 0, dz: 0, rx: 0, ry: Math.PI / 2, rz: 0, ti: 0xFFFFFF }); self.rightFace = new SimpleFace({ w: self.baseSize, h: self.baseSize, d: self.baseSize, dx: 1, dy: 0, dz: 0, rx: 0, ry: -Math.PI * 0.5, rz: 0, ti: 0xFFFFFF }); self.topFace = new SimpleFace({ w: self.baseSize, h: self.baseSize, d: self.baseSize, dx: 0, dy: -1, dz: 0, rx: -Math.PI / 2, ry: 0, rz: 0, ti: 0xFFFFFF }); self.bottomFace = new SimpleFace({ w: self.baseSize, h: self.baseSize, d: self.baseSize, dx: 0, dy: 1, dz: 0, rx: Math.PI / 2, ry: 0, rz: 0, ti: 0xFFFFFF }); self.faces = [self.frontFace, self.backFace, self.leftFace, self.rightFace, self.topFace, self.bottomFace]; self.faces.forEach(function (face) { self.addChild(face); }); self.speedX = 5; self.speedY = 5; self.speedZ = 5; // Rotate cube around its axes self.rotate3D = function (angleX, angleY, angleZ) { log("cube rotate3D "); self.rotation = angleZ; var zScaleFactor = 1 + self.z / 500; self.faces.forEach(function (face) { face.rotate3D(angleX, angleY, angleZ, zScaleFactor); }); }; }); /***********************************************************************************/ /********************************** SHAPE CLASS ************************************/ /***********************************************************************************/ var Shape = Container.expand(function (coordinates, tint) { var self = Container.call(this); self.polygon = drawPolygon(coordinates, tint); // Function to create a polygon from a list of coordinates self.tint = tint; self.attachLines = function () { // Iterate through each line in the polygon and attach it to the shape self.polygon.forEach(function (line) { self.addChild(line); }); }; self.attachLines(); self.updateCoordinates = function (newCoordinates) { log("Shape updateCoordinates ", newCoordinates); // Ensure newCoordinates is an array and has the same length as the current polygon if (!Array.isArray(newCoordinates) || newCoordinates.length !== self.polygon.length) { error("Invalid newCoordinates length"); return; } // Update each line in the polygon with new coordinates self.polygon = updatePolygon(self.polygon, newCoordinates); }; }); /***********************************************************************************/ /******************************* SIMPLE FACE CLASS *********************************/ /***********************************************************************************/ var SimpleFace = Container.expand(function (options) { var self = Container.call(this); log("SimpleFAce init options =", options); self.baseSize = 100; options = options || {}; self.w = options.w || self.baseSize; self.h = options.h || self.baseSize; self.d = options.d || self.baseSize, self.dx = options.dx || 0; self.dy = options.dy || 0; self.dz = options.dz || 0; self.rx = options.rx || 0; self.ry = options.ry || 0; self.rz = options.rz || 0; self.tint = options.ti || 0xFFFFFF; // Define faceCoordinates property self.baseFaceCoordinates = [{ x: -self.w + self.dx * self.w, y: -self.h + self.dy * self.h, z: self.dz * self.d }, // Top-left { x: self.w + self.dx * self.w, y: -self.h + self.dy * self.h, z: self.dz * self.d }, // Top-right { x: self.w + self.dx * self.w, y: self.h + self.dy * self.h, z: self.dz * self.d }, // Bottom-right { x: -self.w + self.dx * self.w, y: self.h + self.dy * self.h, z: self.dz * self.d } // Bottom-left ]; log("SimpleFAce ready to init ...", self.baseFaceCoordinates, "DX=" + self.dx); self.baseFaceCoordinates.forEach(function (point) { // Update z of each face point coordinates depending on dz and rx, ry point.z += self.dz * Math.cos(self.rx) * Math.cos(self.ry); }); // Create a square face using the Shape class self.face = new Shape(self.baseFaceCoordinates, self.tint); // Attach the face to the SimpleFace container self.addChild(self.face); // Rotate in 3d : X = roasting chicken / Y = whirling dervish / Z = wheel of Fortune self.rotate3D = function (angleX, angleY, angleZ, scale) { scale = scale || 1; log("SimpleFace rotate3D old coord=", self.faceCoordinates, Date.now()); self.faceCoordinates = self.baseFaceCoordinates.map(function (coord) { return { x: coord.x, y: coord.y, z: coord.z }; }); // Apply rotation around X-axis // Adjust initial rotation parameters before applying new rotations self.faceCoordinates = self.faceCoordinates.map(function (coord) { // Apply initial rotation around Z-axis var xZ = coord.x * Math.cos(self.rz) - coord.y * Math.sin(self.rz); var yZ = coord.x * Math.sin(self.rz) + coord.y * Math.cos(self.rz); // Apply initial rotation around Y-axis var xY = xZ * Math.cos(self.ry) + coord.z * Math.sin(self.ry); var zY = coord.z * Math.cos(self.ry) - xZ * Math.sin(self.ry); // Apply initial rotation around X-axis var yX = yZ * Math.cos(self.rx) - zY * Math.sin(self.rx); var zX = yZ * Math.sin(self.rx) + zY * Math.cos(self.rx); return { x: xY, y: yX, z: zX }; }); // Apply new rotations // Calculate center of the face var centerX = self.faceCoordinates.reduce(function (acc, coord) { return acc + coord.x; }, 0) / self.faceCoordinates.length; var centerY = self.faceCoordinates.reduce(function (acc, coord) { return acc + coord.y; }, 0) / self.faceCoordinates.length; var centerZ = self.faceCoordinates.reduce(function (acc, coord) { return acc + coord.z; }, 0) / self.faceCoordinates.length; self.faceCoordinates = self.faceCoordinates.map(function (coord) { // Translate coordinates to rotate around the center including dy and dz adjustment var translatedY = (coord.y + self.dy * self.h - centerY) * Math.cos(angleX) - (coord.z + self.dz * self.d - centerZ) * Math.sin(angleX); var translatedZ = (coord.y + self.dy * self.h - centerY) * Math.sin(angleX) + (coord.z + self.dz * self.d - centerZ) * Math.cos(angleX); return { x: coord.x + self.dx * self.w - centerX, // Keep X unchanged but translate to rotate around center y: translatedY + centerY, z: translatedZ + centerZ }; }); self.faceCoordinates = self.faceCoordinates.map(function (coord) { var translatedX = (coord.z - centerZ) * Math.sin(angleY) + (coord.x - centerX) * Math.cos(angleY); var translatedZ = (coord.z - centerZ) * Math.cos(angleY) - (coord.x - centerX) * Math.sin(angleY); return { x: translatedX + centerX, y: coord.y, // Keep Y unchanged z: translatedZ + centerZ }; }); self.faceCoordinates = self.faceCoordinates.map(function (coord) { return { x: coord.x * scale, y: coord.y * scale, z: coord.z * scale }; }); log("SimpleFace rotate3D new coord=", self.faceCoordinates, Date.now()); self.face.updateCoordinates(self.faceCoordinates); }; // initialize face in 3D space self.rotate3D(0, 0, 0, 1); log("SimpleFace end init coord=", self.baseFaceCoordinates, Date.now()); }); /***********************************************************************************/ /********************************** SPHERE CLASS ***********************************/ /***********************************************************************************/ var Sphere = Container.expand(function () { var self = Container.call(this); self.z = 0; self.radius = 50; // Sphere radius // Initialize sphere as a collection of SimpleFace instances to simulate a 3D sphere self.faces = []; var segments = 12; // Number of segments to simulate the sphere for (var i = 0; i < segments; i++) { var angle = 2 * Math.PI * (i / segments); var dx = Math.cos(angle); var dy = Math.sin(angle); // Create a circular segment as a face of the sphere var face = new SimpleFace({ w: self.radius * 2, // Width of the face, approximating the sphere's circumference segment h: self.radius / 3, // Height of the face, arbitrary for visual effect d: self.radius * 2, // Depth, using width to maintain circular appearance dx: dx, // X offset based on circle calculation dy: dy, // Y offset based on circle calculation dz: 0, // No Z offset for a sphere rx: 0, // Rotation around X-axis ry: 0, // Rotation around Y-axis rz: angle, // Rotation around Z-axis to position the segment correctly ti: 0xFFFFFF // Tint color }); self.faces.push(face); self.addChild(face); } self.speedX = 5; self.speedY = 5; self.speedZ = 5; // Rotate sphere around its axes self.rotate3D = function (angleX, angleY, angleZ) { log("sphere rotate3D "); self.rotation = angleZ; var zScaleFactor = 1 + self.z / 500; self.faces.forEach(function (face) { face.rotate3D(angleX, angleY, angleZ, zScaleFactor); }); }; }); /**** * Initialize Game ****/ // Utility function to draw a polygon using drawLine var game = new LK.Game({ backgroundColor: 0x000050 // Initialize game with a black background }); /**** * Game Code ****/ var fpsText; var lastTick; var frameCount; var debugText; /***********************************************************************************/ /******************************* UTILITY FUNCTIONS *********************************/ /***********************************************************************************/ function drawPolygon(coordinates, tint) { log("drawPolygon ", coordinates); var lines = []; for (var i = 0; i < coordinates.length; i++) { var startPoint = coordinates[i]; var endPoint = coordinates[(i + 1) % coordinates.length]; // Loop back to the first point var line = drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, tint); lines.push(line); } return lines; } function updatePolygon(lines, newCoordinates, scale) { log("updatePolygon ", lines, scale); // Ensure lines and newCoordinates have the same length if (lines.length !== newCoordinates.length) { error("updatePolygon error: lines and newCoordinates length mismatch"); return lines; } // Update each line with new coordinates for (var i = 0; i < lines.length; i++) { var startPoint = newCoordinates[i]; var endPoint = newCoordinates[(i + 1) % newCoordinates.length]; // Loop back to the first point for the last line updateLine(lines[i], startPoint.x, startPoint.y, endPoint.x, endPoint.y, scale); } return lines; } // Utility function to draw lines between two points function drawLine(x1, y1, x2, y2, tint) { log("drawLine ", x1, y1); var line = LK.getAsset('line', { anchorX: 0.0, anchorY: 0.0, x: x1, y: y1, tint: tint }); line.startX = x1; line.startY = y1; line.endX = x2; line.endY = y2; // Calculate the distance between the two points var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); // Set the width of the line to the distance between the points line.width = distance; // Calculate the angle between the two points var angle = Math.atan2(y2 - y1, x2 - x1); // Correct angle calculation for all quadrants line.rotation = angle; return line; } // Utility function to draw lines between two points function updateLine(line, newX1, newY1, newX2, newY2, scale) { log("updateLine ", line); scale = scale === undefined ? 1 : scale; // Calculate midpoint of the original line var midX = (newX1 + newX2) / 2; var midY = (newY1 + newY2) / 2; // Adjust start and end points based on scale newX1 = midX + (newX1 - midX) * scale; newY1 = midY + (newY1 - midY) * scale; newX2 = midX + (newX2 - midX) * scale; newY2 = midY + (newY2 - midY) * scale; // Update line start and end coordinates after scaling line.x = newX1; line.y = newY1; line.startX = newX1; line.startY = newY1; line.endX = newX2; line.endY = newY2; // Recalculate the distance between the new scaled points var distance = Math.sqrt(Math.pow(newX2 - newX1, 2) + Math.pow(newY2 - newY1, 2)); // Update the width of the line to the new distance line.width = distance; // Recalculate the angle between the new points var angle = Math.atan2(newY2 - newY1, newX2 - newX1); // Update the rotation of the line to the new angle line.rotation = angle; return line; } function log() { if (isDebug) { console.log(arguments); } } /***********************************************************************************/ /******************************* GAME VARIABLES*********************************/ /***********************************************************************************/ var cube; var simpleFace; var simpleFace2; var simpleFace3; var rotationSpeedX = 0; var rotationSpeedY = 0; var rotationSpeedZ = 0; var isDebug = false; var fullLog = []; /***********************************************************************************/ /***************************** GAME INITIALIZATION *********************************/ /***********************************************************************************/ function gameInitialize() { cube = new Cube(); cube.x = 2048 * 0.25; // Center horizontally cube.y = 2732 / 2; // Center vertically cube.z = 0; game.addChild(cube); if (isDebug) { var debugMarker = LK.getAsset('debugMarker', { anchorX: 0.5, anchorY: 0.5, x: 2048 * 0.5, y: 2732 / 2 }); game.addChild(debugMarker); fpsText = new Text2('FPS: 0', { size: 50, fill: "#ffffff" }); // Position FPS text at the bottom-right corner fpsText.anchor.set(1, 1); // Anchor to the bottom-right LK.gui.bottomRight.addChild(fpsText); // Update FPS display every second lastTick = Date.now(); frameCount = 0; // Debug text to display cube information debugText = new Text2('Debug Info', { size: 50, fill: "#ffffff" }); debugText.anchor.set(0.5, 0); // Anchor to the bottom-right LK.gui.top.addChild(debugText); } } /***********************************************************************************/ /******************************** MAIN GAME LOOP ***********************************/ /***********************************************************************************/ game.update = function () { // Rotate simpleFace in 3D on each game update rotationSpeedX += 1 * Math.PI * 0.125 * 0.02; rotationSpeedY += 1 * Math.PI * 0.125 * 0.02; rotationSpeedZ += 1 * Math.PI * 0.125 * 0.02; // Update cube position with movement speed cube.x += cube.speedX; cube.y += cube.speedY; cube.z += cube.speedZ; // Check for cube bouncing on horizontal borders if (cube.x <= 100 || cube.x >= 2048 - 100) { cube.speedX *= -1; // Reverse horizontal direction } // Check for cube bouncing on Z dimension boundaries if (cube.z <= -250 || cube.z >= 1000) { // Assuming -500 and 500 as Z dimension boundaries cube.speedZ *= -1; // Reverse Z dimension direction } // Check for cube bouncing on vertical borders if (cube.y <= 100 || cube.y >= 2732 - 100) { cube.speedY *= -1; // Reverse vertical direction } // Rotating the cube cube.rotate3D(rotationSpeedX, rotationSpeedY, rotationSpeedZ); if (isDebug) { debugText.setText("X: " + Math.round(cube.x) + ", Y: " + Math.round(cube.y) + ", Z: " + Math.round(cube.z) + ", R: " + cube.rotation.toFixed(2)); // FPS var now = Date.now(); frameCount++; if (now - lastTick >= 1000) { // Update every second fpsText.setText('FPS: ' + frameCount); frameCount = 0; lastTick = now; } } }; gameInitialize(); // Initialize the game
===================================================================
--- original.js
+++ change.js
@@ -248,8 +248,60 @@
// initialize face in 3D space
self.rotate3D(0, 0, 0, 1);
log("SimpleFace end init coord=", self.baseFaceCoordinates, Date.now());
});
+/***********************************************************************************/
+/********************************** SPHERE CLASS ***********************************/
+/***********************************************************************************/
+var Sphere = Container.expand(function () {
+ var self = Container.call(this);
+ self.z = 0;
+ self.radius = 50; // Sphere radius
+ // Initialize sphere as a collection of SimpleFace instances to simulate a 3D sphere
+ self.faces = [];
+ var segments = 12; // Number of segments to simulate the sphere
+ for (var i = 0; i < segments; i++) {
+ var angle = 2 * Math.PI * (i / segments);
+ var dx = Math.cos(angle);
+ var dy = Math.sin(angle);
+ // Create a circular segment as a face of the sphere
+ var face = new SimpleFace({
+ w: self.radius * 2,
+ // Width of the face, approximating the sphere's circumference segment
+ h: self.radius / 3,
+ // Height of the face, arbitrary for visual effect
+ d: self.radius * 2,
+ // Depth, using width to maintain circular appearance
+ dx: dx,
+ // X offset based on circle calculation
+ dy: dy,
+ // Y offset based on circle calculation
+ dz: 0,
+ // No Z offset for a sphere
+ rx: 0,
+ // Rotation around X-axis
+ ry: 0,
+ // Rotation around Y-axis
+ rz: angle,
+ // Rotation around Z-axis to position the segment correctly
+ ti: 0xFFFFFF // Tint color
+ });
+ self.faces.push(face);
+ self.addChild(face);
+ }
+ self.speedX = 5;
+ self.speedY = 5;
+ self.speedZ = 5;
+ // Rotate sphere around its axes
+ self.rotate3D = function (angleX, angleY, angleZ) {
+ log("sphere rotate3D ");
+ self.rotation = angleZ;
+ var zScaleFactor = 1 + self.z / 500;
+ self.faces.forEach(function (face) {
+ face.rotate3D(angleX, angleY, angleZ, zScaleFactor);
+ });
+ };
+});
/****
* Initialize Game
****/
@@ -403,8 +455,31 @@
/***********************************************************************************/
/******************************** MAIN GAME LOOP ***********************************/
/***********************************************************************************/
game.update = function () {
+ // Rotate simpleFace in 3D on each game update
+ rotationSpeedX += 1 * Math.PI * 0.125 * 0.02;
+ rotationSpeedY += 1 * Math.PI * 0.125 * 0.02;
+ rotationSpeedZ += 1 * Math.PI * 0.125 * 0.02;
+ // Update cube position with movement speed
+ cube.x += cube.speedX;
+ cube.y += cube.speedY;
+ cube.z += cube.speedZ;
+ // Check for cube bouncing on horizontal borders
+ if (cube.x <= 100 || cube.x >= 2048 - 100) {
+ cube.speedX *= -1; // Reverse horizontal direction
+ }
+ // Check for cube bouncing on Z dimension boundaries
+ if (cube.z <= -250 || cube.z >= 1000) {
+ // Assuming -500 and 500 as Z dimension boundaries
+ cube.speedZ *= -1; // Reverse Z dimension direction
+ }
+ // Check for cube bouncing on vertical borders
+ if (cube.y <= 100 || cube.y >= 2732 - 100) {
+ cube.speedY *= -1; // Reverse vertical direction
+ }
+ // Rotating the cube
+ cube.rotate3D(rotationSpeedX, rotationSpeedY, rotationSpeedZ);
if (isDebug) {
debugText.setText("X: " + Math.round(cube.x) + ", Y: " + Math.round(cube.y) + ", Z: " + Math.round(cube.z) + ", R: " + cube.rotation.toFixed(2));
// FPS
var now = Date.now();
remove background
remove background
Futuristic speaker in the shape of a white orb. Face view
white video camera icon
landscape of a furturistic world by night
a white music note
white sparkles emiting from the center. back background
clean red-violet beam from above
button in the shape of a protorealistic holographic futuristc Rectangle . Front view.
above the clouds by a bright night, no visible moon Photorealistic
White Clef de sol
A 20 nodes straight metalic lock chain. High definition. In-Game asset. 2d. High contrast. No shadows
a closed metalic padlock. No visible key hole.
white menu icon
in white