Code edit (11 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught ReferenceError: size is not defined' in or related to this line: 'var faces = [' Line Number: 18
Code edit (5 edits merged)
Please save this source code
User prompt
Now for the Cube, use Face with 4 points instead of SimpleFace
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught ReferenceError: ry is not defined' in or related to this line: 'y = x * Math.sin(self.rx) * Math.cos(self.ry) + y * Math.cos(self.rx) * Math.cos(ry) - z * Math.sin(self.ry);' Line Number: 153
Code edit (11 edits merged)
Please save this source code
User prompt
in Face.rotate3D, take also rz into account
User prompt
in Face.rotate3D, take also rx into account
User prompt
in Face.rotate3D, take ry into account
Code edit (1 edits merged)
Please save this source code
Code edit (17 edits merged)
Please save this source code
User prompt
in Sphere.rotate3D, adjust angles so that angle between segments stay constant
Code edit (1 edits merged)
Please save this source code
Code edit (14 edits merged)
Please save this source code
User prompt
in Sphere rotate3D replace forEach by a for loo^p
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
in gameInitialize, init face1 witha all options
Code edit (2 edits merged)
Please save this source code
User prompt
in gameInitialize, init face1 with w & h of 100
User prompt
and a w/h of 100
User prompt
in gameInitialize, init face1 with 10 points
/**** * 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 var faces = [ // Face 1 (positive X, negative Z) new Face({ points: 4, w: self.baseSize, h: self.baseSize, dx: 0.5, dz: -0.5, ry: Math.PI / 2 }), // Face 2 (negative X, negative Z) new Face({ points: 4, w: self.baseSize, h: self.baseSize, dx: -0.5, dz: -0.5, ry: Math.PI / 2 }), // Face 3 (positive X, positive Z) new Face({ points: 4, w: self.baseSize, h: self.baseSize, dx: 0.5, dz: 0.5, ry: Math.PI / 2 }), // Face 4 (negative X, positive Z) new Face({ points: 4, w: self.baseSize, h: self.baseSize, dx: -0.5, dz: 0.5, ry: Math.PI / 2 }), // Face 5 (positive X, Y plane) - adjust dx, dy for positioning new Face({ points: 4, w: self.baseSize, h: self.baseSize, dx: 0.5, dy: 0.5 }), // Face 6 (negative X, Y plane) - adjust dx, dy for positioning new Face({ points: 4, w: self.baseSize, h: self.baseSize, dx: -0.5, dy: 0.5 })]; /* self.frontFace = new Face({ 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 Face({ 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 Face({ 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 Face({ 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 Face({ 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 Face({ 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); }); }; }); /***********************************************************************************/ /******************************* FACE CLASS *********************************/ /***********************************************************************************/ var Face = Container.expand(function (options) { var self = Container.call(this); options = options || {}; var points = Math.max(2, Math.min(10, options.points || 4)); // Ensure points are between 2 and 10 self.baseSize = 100; 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; // Generate points for the face based on the number of points specified self.baseFaceCoordinates = []; for (var i = 0; i < points; i++) { var angle = 2 * Math.PI * (i / points); self.baseFaceCoordinates.push({ x: self.w * Math.cos(angle) + self.dx * self.w, y: self.h * Math.sin(angle) + self.dy * self.h, z: self.dz * self.d }); } 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 polygon face using the Shape class self.face = new Shape(self.baseFaceCoordinates, self.tint); // Attach the face to the Face 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; self.faceCoordinates = self.baseFaceCoordinates.map(function (coord) { var x = coord.x - self.dx * self.w; var y = coord.y - self.dy * self.h; var z = coord.z - self.dz * self.d; // Apply new rotations (angleX, angleY, angleZ) first var newY = y * Math.cos(angleX) - z * Math.sin(angleX); var newZ = y * Math.sin(angleX) + z * Math.cos(angleX); var newX = x * Math.cos(angleY) + newZ * Math.sin(angleY); newZ = -x * Math.sin(angleY) + newZ * Math.cos(angleY); x = newX * Math.cos(angleZ) - newY * Math.sin(angleZ); y = newX * Math.sin(angleZ) + newY * Math.cos(angleZ); // Apply initial rotations (rx, ry, rz) newY = y * Math.cos(self.rx) - newZ * Math.sin(self.rx); newZ = y * Math.sin(self.rx) + newZ * Math.cos(self.rx); newX = x * Math.cos(self.ry) + newZ * Math.sin(self.ry); newZ = -x * Math.sin(self.ry) + newZ * Math.cos(self.ry); x = newX * Math.cos(self.rz) - newY * Math.sin(self.rz); y = newX * Math.sin(self.rz) + newY * Math.cos(self.rz); return { x: (x + self.dx * self.w) * scale, y: (y + self.dy * self.h) * scale, z: (newZ + self.dz * self.d) * scale }; }); self.face.updateCoordinates(self.faceCoordinates); }; /* self.rotate3D = function (angleX, angleY, angleZ, scale) { scale = scale || 1; self.faceCoordinates = self.baseFaceCoordinates.map(function (coord) { var x = coord.x - self.dx * self.w, y = coord.y - self.dy * self.h, z = coord.z - self.dz * self.d; // Apply initial rotations (rx, ry, rz) var newY = y * Math.cos(self.rx) - z * Math.sin(self.rx); var newZ = y * Math.sin(self.rx) + z * Math.cos(self.rx); var newX = x * Math.cos(self.ry) + newZ * Math.sin(self.ry); newZ = -x * Math.sin(self.ry) + newZ * Math.cos(self.ry); x = newX * Math.cos(self.rz) - newY * Math.sin(self.rz); y = newX * Math.sin(self.rz) + newY * Math.cos(self.rz); // Apply X-axis rotation newY = y * Math.cos(angleX) - newZ * Math.sin(angleX); newZ = y * Math.sin(angleX) + newZ * Math.cos(angleX); // Apply Y-axis rotation newX = x * Math.cos(angleY) + newZ * Math.sin(angleY); newZ = -x * Math.sin(angleY) + newZ * Math.cos(angleY); // Apply Z-axis rotation x = newX * Math.cos(angleZ) - newY * Math.sin(angleZ); y = newX * Math.sin(angleZ) + newY * Math.cos(angleZ); return { x: (x + self.dx * self.w) * scale, y: (y + self.dy * self.h) * scale, z: (newZ + self.dz * self.d) * scale }; }); self.face.updateCoordinates(self.faceCoordinates); }; */ // Initialize face in 3D space self.rotate3D(0, 0, 0, 1); }); /***********************************************************************************/ /********************************** 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 Face instances to simulate a 3D sphere self.faces = []; var segments = 5; // Number of segments to simulate the sphere for (var i = 0; i < segments; i++) { var angle = 2 * Math.PI / segments; // Create a circular segment as a face of the sphere var face = new Face({ points: 20, w: self.radius * 2, h: self.radius * 2, d: self.radius * 2, dx: 0, dy: 0, dz: 0, rx: 0, ry: i * angle, rz: 0, 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 ", angleX, angleY, angleZ); self.rotation = angleZ; var zScaleFactor = 1 + self.z / 500; for (var i = 0; i < self.faces.length; i++) { self.faces[i].rotate3D(angleX, angleY, angleZ, zScaleFactor); } }; self.rotate3D(0, 0, 0); }); /**** * 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 ****/ /***********************************************************************************/ /******************************* 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 sphere; var face1; var face2; var face3; var rotationSpeedX = 0; var rotationSpeedY = 0; var rotationSpeedZ = 0; var isDebug = false; var fullLog = []; var fpsText; var lastTick; var frameCount; var debugText; /***********************************************************************************/ /***************************** 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); sphere = new Sphere(); sphere.x = 2048 * 0.75; // Center horizontally sphere.y = 2732 / 2; // Center vertically sphere.z = 0; game.addChild(sphere); 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); // Update cube position with movement speed sphere.x += sphere.speedX; sphere.y += sphere.speedY; sphere.z += sphere.speedZ; // Check for sphere bouncing on horizontal borders if (sphere.x <= 100 || sphere.x >= 2048 - 100) { sphere.speedX *= -1; // Reverse horizontal direction } // Check for cube bouncing on Z dimension boundaries if (sphere.z <= -250 || sphere.z >= 1000) { // Assuming -500 and 500 as Z dimension boundaries sphere.speedZ *= -1; // Reverse Z dimension direction } // Check for cube bouncing on vertical borders if (sphere.y <= 100 || sphere.y >= 2732 - 100) { sphere.speedY *= -1; // Reverse vertical direction } // Rotating the cube sphere.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
@@ -21,45 +21,45 @@
}),
// Face 2 (negative X, negative Z)
new Face({
points: 4,
- w: size,
- h: size,
+ w: self.baseSize,
+ h: self.baseSize,
dx: -0.5,
dz: -0.5,
ry: Math.PI / 2
}),
// Face 3 (positive X, positive Z)
new Face({
points: 4,
- w: size,
- h: size,
+ w: self.baseSize,
+ h: self.baseSize,
dx: 0.5,
dz: 0.5,
ry: Math.PI / 2
}),
// Face 4 (negative X, positive Z)
new Face({
points: 4,
- w: size,
- h: size,
+ w: self.baseSize,
+ h: self.baseSize,
dx: -0.5,
dz: 0.5,
ry: Math.PI / 2
}),
// Face 5 (positive X, Y plane) - adjust dx, dy for positioning
new Face({
points: 4,
- w: size,
- h: size,
+ w: self.baseSize,
+ h: self.baseSize,
dx: 0.5,
dy: 0.5
}),
// Face 6 (negative X, Y plane) - adjust dx, dy for positioning
new Face({
points: 4,
- w: size,
- h: size,
+ w: self.baseSize,
+ h: self.baseSize,
dx: -0.5,
dy: 0.5
})]; /*
self.frontFace = new Face({
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