/**** * Plugins ****/ var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Import the storage plugin var Counter = Container.expand(function () { var self = Container.call(this); var txt = new Text2('15', { size: 100, fill: 0xFFFFFF, anchorX: 0.5, anchorY: 0, weight: 800, align: 'center', dropShadow: true, dropShadowColor: '#000000', dropShadowAngle: Math.PI / 6, dropShadowDistance: 5 }); self.val = counterMax; self.addChild(txt); self.init = function (index) { //var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; //self.width = game.width / (currentPalette.length - 1) / 2; //self.height = self.width / 2; self.val = counterMax; txt.setText('' + self.val); //self.x = selector.x + 50; self.x = selector.x + selector.width / 3; self.y = game.height - 430; txt.x = -40; }; self._update_migrated = function () { self.val -= 1; txt.setText('' + self.val); if (self.val > 9) { txt.x = -40; } else { txt.x = 0; } //self.x = selector.x; if (self.val <= 0) { //LK.showGameOver(); goToPainting(); } }; }); var GameLogo = Container.expand(function () { var self = Container.call(this); var logoGraphics = self.attachAsset('gameLogo', { anchorX: 0.5, anchorY: 0.5 }); }); var GameOverButton = Container.expand(function () { var self = Container.call(this); var buttonGraphics = self.attachAsset('gameOverButton', { anchorX: 0.5, anchorY: 0.5 }); }); // Particle class for explosion effect var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.init = function (x, y, vx, vy, scale) { self.x = x; self.y = y; self.vx = vx; self.vy = vy; self.scale.x = scale; self.scale.y = scale; //LK.effects.flashObject(self, 0xffffff, 50); }; self._move_migrated = function () { self.x += self.vx; self.y += self.vy; // Gradually fade out the particle particleGraphics.alpha -= 0.004; //self.scale.x -= 0.1; //self.scale.y -= 0.1; }; }); var Selector = Container.expand(function () { var self = Container.call(this); var selectorGraphics = self.attachAsset('selector', { anchorX: 0, anchorY: 0 }); self.init = function (index) { var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; self.width = game.width / (currentPalette.length - 1) / 2; self.height = self.width / 2; self.x = self.width / 2 + index * self.width * 2; self.y = game.height - self.height - 220; }; }); // Square class var Square = Container.expand(function () { var self = Container.call(this); var squareGraphics = self.attachAsset('square', { anchorX: 0, anchorY: 0 //tint: currentPalette[Math.floor(Math.random() * currentPalette.length)] }); self.init = function (index) { self.width = game.width / (currentPalette.length - 1); self.height = 200; self.x = index * self.width; self.y = game.height - 200; squareGraphics.tint = currentPalette[index]; }; //self.init(); }); // Star class var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, //tint: Math.random() * 0xFFFFFF // Assign a random color tint to each star //tint: colorArray[colorArrayCounter++ % colorArray.length] //tint: rainbowColors[Math.floor(Math.random() * rainbowColors.length - 1)] //tint: customColorsVibin[Math.floor(Math.random() * customColorsVibin.length - 1)] //tint: galacticGreen[Math.floor(Math.random() * galacticGreen.length)] tint: currentPalette[Math.floor(Math.random() * (currentPalette.length - 1))] }); self.init = function () { //console.log(self.tint); // Initialize star position closer to the center for a 3D effect //self.z = Math.random() * 1900 + 100; // Adjusted Z position range to prevent very small values self.z = 5000; //self.x = (Math.random() - 0.5) * game.width * 2; self.x = 100 + Math.random() * (game.width - 100); //self.y = (Math.random() - 0.5) * game.height * 2; //self.y = Math.random() * game.height; self.y = 100 + Math.random() * (game.height - 100); self.vx = (self.x - centerX) / self.z; self.vy = (self.y - centerY) / self.z; starGraphics.tint = currentPalette[Math.floor(Math.random() * (currentPalette.length - 1))]; }; self.init(); // Calculate velocity based on z position to simulate speed increase as stars move closer // Initialize velocities considering the deltaTime for consistent movement across different frame rates // Removed static deltaTime, will calculate dynamically in the game tick // Removed redundant initial velocity calculation // Cap maximum speed to prevent stars from moving too fast //self.speed = Math.min(40 + Math.random() * 40, 60); // Increase speed range for light-speed effect self.speed = 300; //self.speed = Math.min(2 + Math.random() * 2, 6); // Increase speed range for light-speed effect self._move_migrated = function () { /* // Calculate the direction vector from the center to the star var dx = self.x - centerX; var dy = self.y - centerY; // Normalize the direction vector var length = Math.sqrt(dx * dx + dy * dy); dx /= length; dy /= length; self.vx -= dx; self.vy -= dy; */ // Update position based on velocity self.z += self.speed; // This code block is removed to prevent redundancy in position updates. // Reset star position and properties for smooth re-entry //if (self.z > 2000 || self.x < -game.width || self.x > game.width * 2 || self.y < -game.height || self.y > game.height * 2) { //if (self.x < -game.width || self.x > game.width * 2 || self.y < -game.height || self.y > game.height * 2) { if (self.z > 640000 || self.x < 0 - self.width || self.x > game.width + self.width || self.y < 0 - self.height || self.y > game.height + self.height) { //self.z = Math.random() * 1900 + 100; // Reset Z to simulate continuous flow with varied depth /* self.z = 500; self.x = (Math.random() - 0.5) * game.width * 2; self.y = (Math.random() - 0.5) * game.height * 2; self.vx = (self.x - centerX) / self.z; self.vy = (self.y - centerY) / self.z; */ self.init(); //self.speed = Math.min(50 + Math.random() * 20, 70); // Increase speed range for enhanced light-speed effect //self.speed = Math.min(5 + Math.random() * 20, 30); // Increase speed range for enhanced light-speed effect //self.speed = Math.min(40 + Math.random() * 40, 60); } /* if (allPalettesCounter % 3 == 1) { self.x = centerX + Math.sin(self.z / 10000) * self.vx * self.z; } else { self.x = centerX + self.vx * self.z; } if (allPalettesCounter % 3 == 2) { self.y = centerY + Math.cos(self.z / 10000) * self.vy * self.z; } else { self.y = centerY + self.vy * self.z; }*/ var moveType = allPalettesCounter % 5; //var moveType = (movementTypeSelectorOffset + allPalettesCounter) % 5; /*if (currentPalette == matriax8c && score != 0) { moveType == 3; }*/ if (moveType == 0) { self.x = centerX + self.vx * self.z; self.y = centerY + self.vy * self.z; } else if (moveType == 1) { self.x = centerX + self.vx * self.z; self.y = centerY + Math.cos(self.z / 10000) * self.vy * self.z; } else if (moveType == 2) { self.x = centerX + Math.sin(self.z / 10000) * self.vx * self.z; self.y = centerY + self.vy * self.z; } else if (moveType == 3) { self.x = centerX + Math.sin(self.z / 10000) * self.vx * self.z; self.y = centerY + Math.cos(self.z / 10000) * self.vy * self.z; } else if (moveType == 4) { // Calculate the direction vector from the center to the star var dx = self.x - centerX; var dy = self.y - centerY; // Normalize the direction vector var length = Math.sqrt(dx * dx + dy * dy); dx /= length; dy /= length; // Adjust velocity to create a spiraling effect //self.vx += dy * 0.4; // Adjust the 0.05 value to control the tightness of the spiral //self.vy -= dx * 0.4; // Adjust the 0.05 value to control the tightness of the spiral self.vx += dy * 0.4 * 7500 / self.z; // Adjust the 0.05 value to control the tightness of the spiral self.vy -= dx * 0.4 * 7500 / self.z; // Adjust the 0.05 value to control the tightness of the spiral // Update position based on velocity self.x += self.vx; self.y += self.vy; self.z += self.speed / 2; // A little extra z required for this effect, for faster scaling. } else { self.x = centerX + self.vx * self.z; //self.x += Math.cos(LK.ticks % 100) * 10; self.y -= 4; } // Scale star based on z position to simulate 3D effect var scale = Math.min(1000 / (1000 + self.z), 1.5); // Limit maximum scale to 1.5 to prevent abrupt size changes //scale = Math.max((1000 + self.z) / 1000, 1.5); // Limit maximum scale to 1.5 to prevent abrupt size changes scale = self.z / 5000; //scale = Math.max(self.z / 10000, 1); self.scale.x = scale; self.scale.y = scale; }; self.on('down', function (x, y, obj) { // If player clicked the right color. if (self.getChildAt(0).tint == currentPalette[currentRightColor]) { // Increment score. score++; scoreTxt.setText(score); LK.setScore(score); if (score > storage.bestScore) { storage.bestScore = score; bestScoreTxt.setText('Best Score\n' + score); } collection.push({ w: self.width, c: currentPalette[currentRightColor] }); console.log(collection); // Trigger radial particle explosion createRadialExplosion(self.x, self.y); // Show second hint, if this is first correctly clicked color. if (!secondHintShown) { secondHintShown = true; instructionsTxt.setText("Great, now collect the next colors!\nDon't let the counter reach zero"); } if (score >= 2 && instructionsTxt) { instructionsTxt.destroy(); } if (++currentRightColor == currentPalette.length - 1) { LK.getSound('hyper1').play(); // Change to new palette. allPalettesCounter++; if (allPalettesCounter == allPalettes.length) { allPalettesCounter = 0; } currentPalette = allPalettes[allPalettesCounter]; currentRightColor = 0; game.setBackgroundColor(currentPalette[currentPalette.length - 1]); initSquares(); selector.init(0); stars.forEach(function (star, index) { star.init(); }); // Every once in a while, we'll decrement the countdown timer to increase difficulty. if (score > 44 && score < 80) { counterMax--; } else if (score > 89 && score < 130) { counterMax--; } else if (score > 134 && score < 170) { counterMax--; } else if (score > 179 && counterMax > 6) { counterMax--; } } else { // Move selector to next color on palette. selector.init(currentRightColor); //LK.effects.flashObject(selector, 0xFFFF00, 1000); LK.effects.flashObject(selector, currentPalette[currentRightColor], 2000); } counter.init(); game.setChildIndex(counter, game.children.length - 1); //game.getChildByName('counter').setDepth(game.getChildByName('selector').getDepth() + 1); //console.log(game.getChildByName('selector').getDepth()); // Re-init this star. self.x = -50000; } else { //console.log('wrong'); // TODO: Game over or life lost? } }); }); /**** * Initialize Game ****/ var game = new LK.Game({ //backgroundColor: 0x002255 backgroundColor: 0x16161c }); /**** * Game Code ****/ // Play background sound at start and loop it LK.playMusic('bgSound', { loop: true }); LK.getSound('hyper1').play(); function createRadialExplosion(x, y) { LK.getSound('planet1').play(); var numParticles = 20; //var particles = []; for (var i = 0; i < numParticles; i++) { //var angle = Math.random() * Math.PI * 2; //var angle = Math.PI * 2 / numParticles - i; var angle = 360 / numParticles * i * (Math.PI / 180); //var speed = Math.random() * 5 + 2; // Random speed between 2 and 7 var speed = 30; var vx = Math.cos(angle) * speed; var vy = Math.sin(angle) * speed; //var scale = Math.random() * 0.5 + 0.5; // Random scale between 0.5 and 1 var scale = 3; var particle = new Particle(); particle.init(x, y, vx, vy, scale); game.addChild(particle); particles.push(particle); } } function hsvToHex(h, s, v) { var r, g, b, i, f, p, q, t; i = Math.floor(h * 6); f = h * 6 - i; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } var toHex = function toHex(x) { var hex = Math.round(x * 255).toString(16); return hex.length === 1 ? '0' + hex : hex; }; return '0x' + toHex(r) + toHex(g) + toHex(b); } var numColors = 36; var rainbowColors = function () { var colors = []; for (var i = 0; i < numColors; i++) { var hue = i * (360 / numColors) % 360; colors.push(hsvToHex(hue / 360, 1, 1)); } return colors; }(); var customColorsVibin = ["0xeffbf9", "0x0b152e", "0x194471", "0x1b7eb4", "0x11bbd9", "0x0f5434", "0x127d2c", "0x1a9f25", "0x60d12b", "0x162a2e", "0x2d4747", "0x3b6058", "0x577d6f", "0x13353b", "0x205858", "0x2d7d75", "0x57ab96", "0x67978c", "0x83b09c", "0xa9d5bb", "0xdbf2df", "0xbc5132", "0xd97840", "0xe29e3f", "0xfbca6b", "0xb03502", "0xcd6d07", "0xea9b06", "0xf2cc2c", "0x60212b", "0x8a331d", "0xb46d23", "0xd9a744", "0x64112a", "0x961b2d", "0xc02038", "0xf23a3a", "0x301d32", "0x6f1771", "0xbc1a8d", "0xf23e9a", "0x433933", "0x585047", "0x7d705c", "0x9b9172", "0x003a5c", "0x03668e", "0x0d8cb0", "0x18abc4", "0xd138a0", "0xea5699", "0xf78c9d", "0xfbb495", "0xa76372", "0xc98a9c", "0xe6acc1", "0xf2bed1", "0x16111d"]; //var galacticGreen = ["0xe8f1a6", "0xcad670", "0xa3c255", "0x6fa341", "0x498f45", "0x387450", "0x2d5c56", "0x1f3741", "0x1e2029", "0x16161c"]; var galacticGreen = ["0xe8f1a6", "0xa3c255", "0x498f45", "0x387450", "0x2d5c56", "0x1f3741", "0x06060c"]; //var berryNebula = ["0x6ceded", "0x6cb9c9", "0x6d85a5", "0x6e5181", "0x6f1d5c", "0x4f1446", "0x2e0a30", "0x0d001a"]; var berryNebula = ["0x6ceded", "0x6d85a5", "0x6e5181", "0x6f1d5c", "0x4f1446", "0x0d001a"]; var matriax8c = ["0xf0f0dc", "0x736464", "0xa0694b", "0xd24040", "0x00a0c8", "0x10c840", "0xfac800", "0x101820"]; //var vividMemory8 = ["0xe21c61", "0xe26159", "0xfea85f", "0xd8dcb4", "0x5eb6ad", "0x1b958d", "0x105390", "0x381631"]; var vividMemory8 = ["0xe21c61", "0xe26159", "0xfea85f", "0xd8dcb4", "0x64b9b0", "0x1b958d", "0x105390", "0x381631"]; //var superNova7 = ["0xffce9c", "0xcf7862", "0xa75252", "0x773a4d", "0x543246", "0x3d203b", "0x1a080e"]; var superNova7 = ["0xffce9c", "0xcf7862", "0xa75252", "0x773a4d", "0x543246", "0x1a080e"]; //var cyclope6 = ["0x30e1b9", "0x0eaf9b", "0x0b8a8f", "0x32535f", "0x631b34", "0x411d31"]; var cyclope6 = ["0x52f3db", "0x0eaf6b", "0x0b8a8f", "0x32535f", "0x631b34", "0x300d21"]; //var hotSand = ["0xf26d1f", "0xe04217", "0xc02b18", "0x7c0300", "0x590000", "0x3a0000"]; var hotSand = ["0xf3b93e", "0xf26d1f", "0xe04217", "0xa92616", "0x7c0300", "0x290000"]; //var pinkNeonSign6 = ["0xef87c3", "0xcc77af", "0x9e6695", "0x70567b", "0x51496b", "0x313d59"]; var pinkNeonSign6 = ["0xffe8e3", "0xef97c3", "0xbb66af", "0x8e5685", "0x932a6f", "0x313d59"]; //var currentPalette = berryNebula; //game.setBackgroundColor(currentPalette[currentPalette.length - 1]); // Since game changes between palettes as we progress, we keep the different palettes in an array and have a counter for which one we're current using. var allPalettes = [vividMemory8, berryNebula, superNova7, matriax8c, pinkNeonSign6, hotSand, cyclope6, galacticGreen]; var allPalettesCounter = 0; //Math.floor(Math.random() * allPalettes.length); //var movementTypeSelectorOffset = 5 - allPalettesCounter; //-1 * allPalettesCounter; var currentPalette = allPalettes[allPalettesCounter]; game.setBackgroundColor(currentPalette[currentPalette.length - 1]); // TODO: Add more palettes to game. /* // Create a text label with instructions. var instructionsTxt = new Text2('Tap stars of the indicated color.\n', { size: 75, fill: "#ffffff", anchorX: 0.5, anchorY: 0.5, align: 'center' }); // Center the text label on the screen instructionsTxt.x = game.width / 2 - 900; instructionsTxt.y = game.height / 2; // Add the text label to the game game.addChild(instructionsTxt); */ storage.bestScore = storage.bestScore || 0; var centerX = 1024; var centerY = game.height / 2; var targetX = centerX; var targetY = centerY; var tweenDuration = 60; // 60 frames = 1 second at 60FPS var tweenProgress = 0; game.on('down', function (x, y, obj) { if (!gameStarted) { gameStarted = true; //instructionsTxt.destroy(); instructionsTxt.setText(''); gameLogo.destroy(); scoreTxt.alpha = 1; bestScoreTxt.alpha = 1; } else { var pos = game.toLocal(obj.global); //targetX = pos.x; //targetY = pos.y; tweenProgress = 0; targetX = game.width - pos.x; targetY = game.height - pos.y; } }); var particles = []; var stars = []; for (var i = 0; i < 100; i++) { // Increase star count for denser starfield var star = new Star(); stars.push(star); game.addChild(star); } var squares = []; var initSquares = function initSquares() { // Start by removing squares from previous palette, if they exist. squares.forEach(function (square, index) { square.destroy(); }); squares = []; for (var j = 0; j < currentPalette.length - 1; j++) { var square = new Square(); square.init(j); squares.push(square); game.addChild(square); } }; /* for (var j = 0; j < currentPalette.length - 1; j++) { var square = new Square(); square.init(j); squares.push(square); game.addChild(square); }*/ initSquares(); var collection = []; var goToPainting = function goToPainting() { LK.stopMusic('bgSound'); LK.getSound('endTransition').play(); gameEnded = true; stars.forEach(function (star, index) { star.destroy(); }); stars = []; particles.forEach(function (particle, index) { particle.destroy(); }); particles = []; selector.destroy(); counter.destroy(); squares.forEach(function (square, index) { square.destroy(); }); for (var i = 0; i < collection.length && i < 100; i++) { var t = new Particle(); //t.init(Math.random() * game.width, Math.random() * game.height, 0, 0, 1); //x, y, vx, vy, scale t.init(0, 0, 0, 0, 1); //x, y, vx, vy, scale t.width = collection[i].w; t.height = t.width; t.x = t.width + Math.random() * (game.width - t.width * 2); //t.y = 500 + Math.random() * (game.height - t.height - 500); t.y = 700 + Math.random() * (game.height - t.height - 700); t.getChildAt(0).tint = collection[i].c; /*t.on('down', function () { draggedItem = self; });*/ // Listen for 'up' event to stop dragging game.on('up', function (x, y, obj) { draggedItem = null; }); game.addChild(t); makeObjectDraggable(t); } var goText = new Text2("Good Job! Here are the colors you collected!\nYou can drag and arrange them into something -\nmaybe for a screenshot to share :)", { weight: 800, size: 80, fill: 0xFFFFFF, anchorX: 0.5, align: 'center', dropShadow: true, dropShadowColor: '#000000', dropShadowAngle: Math.PI / 6, dropShadowDistance: 5 }); goText.x = game.width / 2 - goText.width / 2; goText.y = 300; //game.height / 2; game.addChild(goText); var gLogo = game.addChild(new GameLogo()); gLogo.scale.x = 0.2; gLogo.scale.y = 0.2; gLogo.x = 300 + gLogo.width / 2; //game.width - 50 - gLogo.width / 2; gLogo.y = 50 + gLogo.height / 2; //TODO: add game over button here var b = game.addChild(new GameOverButton()); b.x = game.width - 50 - b.width / 2; b.y = game.height - 50 - b.height / 2; b.on('down', function () { LK.setScore(score); LK.showGameOver(); }); }; function makeObjectDraggable(object) { // Listen for 'down' event to start dragging object.on('down', function (x, y, obj) { // Set the draggedObject to this object when it is pressed and move it to the highest depth draggedItem = object; game.setChildIndex(draggedItem, game.children.length - 1); }); } var draggedItem = null; var selector = new Selector(); selector.init(0); game.addChild(selector); var counterMax = 15; var counter = new Counter(); counter.init(selector); game.addChild(counter); var currentRightColor = 0; var score = 0; var gameStarted = false; var gameEnded = false; var secondHintShown = false; // Score display var scoreTxt = new Text2('0', { weight: 800, size: 120, fill: 0xFFFFFF, anchorX: 0.5 }); scoreTxt.alpha = 0; LK.gui.top.addChild(scoreTxt); var bestScoreTxt = new Text2('Best Score\n' + storage.bestScore, { weight: 300, size: 45, fill: 0xFFFFFF, anchorX: 0.5, align: 'center' }); bestScoreTxt.alpha = 0; bestScoreTxt.x = -250; LK.gui.topRight.addChild(bestScoreTxt); var gameLogo = game.addChild(new GameLogo()); gameLogo.x = game.width / 2; gameLogo.y = 700; var instructionsTxt = new Text2("Welcome to colorful outer space!\n\nWe'll be collecting colors from all\nof the galaxies.\n\nSpace is endless - how far can you go?\n\nTap a planet of the color indicated below\nto get started.", { weight: 800, size: 90, fill: 0xFFFFFF, anchorX: 0.5, align: 'center', dropShadow: true, dropShadowColor: '#000000', dropShadowAngle: Math.PI / 6, dropShadowDistance: 5 }); instructionsTxt.x = game.width / 2 - instructionsTxt.width / 2; instructionsTxt.y = game.height / 2; game.addChild(instructionsTxt); // Update dragging logic to correctly handle 'move' event game.on('move', function (x, y, obj) { if (draggedItem && gameEnded) { var pos = game.toLocal(obj.global); draggedItem.x = pos.x; draggedItem.y = pos.y; } }); // Game tick LK.on('tick', function () { //console.log(particles.length); stars.forEach(function (star, index) { star._move_migrated(); }); if (gameStarted && !gameEnded) { //console.log(LK.ticks); if (LK.ticks > 0 && LK.ticks % 100 == 0) { counter._update_migrated(); } particles.forEach(function (particle, index) { particle._move_migrated(); if (particle.alpha <= 0 || particle.y > game.height - 200) { particles.splice(index, 1); particle.destroy(); } }); if (tweenProgress < tweenDuration) { centerX += (targetX - centerX) / (tweenDuration - tweenProgress); centerY += (targetY - centerY) / (tweenDuration - tweenProgress); tweenProgress++; } } });
/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Import the storage plugin
var Counter = Container.expand(function () {
var self = Container.call(this);
var txt = new Text2('15', {
size: 100,
fill: 0xFFFFFF,
anchorX: 0.5,
anchorY: 0,
weight: 800,
align: 'center',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 5
});
self.val = counterMax;
self.addChild(txt);
self.init = function (index) {
//var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
//self.width = game.width / (currentPalette.length - 1) / 2;
//self.height = self.width / 2;
self.val = counterMax;
txt.setText('' + self.val);
//self.x = selector.x + 50;
self.x = selector.x + selector.width / 3;
self.y = game.height - 430;
txt.x = -40;
};
self._update_migrated = function () {
self.val -= 1;
txt.setText('' + self.val);
if (self.val > 9) {
txt.x = -40;
} else {
txt.x = 0;
}
//self.x = selector.x;
if (self.val <= 0) {
//LK.showGameOver();
goToPainting();
}
};
});
var GameLogo = Container.expand(function () {
var self = Container.call(this);
var logoGraphics = self.attachAsset('gameLogo', {
anchorX: 0.5,
anchorY: 0.5
});
});
var GameOverButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('gameOverButton', {
anchorX: 0.5,
anchorY: 0.5
});
});
// Particle class for explosion effect
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
self.init = function (x, y, vx, vy, scale) {
self.x = x;
self.y = y;
self.vx = vx;
self.vy = vy;
self.scale.x = scale;
self.scale.y = scale;
//LK.effects.flashObject(self, 0xffffff, 50);
};
self._move_migrated = function () {
self.x += self.vx;
self.y += self.vy;
// Gradually fade out the particle
particleGraphics.alpha -= 0.004;
//self.scale.x -= 0.1;
//self.scale.y -= 0.1;
};
});
var Selector = Container.expand(function () {
var self = Container.call(this);
var selectorGraphics = self.attachAsset('selector', {
anchorX: 0,
anchorY: 0
});
self.init = function (index) {
var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
self.width = game.width / (currentPalette.length - 1) / 2;
self.height = self.width / 2;
self.x = self.width / 2 + index * self.width * 2;
self.y = game.height - self.height - 220;
};
});
// Square class
var Square = Container.expand(function () {
var self = Container.call(this);
var squareGraphics = self.attachAsset('square', {
anchorX: 0,
anchorY: 0
//tint: currentPalette[Math.floor(Math.random() * currentPalette.length)]
});
self.init = function (index) {
self.width = game.width / (currentPalette.length - 1);
self.height = 200;
self.x = index * self.width;
self.y = game.height - 200;
squareGraphics.tint = currentPalette[index];
};
//self.init();
});
// Star class
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
//tint: Math.random() * 0xFFFFFF // Assign a random color tint to each star
//tint: colorArray[colorArrayCounter++ % colorArray.length]
//tint: rainbowColors[Math.floor(Math.random() * rainbowColors.length - 1)]
//tint: customColorsVibin[Math.floor(Math.random() * customColorsVibin.length - 1)]
//tint: galacticGreen[Math.floor(Math.random() * galacticGreen.length)]
tint: currentPalette[Math.floor(Math.random() * (currentPalette.length - 1))]
});
self.init = function () {
//console.log(self.tint);
// Initialize star position closer to the center for a 3D effect
//self.z = Math.random() * 1900 + 100; // Adjusted Z position range to prevent very small values
self.z = 5000;
//self.x = (Math.random() - 0.5) * game.width * 2;
self.x = 100 + Math.random() * (game.width - 100);
//self.y = (Math.random() - 0.5) * game.height * 2;
//self.y = Math.random() * game.height;
self.y = 100 + Math.random() * (game.height - 100);
self.vx = (self.x - centerX) / self.z;
self.vy = (self.y - centerY) / self.z;
starGraphics.tint = currentPalette[Math.floor(Math.random() * (currentPalette.length - 1))];
};
self.init();
// Calculate velocity based on z position to simulate speed increase as stars move closer
// Initialize velocities considering the deltaTime for consistent movement across different frame rates
// Removed static deltaTime, will calculate dynamically in the game tick
// Removed redundant initial velocity calculation
// Cap maximum speed to prevent stars from moving too fast
//self.speed = Math.min(40 + Math.random() * 40, 60); // Increase speed range for light-speed effect
self.speed = 300;
//self.speed = Math.min(2 + Math.random() * 2, 6); // Increase speed range for light-speed effect
self._move_migrated = function () {
/*
// Calculate the direction vector from the center to the star
var dx = self.x - centerX;
var dy = self.y - centerY;
// Normalize the direction vector
var length = Math.sqrt(dx * dx + dy * dy);
dx /= length;
dy /= length;
self.vx -= dx;
self.vy -= dy;
*/
// Update position based on velocity
self.z += self.speed;
// This code block is removed to prevent redundancy in position updates.
// Reset star position and properties for smooth re-entry
//if (self.z > 2000 || self.x < -game.width || self.x > game.width * 2 || self.y < -game.height || self.y > game.height * 2) {
//if (self.x < -game.width || self.x > game.width * 2 || self.y < -game.height || self.y > game.height * 2) {
if (self.z > 640000 || self.x < 0 - self.width || self.x > game.width + self.width || self.y < 0 - self.height || self.y > game.height + self.height) {
//self.z = Math.random() * 1900 + 100; // Reset Z to simulate continuous flow with varied depth
/*
self.z = 500;
self.x = (Math.random() - 0.5) * game.width * 2;
self.y = (Math.random() - 0.5) * game.height * 2;
self.vx = (self.x - centerX) / self.z;
self.vy = (self.y - centerY) / self.z;
*/
self.init();
//self.speed = Math.min(50 + Math.random() * 20, 70); // Increase speed range for enhanced light-speed effect
//self.speed = Math.min(5 + Math.random() * 20, 30); // Increase speed range for enhanced light-speed effect
//self.speed = Math.min(40 + Math.random() * 40, 60);
}
/*
if (allPalettesCounter % 3 == 1) {
self.x = centerX + Math.sin(self.z / 10000) * self.vx * self.z;
} else {
self.x = centerX + self.vx * self.z;
}
if (allPalettesCounter % 3 == 2) {
self.y = centerY + Math.cos(self.z / 10000) * self.vy * self.z;
} else {
self.y = centerY + self.vy * self.z;
}*/
var moveType = allPalettesCounter % 5;
//var moveType = (movementTypeSelectorOffset + allPalettesCounter) % 5;
/*if (currentPalette == matriax8c && score != 0) {
moveType == 3;
}*/
if (moveType == 0) {
self.x = centerX + self.vx * self.z;
self.y = centerY + self.vy * self.z;
} else if (moveType == 1) {
self.x = centerX + self.vx * self.z;
self.y = centerY + Math.cos(self.z / 10000) * self.vy * self.z;
} else if (moveType == 2) {
self.x = centerX + Math.sin(self.z / 10000) * self.vx * self.z;
self.y = centerY + self.vy * self.z;
} else if (moveType == 3) {
self.x = centerX + Math.sin(self.z / 10000) * self.vx * self.z;
self.y = centerY + Math.cos(self.z / 10000) * self.vy * self.z;
} else if (moveType == 4) {
// Calculate the direction vector from the center to the star
var dx = self.x - centerX;
var dy = self.y - centerY;
// Normalize the direction vector
var length = Math.sqrt(dx * dx + dy * dy);
dx /= length;
dy /= length;
// Adjust velocity to create a spiraling effect
//self.vx += dy * 0.4; // Adjust the 0.05 value to control the tightness of the spiral
//self.vy -= dx * 0.4; // Adjust the 0.05 value to control the tightness of the spiral
self.vx += dy * 0.4 * 7500 / self.z; // Adjust the 0.05 value to control the tightness of the spiral
self.vy -= dx * 0.4 * 7500 / self.z; // Adjust the 0.05 value to control the tightness of the spiral
// Update position based on velocity
self.x += self.vx;
self.y += self.vy;
self.z += self.speed / 2; // A little extra z required for this effect, for faster scaling.
} else {
self.x = centerX + self.vx * self.z;
//self.x += Math.cos(LK.ticks % 100) * 10;
self.y -= 4;
}
// Scale star based on z position to simulate 3D effect
var scale = Math.min(1000 / (1000 + self.z), 1.5); // Limit maximum scale to 1.5 to prevent abrupt size changes
//scale = Math.max((1000 + self.z) / 1000, 1.5); // Limit maximum scale to 1.5 to prevent abrupt size changes
scale = self.z / 5000;
//scale = Math.max(self.z / 10000, 1);
self.scale.x = scale;
self.scale.y = scale;
};
self.on('down', function (x, y, obj) {
// If player clicked the right color.
if (self.getChildAt(0).tint == currentPalette[currentRightColor]) {
// Increment score.
score++;
scoreTxt.setText(score);
LK.setScore(score);
if (score > storage.bestScore) {
storage.bestScore = score;
bestScoreTxt.setText('Best Score\n' + score);
}
collection.push({
w: self.width,
c: currentPalette[currentRightColor]
});
console.log(collection);
// Trigger radial particle explosion
createRadialExplosion(self.x, self.y);
// Show second hint, if this is first correctly clicked color.
if (!secondHintShown) {
secondHintShown = true;
instructionsTxt.setText("Great, now collect the next colors!\nDon't let the counter reach zero");
}
if (score >= 2 && instructionsTxt) {
instructionsTxt.destroy();
}
if (++currentRightColor == currentPalette.length - 1) {
LK.getSound('hyper1').play();
// Change to new palette.
allPalettesCounter++;
if (allPalettesCounter == allPalettes.length) {
allPalettesCounter = 0;
}
currentPalette = allPalettes[allPalettesCounter];
currentRightColor = 0;
game.setBackgroundColor(currentPalette[currentPalette.length - 1]);
initSquares();
selector.init(0);
stars.forEach(function (star, index) {
star.init();
});
// Every once in a while, we'll decrement the countdown timer to increase difficulty.
if (score > 44 && score < 80) {
counterMax--;
} else if (score > 89 && score < 130) {
counterMax--;
} else if (score > 134 && score < 170) {
counterMax--;
} else if (score > 179 && counterMax > 6) {
counterMax--;
}
} else {
// Move selector to next color on palette.
selector.init(currentRightColor);
//LK.effects.flashObject(selector, 0xFFFF00, 1000);
LK.effects.flashObject(selector, currentPalette[currentRightColor], 2000);
}
counter.init();
game.setChildIndex(counter, game.children.length - 1);
//game.getChildByName('counter').setDepth(game.getChildByName('selector').getDepth() + 1);
//console.log(game.getChildByName('selector').getDepth());
// Re-init this star.
self.x = -50000;
} else {
//console.log('wrong');
// TODO: Game over or life lost?
}
});
});
/****
* Initialize Game
****/
var game = new LK.Game({
//backgroundColor: 0x002255
backgroundColor: 0x16161c
});
/****
* Game Code
****/
// Play background sound at start and loop it
LK.playMusic('bgSound', {
loop: true
});
LK.getSound('hyper1').play();
function createRadialExplosion(x, y) {
LK.getSound('planet1').play();
var numParticles = 20;
//var particles = [];
for (var i = 0; i < numParticles; i++) {
//var angle = Math.random() * Math.PI * 2;
//var angle = Math.PI * 2 / numParticles - i;
var angle = 360 / numParticles * i * (Math.PI / 180);
//var speed = Math.random() * 5 + 2; // Random speed between 2 and 7
var speed = 30;
var vx = Math.cos(angle) * speed;
var vy = Math.sin(angle) * speed;
//var scale = Math.random() * 0.5 + 0.5; // Random scale between 0.5 and 1
var scale = 3;
var particle = new Particle();
particle.init(x, y, vx, vy, scale);
game.addChild(particle);
particles.push(particle);
}
}
function hsvToHex(h, s, v) {
var r, g, b, i, f, p, q, t;
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0:
r = v, g = t, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = t;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = t, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}
var toHex = function toHex(x) {
var hex = Math.round(x * 255).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return '0x' + toHex(r) + toHex(g) + toHex(b);
}
var numColors = 36;
var rainbowColors = function () {
var colors = [];
for (var i = 0; i < numColors; i++) {
var hue = i * (360 / numColors) % 360;
colors.push(hsvToHex(hue / 360, 1, 1));
}
return colors;
}();
var customColorsVibin = ["0xeffbf9", "0x0b152e", "0x194471", "0x1b7eb4", "0x11bbd9", "0x0f5434", "0x127d2c", "0x1a9f25", "0x60d12b", "0x162a2e", "0x2d4747", "0x3b6058", "0x577d6f", "0x13353b", "0x205858", "0x2d7d75", "0x57ab96", "0x67978c", "0x83b09c", "0xa9d5bb", "0xdbf2df", "0xbc5132", "0xd97840", "0xe29e3f", "0xfbca6b", "0xb03502", "0xcd6d07", "0xea9b06", "0xf2cc2c", "0x60212b", "0x8a331d", "0xb46d23", "0xd9a744", "0x64112a", "0x961b2d", "0xc02038", "0xf23a3a", "0x301d32", "0x6f1771", "0xbc1a8d", "0xf23e9a", "0x433933", "0x585047", "0x7d705c", "0x9b9172", "0x003a5c", "0x03668e", "0x0d8cb0", "0x18abc4", "0xd138a0", "0xea5699", "0xf78c9d", "0xfbb495", "0xa76372", "0xc98a9c", "0xe6acc1", "0xf2bed1", "0x16111d"];
//var galacticGreen = ["0xe8f1a6", "0xcad670", "0xa3c255", "0x6fa341", "0x498f45", "0x387450", "0x2d5c56", "0x1f3741", "0x1e2029", "0x16161c"];
var galacticGreen = ["0xe8f1a6", "0xa3c255", "0x498f45", "0x387450", "0x2d5c56", "0x1f3741", "0x06060c"];
//var berryNebula = ["0x6ceded", "0x6cb9c9", "0x6d85a5", "0x6e5181", "0x6f1d5c", "0x4f1446", "0x2e0a30", "0x0d001a"];
var berryNebula = ["0x6ceded", "0x6d85a5", "0x6e5181", "0x6f1d5c", "0x4f1446", "0x0d001a"];
var matriax8c = ["0xf0f0dc", "0x736464", "0xa0694b", "0xd24040", "0x00a0c8", "0x10c840", "0xfac800", "0x101820"];
//var vividMemory8 = ["0xe21c61", "0xe26159", "0xfea85f", "0xd8dcb4", "0x5eb6ad", "0x1b958d", "0x105390", "0x381631"];
var vividMemory8 = ["0xe21c61", "0xe26159", "0xfea85f", "0xd8dcb4", "0x64b9b0", "0x1b958d", "0x105390", "0x381631"];
//var superNova7 = ["0xffce9c", "0xcf7862", "0xa75252", "0x773a4d", "0x543246", "0x3d203b", "0x1a080e"];
var superNova7 = ["0xffce9c", "0xcf7862", "0xa75252", "0x773a4d", "0x543246", "0x1a080e"];
//var cyclope6 = ["0x30e1b9", "0x0eaf9b", "0x0b8a8f", "0x32535f", "0x631b34", "0x411d31"];
var cyclope6 = ["0x52f3db", "0x0eaf6b", "0x0b8a8f", "0x32535f", "0x631b34", "0x300d21"];
//var hotSand = ["0xf26d1f", "0xe04217", "0xc02b18", "0x7c0300", "0x590000", "0x3a0000"];
var hotSand = ["0xf3b93e", "0xf26d1f", "0xe04217", "0xa92616", "0x7c0300", "0x290000"];
//var pinkNeonSign6 = ["0xef87c3", "0xcc77af", "0x9e6695", "0x70567b", "0x51496b", "0x313d59"];
var pinkNeonSign6 = ["0xffe8e3", "0xef97c3", "0xbb66af", "0x8e5685", "0x932a6f", "0x313d59"];
//var currentPalette = berryNebula;
//game.setBackgroundColor(currentPalette[currentPalette.length - 1]);
// Since game changes between palettes as we progress, we keep the different palettes in an array and have a counter for which one we're current using.
var allPalettes = [vividMemory8, berryNebula, superNova7, matriax8c, pinkNeonSign6, hotSand, cyclope6, galacticGreen];
var allPalettesCounter = 0; //Math.floor(Math.random() * allPalettes.length);
//var movementTypeSelectorOffset = 5 - allPalettesCounter; //-1 * allPalettesCounter;
var currentPalette = allPalettes[allPalettesCounter];
game.setBackgroundColor(currentPalette[currentPalette.length - 1]);
// TODO: Add more palettes to game.
/*
// Create a text label with instructions.
var instructionsTxt = new Text2('Tap stars of the indicated color.\n', {
size: 75,
fill: "#ffffff",
anchorX: 0.5,
anchorY: 0.5,
align: 'center'
});
// Center the text label on the screen
instructionsTxt.x = game.width / 2 - 900;
instructionsTxt.y = game.height / 2;
// Add the text label to the game
game.addChild(instructionsTxt);
*/
storage.bestScore = storage.bestScore || 0;
var centerX = 1024;
var centerY = game.height / 2;
var targetX = centerX;
var targetY = centerY;
var tweenDuration = 60; // 60 frames = 1 second at 60FPS
var tweenProgress = 0;
game.on('down', function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
//instructionsTxt.destroy();
instructionsTxt.setText('');
gameLogo.destroy();
scoreTxt.alpha = 1;
bestScoreTxt.alpha = 1;
} else {
var pos = game.toLocal(obj.global);
//targetX = pos.x;
//targetY = pos.y;
tweenProgress = 0;
targetX = game.width - pos.x;
targetY = game.height - pos.y;
}
});
var particles = [];
var stars = [];
for (var i = 0; i < 100; i++) {
// Increase star count for denser starfield
var star = new Star();
stars.push(star);
game.addChild(star);
}
var squares = [];
var initSquares = function initSquares() {
// Start by removing squares from previous palette, if they exist.
squares.forEach(function (square, index) {
square.destroy();
});
squares = [];
for (var j = 0; j < currentPalette.length - 1; j++) {
var square = new Square();
square.init(j);
squares.push(square);
game.addChild(square);
}
};
/*
for (var j = 0; j < currentPalette.length - 1; j++) {
var square = new Square();
square.init(j);
squares.push(square);
game.addChild(square);
}*/
initSquares();
var collection = [];
var goToPainting = function goToPainting() {
LK.stopMusic('bgSound');
LK.getSound('endTransition').play();
gameEnded = true;
stars.forEach(function (star, index) {
star.destroy();
});
stars = [];
particles.forEach(function (particle, index) {
particle.destroy();
});
particles = [];
selector.destroy();
counter.destroy();
squares.forEach(function (square, index) {
square.destroy();
});
for (var i = 0; i < collection.length && i < 100; i++) {
var t = new Particle();
//t.init(Math.random() * game.width, Math.random() * game.height, 0, 0, 1); //x, y, vx, vy, scale
t.init(0, 0, 0, 0, 1); //x, y, vx, vy, scale
t.width = collection[i].w;
t.height = t.width;
t.x = t.width + Math.random() * (game.width - t.width * 2);
//t.y = 500 + Math.random() * (game.height - t.height - 500);
t.y = 700 + Math.random() * (game.height - t.height - 700);
t.getChildAt(0).tint = collection[i].c;
/*t.on('down', function () {
draggedItem = self;
});*/
// Listen for 'up' event to stop dragging
game.on('up', function (x, y, obj) {
draggedItem = null;
});
game.addChild(t);
makeObjectDraggable(t);
}
var goText = new Text2("Good Job! Here are the colors you collected!\nYou can drag and arrange them into something -\nmaybe for a screenshot to share :)", {
weight: 800,
size: 80,
fill: 0xFFFFFF,
anchorX: 0.5,
align: 'center',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 5
});
goText.x = game.width / 2 - goText.width / 2;
goText.y = 300; //game.height / 2;
game.addChild(goText);
var gLogo = game.addChild(new GameLogo());
gLogo.scale.x = 0.2;
gLogo.scale.y = 0.2;
gLogo.x = 300 + gLogo.width / 2; //game.width - 50 - gLogo.width / 2;
gLogo.y = 50 + gLogo.height / 2;
//TODO: add game over button here
var b = game.addChild(new GameOverButton());
b.x = game.width - 50 - b.width / 2;
b.y = game.height - 50 - b.height / 2;
b.on('down', function () {
LK.setScore(score);
LK.showGameOver();
});
};
function makeObjectDraggable(object) {
// Listen for 'down' event to start dragging
object.on('down', function (x, y, obj) {
// Set the draggedObject to this object when it is pressed and move it to the highest depth
draggedItem = object;
game.setChildIndex(draggedItem, game.children.length - 1);
});
}
var draggedItem = null;
var selector = new Selector();
selector.init(0);
game.addChild(selector);
var counterMax = 15;
var counter = new Counter();
counter.init(selector);
game.addChild(counter);
var currentRightColor = 0;
var score = 0;
var gameStarted = false;
var gameEnded = false;
var secondHintShown = false;
// Score display
var scoreTxt = new Text2('0', {
weight: 800,
size: 120,
fill: 0xFFFFFF,
anchorX: 0.5
});
scoreTxt.alpha = 0;
LK.gui.top.addChild(scoreTxt);
var bestScoreTxt = new Text2('Best Score\n' + storage.bestScore, {
weight: 300,
size: 45,
fill: 0xFFFFFF,
anchorX: 0.5,
align: 'center'
});
bestScoreTxt.alpha = 0;
bestScoreTxt.x = -250;
LK.gui.topRight.addChild(bestScoreTxt);
var gameLogo = game.addChild(new GameLogo());
gameLogo.x = game.width / 2;
gameLogo.y = 700;
var instructionsTxt = new Text2("Welcome to colorful outer space!\n\nWe'll be collecting colors from all\nof the galaxies.\n\nSpace is endless - how far can you go?\n\nTap a planet of the color indicated below\nto get started.", {
weight: 800,
size: 90,
fill: 0xFFFFFF,
anchorX: 0.5,
align: 'center',
dropShadow: true,
dropShadowColor: '#000000',
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 5
});
instructionsTxt.x = game.width / 2 - instructionsTxt.width / 2;
instructionsTxt.y = game.height / 2;
game.addChild(instructionsTxt);
// Update dragging logic to correctly handle 'move' event
game.on('move', function (x, y, obj) {
if (draggedItem && gameEnded) {
var pos = game.toLocal(obj.global);
draggedItem.x = pos.x;
draggedItem.y = pos.y;
}
});
// Game tick
LK.on('tick', function () {
//console.log(particles.length);
stars.forEach(function (star, index) {
star._move_migrated();
});
if (gameStarted && !gameEnded) {
//console.log(LK.ticks);
if (LK.ticks > 0 && LK.ticks % 100 == 0) {
counter._update_migrated();
}
particles.forEach(function (particle, index) {
particle._move_migrated();
if (particle.alpha <= 0 || particle.y > game.height - 200) {
particles.splice(index, 1);
particle.destroy();
}
});
if (tweenProgress < tweenDuration) {
centerX += (targetX - centerX) / (tweenDuration - tweenProgress);
centerY += (targetY - centerY) / (tweenDuration - tweenProgress);
tweenProgress++;
}
}
});
A white triangle pointing down.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
A colorful rectangular button with the text "Play Again" with each letter in a different color picked from a nice palette.. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.