/****
* 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.