Code edit (1 edits merged)
Please save this source code
User prompt
Les zombies infligent 10 pv au robot
Code edit (6 edits merged)
Please save this source code
User prompt
Met autant de pv au robot qu'au zombie
User prompt
Affiche une barre de vie au dessus du robot aves ses points de vie restants
Code edit (1 edits merged)
Please save this source code
User prompt
Met la bar de point de vie des robot en vert et deux fois plus large et un peu plus haut
Code edit (4 edits merged)
Please save this source code
User prompt
La barre de vie du robot n'est pas visible
Code edit (1 edits merged)
Please save this source code
User prompt
met les points de vie du robot au premier plan
User prompt
La barre de vie des robot doit suivre le robot pendant ses mouvements
User prompt
Affiche les points de vie au dessus des robots en vert
Code edit (1 edits merged)
Please save this source code
User prompt
Ajoute des points de vie aux robot (20pv) et quand un zombie touche un robot le zombie disparait mais fait perdre 5pv au robot
User prompt
Fix Bug: 'Timeout.tick error: BloodSplatter.forEach is not a function' in this line: 'BloodSplatter.forEach(function (zombie) {' Line Number: 264
User prompt
Fix Bug: 'TypeError: BloodSplatter.forEach is not a function' in this line: 'BloodSplatter.forEach(function (zombie) {' Line Number: 253
User prompt
Fix Bug: 'TypeError: BloodSplatter.forEach is not a function' in this line: 'BloodSplatter.forEach(function (zombie) {' Line Number: 251
User prompt
Fix Bug: 'TypeError: BloodSplatter.forEach is not a function' in this line: 'BloodSplatter.forEach(function (zombie) {' Line Number: 249
Code edit (3 edits merged)
Please save this source code
User prompt
Quand un flash de type LK.effects.flashScreen est utilisé rend visible tous les zombies pendant 200ms
User prompt
Quand les robots tir ajoute un flash LK.effects.flashScreen(0xffffff, 100)
User prompt
Fix Bug: 'ReferenceError: killDIsplay is not defined' in this line: 'killDIsplay.killText.visible = false;' Line Number: 328
Code edit (1 edits merged)
Please save this source code
User prompt
A chaque tir du hero fait un "LK.effects.flashScreen" de 100ms
/**** * Classes ****/ var ZombieCountDisplay = Container.expand(function () { var self = Container.call(this); self.zombieCountText = new Text2('Zombies: 0', { size: 100, fill: "#ffffff" }); self.zombieCountText.anchor.set(1, 0); self.zombieCountText.y = 240; // Position below the credit display self.updateZombieCount = function (zombieCount) { self.zombieCountText.setText('Zombies: ' + zombieCount); }; LK.gui.topRight.addChild(self.zombieCountText); }); var BuyRobotButton = Container.expand(function () { var self = Container.call(this); self.buttonGraphics = self.createAsset('buyRobotButton', 'Buy Robot Button', 0.5, 0.5); self.buttonGraphics.interactive = true; self.buttonGraphics.buttonMode = true; self.buttonGraphics.tint = 0x808080; // Set the background color to grey self.buttonGraphics.zIndex = 100; self.cost = 40; self.costText = new Text2(self.cost + ' credits', { size: 50, fill: "#ffffff" }); self.costText.anchor.set(0.5, 0); self.costText.y = 80; // Position below the button self.addChild(self.costText); self.on('down', function (obj) { if (credits >= self.cost && (!robot || robot.length < 2)) { credits -= self.cost; creditDisplay.updateCredits(credits); var newRobot = new Robot(); newRobot.x = Math.random() * (2048 * 0.6) + 2048 * 0.2; var targetYPositions = [2732 / 2 + 150, 2732 / 2 - 150]; newRobot.y = 2732; // Start at the bottom of the screen robot = robot ? robot.concat(newRobot) : [newRobot]; // Assign unique target Y position to each robot newRobot.targetY = targetYPositions[robot.length % targetYPositions.length]; game.addChild(newRobot); } }); }); var ScoreDisplay = Container.expand(function () { var self = Container.call(this); self.scoreText = new Text2('Kills: 0', { size: 100, fill: "#ffffff" }); self.scoreText.anchor.set(1, 0); self.updateScore = function (score) { self.scoreText.setText('Kills: ' + score); }; LK.gui.topRight.addChild(self.scoreText); }); var MuzzleFlash = Container.expand(function () { var self = Container.call(this); var flashGraphics = self.createAsset('muzzleFlash', 'Muzzle flash', 0.5, 0.5); flashGraphics.alpha = 0.5; self.zIndex = -5; }); var BloodSplatter = Container.expand(function (type) { var self = Container.call(this); self.createBloodSplatter = function (type) { var assetName; switch (type) { case 1: assetName = 'bloodSplatter1'; break; case 2: assetName = 'bloodSplatter2'; break; case 3: assetName = 'bloodSplatter3'; break; default: assetName = 'bloodSplatter1'; } return self.createAsset(assetName, 'Blood splatter', 0.5, 0.5); }; var bloodGraphics = self.createBloodSplatter(type); bloodGraphics.rotation = Math.random() * Math.PI * 2; self.visible = false; }); var AmmoDisplay = Container.expand(function () { var self = Container.call(this); self.ammoText = new Text2('Ammo: 20', { size: 100, fill: "#ffffff" }); self.ammoText.anchor.set(1, 1); self.updateAmmo = function (ammoCount) { self.ammoText.setText('Ammo: ' + ammoCount); }; LK.gui.bottomRight.addChild(self.ammoText); }); var CreditDisplay = Container.expand(function () { var self = Container.call(this); self.creditText = new Text2('Credits: 0', { size: 100, fill: "#ffffff" }); self.creditText.anchor.set(1, 0); self.creditText.y = 120; // Position below the score display self.updateCredits = function (credits) { self.creditText.setText('Credits: ' + credits); }; LK.gui.topRight.addChild(self.creditText); }); // Define the Robot class var Robot = Container.expand(function () { var self = Container.call(this); var robotGraphics = self.createAsset('robot', 'Reinforcement robot', 0.5, 0.5); self.speed = 2; self.health = 20; self.lastShotTime = 0; self.move = function (targetY) { var stopPosition = 2732 * 0.6; // 40% from the bottom of the screen if (self.y > stopPosition) { self.y -= self.speed; } else { self.speed = 0; } }; self.shoot = function () { if (LK.ticks - self.lastShotTime >= 120) { var closestZombie = null; var closestDistance = Number.MAX_VALUE; for (var i = 0; i < zombies.length; i++) { var dx = self.x - zombies[i].x; var dy = self.y - zombies[i].y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestZombie = zombies[i]; } } if (closestZombie) { var angle = Math.atan2(closestZombie.y - self.y, closestZombie.x - self.x); robotGraphics.rotation = angle; // Orient the robot towards the target var bullet = new HeroBullet(); // Use HeroBullet for robot shooting bullet.x = self.x + Math.cos(angle) * 40; // Position the bullet at the robot's gun bullet.y = self.y + Math.sin(angle) * 40; // Position the bullet at the robot's gun bullet.rotation = angle; robotBullets.push(bullet); // Add to robotBullets array var muzzleFlash = new MuzzleFlash(); var flashOffsetX = 150 * Math.cos(angle); // Offset for muzzle flash to align with a longer barrel var flashOffsetY = 150 * Math.sin(angle); // Offset for muzzle flash to align with a longer barrel muzzleFlash.x = self.x + flashOffsetX; muzzleFlash.y = self.y + flashOffsetY; muzzleFlash.rotation = angle; // Orient MuzzleFlash in the same direction as the robot muzzleFlash.zIndex = 1; // Ensure MuzzleFlash appears above other game elements muzzleFlash.visible = true; // Make MuzzleFlash visible when shooting game.addChildAt(muzzleFlash, 0); LK.setTimeout(function () { muzzleFlash.destroy(); }, 200); game.addChildAt(muzzleFlash, 0); LK.setTimeout(function () { muzzleFlash.destroy(); }, 400); game.addChild(bullet); LK.effects.flashScreen(0xffffff, 100); } self.lastShotTime = LK.ticks; } }; }); // Define the RobotBullet class var RobotBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.createAsset('robotBullet', 'Robot bullet', 0.5, 1); self.speed = 10; self.move = function () { self.y -= self.speed; }; }); // Define the Hero class var Hero = Container.expand(function () { var self = Container.call(this); var heroGraphics = self.createAsset('hero', 'Hero character', 0.5, 0.5); self.ammo = 20; self.reloadTime = null; self.torchGraphics = self.createAsset('torch', 'Hero torch', 0.5, 0); self.torchGraphics.visible = false; self.orientTorch = function (mousePos) { var angle = Math.atan2(mousePos.y - self.y, mousePos.x - self.x); self.torchGraphics.rotation = angle; self.torchGraphics.visible = false; heroGraphics.rotation = angle; }; self.speed = 5; self.move = function (direction) { self.x += direction.x * self.speed; self.y += direction.y * self.speed; }; self.shoot = function (mousePos) { if (self.ammo > 0 && (!self.lastShotTime || LK.ticks - self.lastShotTime >= 10) && (!self.reloadTime || LK.ticks - self.reloadTime >= 180)) { var bullet = new HeroBullet(); bullet.x = self.x + 5; bullet.y = self.y - 80; var angle = Math.atan2(mousePos.y - self.y, mousePos.x - self.x); bullet.rotation = angle; bullets.push(bullet); game.addChild(bullet); self.lastShotTime = LK.ticks; self.ammo--; ammoDisplay.updateAmmo(self.ammo); var muzzleFlash = new MuzzleFlash(); var flashOffsetX = 80 * Math.cos(angle); // Offset for muzzle flash to align with the barrel var flashOffsetY = 80 * Math.sin(angle); // Offset for muzzle flash to align with the barrel muzzleFlash.x = self.x + flashOffsetX; muzzleFlash.y = self.y + flashOffsetY; muzzleFlash.rotation = angle; // Orient MuzzleFlash in the same direction as the torch muzzleFlash.zIndex = 1; // Ensure MuzzleFlash appears above other game elements muzzleFlash.visible = true; // Make MuzzleFlash visible when shooting game.addChildAt(muzzleFlash, 0); LK.setTimeout(function () { muzzleFlash.destroy(); }, 200); // Flash the screen for 100ms when the hero shoots LK.effects.flashScreen(0xffffff, 100); game.addChildAt(muzzleFlash, 0); LK.setTimeout(function () { muzzleFlash.destroy(); }, 400); } else if (self.ammo === 0 && (!self.reloadTime || LK.ticks - self.reloadTime >= 180)) { self.ammo = 20; ammoDisplay.updateAmmo(self.ammo); self.reloadTime = LK.ticks; } }; }); // Define the TorchLight class var TorchLight = Container.expand(function () { var self = Container.call(this); var lightGraphics = self.createAsset('torchLight', 'Torch light zone', 0.5, 1); self.updatePosition = function (heroPos, torchAngle) { self.x = heroPos.x; self.y = heroPos.y; self.rotation = torchAngle + Math.PI / 2; // Adjust the size and shape of the light zone // Adjust the size and shape of the light zone to simulate a cone of light lightGraphics.width = 600; // Width of the light cone lightGraphics.height = 8000; // Length of the light cone // Set the alpha to a lower value to simulate light lightGraphics.alpha = 0.3; // Set the pivot to the bottom center of the light cone lightGraphics.pivot.x = 0; lightGraphics.pivot.y = 0; }; }); // Define the HeroBullet class var HeroBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.createAsset('heroBullet', 'Hero bullet', 0.5, 1); self.speed = 50; self.move = function () { self.x += Math.cos(self.rotation) * self.speed; self.y += Math.sin(self.rotation) * self.speed; }; }); // Define the Zombie class var Zombie = Container.expand(function () { var self = Container.call(this); var zombieGraphics = self.createAsset('zombie', 'Zombie enemy', 0.5, 0.5); self.speed = 1 + Math.floor(score / 10) * 0.2; self.health = 50; self.healthBar = self.createAsset('healthBar', 'Zombie health bar', 0.5, 0); self.healthBar.width = self.health * 7; self.healthBar.height = 15; self.healthBar.y = -110; self.move = function (heroPos, torchAngle) { var targetPos = robot && robot.length > 0 && robot.some(function (r) { return r.health > 0; }) ? { x: robot.find(function (r) { return r.health > 0; }).x, y: robot.find(function (r) { return r.health > 0; }).y } : heroPos; var angleToTarget = Math.atan2(targetPos.y - self.y, targetPos.x - self.x); self.x += Math.cos(angleToTarget) * self.speed; self.y += Math.sin(angleToTarget) * self.speed; if (heroPos) { var angleToZombie = Math.atan2(self.y - heroPos.y, self.x - heroPos.x); var angleDifference = Math.abs(torchAngle - angleToZombie); if (angleDifference < 0.12) { // Assuming torch has a cone of visibility of 0.5 radians self.visible = true; } else { self.visible = false; } } self.healthBar.width = self.health * 10; }; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 // Init game with black background }); /**** * Game Code ****/ // Initialize important asset arrays function showCustomGameOverScreen() { var gameOverContainer = new Container(); var scoreText = new Text2('Score: ' + score, { size: 200, fill: "#ffffff" }); scoreText.anchor.set(0.5, 0); scoreText.x = 2048 / 2; scoreText.y = 200; gameOverContainer.addChild(scoreText); // Hide AmmoDisplay, CreditDisplay, and ZombieCountDisplay zombieCountDisplay.zombieCountText.visible = false; creditDisplay.creditText.visible = false; ammoDisplay.ammoText.visible = false; scoreDisplay.scoreText.visible = false; // Hide all other game elements for (var i = 0; i < game.children.length; i++) { if (game.children[i] !== gameOverContainer) { game.children[i].visible = false; } } // TODO: Implement score history display var closeButton = new Container(); var closeButtonText = new Text2('Close', { size: 100, fill: "#ffffff" }); closeButtonText.anchor.set(0.5, 0.5); closeButton.addChild(closeButtonText); closeButton.x = 2048 / 2; closeButton.y = 2732 - 200; closeButton.interactive = true; closeButton.buttonMode = true; closeButton.on('down', function () { gameOverContainer.destroy(); LK.showGameOver(); }); gameOverContainer.addChild(closeButton); game.addChild(gameOverContainer); } var robot; var robotBullets = []; var torchLight = game.addChild(new TorchLight()); var bullets = []; var zombies = []; var hero; var isGameOver = false; var score = 0; var ammoDisplay = new AmmoDisplay(); var credits = 0; var creditDisplay = new CreditDisplay(); var zombieCountDisplay = new ZombieCountDisplay(); var scoreDisplay = new ScoreDisplay(); // Create the hero hero = game.addChild(new Hero()); hero.x = 2048 / 2; hero.y = 2732 - 100; // Position hero near the bottom of the screen // Add BuyRobotButton to the game var buyRobotButton = game.addChild(new BuyRobotButton()); buyRobotButton.x = 150; // Position button at the bottom left buyRobotButton.y = 2732 - 150; // Game logic and event handlers LK.on('keydown', function (obj) { var direction = { x: 0, y: 0 }; var e = obj.event; switch (e.keyCode) { case 37: // left arrow direction.x = -1; break; case 39: // right arrow direction.x = 1; break; case 38: // up arrow direction.y = -1; break; case 40: // down arrow direction.y = 1; break; } hero.move(direction); }); LK.on('tick', function () { if (isGameOver) { showCustomGameOverScreen(); return; } // Move bullets and check for off-screen for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i]) { bullets[i].move(); for (var j = zombies.length - 1; j >= 0; j--) { if (bullets[i] && bullets[i].intersects(zombies[j])) { bullets[i].destroy(); bullets.splice(i, 1); zombies[j].health -= Math.floor(Math.random() * (20 + 1)) + 20; if (zombies[j].health <= 0) { var bloodSplatterType = Math.floor(Math.random() * 3) + 1; // Randomly choose a blood splatter type between 1 and 3 var bloodSplatter = new BloodSplatter(bloodSplatterType); bloodSplatter.x = zombies[j].x; bloodSplatter.y = zombies[j].y; game.addChildAt(bloodSplatter, 0); zombies[j].destroy(); zombies.splice(j, 1); score++; credits += Math.floor(Math.random() * 2) + 1; // Zombies now give a random amount of credits between 1 and 2 scoreDisplay.updateScore(score); creditDisplay.updateCredits(credits); zombieCountDisplay.updateZombieCount(zombies.length); } break; } } if (bullets[i] && (bullets[i].x < 0 || bullets[i].x > 2048 || bullets[i].y < 0 || bullets[i].y > 2732)) { bullets[i].destroy(); bullets.splice(i, 1); } } } // Handle torch orientation and make zombies visible if illuminated var torchPos = { x: hero.x, y: hero.y }; var torchAngle = hero.torchGraphics.rotation; // Update torch light position var heroPos = { x: hero.x, y: hero.y }; var torchAngle = hero.torchGraphics.rotation; torchLight.updatePosition(heroPos, torchAngle); // Update visibility of blood splatters based on torch light for (var i = game.children.length - 1; i >= 0; i--) { var obj = game.children[i]; if (obj instanceof BloodSplatter) { var distanceToTorch = Math.sqrt(Math.pow(obj.x - hero.x, 2) + Math.pow(obj.y - hero.y, 2)); var angleToTorch = Math.atan2(obj.y - hero.y, obj.x - hero.x) - torchAngle; // Check if within torch light angle and range if (distanceToTorch <= 8000 && Math.abs(angleToTorch) <= 0.12) { obj.visible = true; } else { obj.visible = false; } } } // Move and shoot with the robot if (robot && robot.length > 0) { for (var i = robot.length - 1; i >= 0; i--) { robot[i].move(robot[i].targetY); robot[i].shoot(); if (robot[i].y < -50 || robot[i].health <= 0) { // If the robot moves off-screen or dies robot[i].destroy(); robot.splice(i, 1); } } } // Move robot bullets, check for off-screen, and apply damage to zombies for (var i = robotBullets.length - 1; i >= 0; i--) { if (robotBullets[i]) { robotBullets[i].move(); for (var j = zombies.length - 1; j >= 0; j--) { if (robotBullets[i] && robotBullets[i].intersects(zombies[j])) { robotBullets[i].destroy(); robotBullets.splice(i, 1); zombies[j].health -= Math.floor(Math.random() * (20 + 1)) + 20; if (zombies[j].health <= 0) { var bloodSplatterType = Math.floor(Math.random() * 3) + 1; var bloodSplatter = new BloodSplatter(bloodSplatterType); bloodSplatter.x = zombies[j].x; bloodSplatter.y = zombies[j].y; game.addChildAt(bloodSplatter, 0); zombies[j].destroy(); zombies.splice(j, 1); score++; scoreDisplay.updateScore(score); } break; } } if (robotBullets[i] && robotBullets[i].y < 0) { robotBullets[i].destroy(); robotBullets.splice(i, 1); } } } // Move zombies and check for collision with hero and robot for (var j = zombies.length - 1; j >= 0; j--) { zombies[j].move(torchPos, torchAngle); if (zombies[j].y > 2732) { zombies[j].destroy(); zombies.splice(j, 1); } else if (zombies[j].intersects(hero) && zombies[j].visible) { isGameOver = true; } else if (robot) { for (var k = robot.length - 1; k >= 0; k--) { if (zombies[j].intersects(robot[k])) { robot[k].health -= 5; if (robot[k].health <= 0) { robot[k].destroy(); robot.splice(k, 1); } zombies[j].destroy(); zombies.splice(j, 1); } } } } game.on('move', function (obj) { var mousePos = obj.event.getLocalPosition(game); hero.orientTorch(mousePos); }); game.on('down', function (obj) { var mousePos = obj.event.getLocalPosition(game); hero.shoot(mousePos); }); // Spawn the robot reinforcement when the player purchases it // Removed the automatic robot spawn code block // Spawn zombies var spawnRate = Math.max(30, 120 - Math.floor(score / 5) * 5); if (LK.ticks % spawnRate == 0) { // Spawn a zombie every 2 seconds var zombie = new Zombie(); zombie.x = Math.random() * 2048; zombie.y = -50; // Start off-screen zombies.push(zombie); game.addChild(zombie); zombieCountDisplay.updateZombieCount(zombies.length); } /*if (LK.ticks === 1) { var zombie = new Zombie(); zombie.x = hero.x; // Spawn next to the player zombie.y = hero.y - 300; zombies.push(zombie); game.addChild(zombie); zombieCountDisplay.updateZombieCount(zombies.length); }*/ });
===================================================================
--- original.js
+++ change.js
@@ -114,9 +114,9 @@
var Robot = Container.expand(function () {
var self = Container.call(this);
var robotGraphics = self.createAsset('robot', 'Reinforcement robot', 0.5, 0.5);
self.speed = 2;
- self.health = 100;
+ self.health = 20;
self.lastShotTime = 0;
self.move = function (targetY) {
var stopPosition = 2732 * 0.6; // 40% from the bottom of the screen
if (self.y > stopPosition) {
@@ -163,30 +163,8 @@
muzzleFlash.destroy();
}, 400);
game.addChild(bullet);
LK.effects.flashScreen(0xffffff, 100);
- // Make all zombies visible for 200ms when a screen flash occurs
- var makeZombiesVisible = function makeZombiesVisible() {
- zombies.forEach(function (zombie) {
- zombie.visible = true;
- });
- game.children.forEach(function (obj) {
- if (obj instanceof BloodSplatter) {
- obj.visible = true;
- }
- });
- };
- makeZombiesVisible();
- LK.setTimeout(function () {
- zombies.forEach(function (zombie) {
- zombie.visible = false;
- });
- game.children.forEach(function (obj) {
- if (obj instanceof BloodSplatter) {
- obj.visible = false;
- }
- });
- }, 200);
}
self.lastShotTime = LK.ticks;
}
};
@@ -244,30 +222,12 @@
muzzleFlash.destroy();
}, 200);
// Flash the screen for 100ms when the hero shoots
LK.effects.flashScreen(0xffffff, 100);
- // Make all zombies visible for 200ms when a screen flash occurs
- var makeZombiesVisible = function makeZombiesVisible() {
- zombies.forEach(function (zombie) {
- zombie.visible = true;
- });
- game.children.forEach(function (obj) {
- if (obj instanceof BloodSplatter) {
- obj.visible = true;
- }
- });
- };
- makeZombiesVisible();
+ game.addChildAt(muzzleFlash, 0);
LK.setTimeout(function () {
- zombies.forEach(function (zombie) {
- zombie.visible = false;
- });
- game.children.forEach(function (obj) {
- if (obj instanceof BloodSplatter) {
- obj.visible = false;
- }
- });
- }, 200);
+ muzzleFlash.destroy();
+ }, 400);
} else if (self.ammo === 0 && (!self.reloadTime || LK.ticks - self.reloadTime >= 180)) {
self.ammo = 20;
ammoDisplay.updateAmmo(self.ammo);
self.reloadTime = LK.ticks;
@@ -555,11 +515,15 @@
isGameOver = true;
} else if (robot) {
for (var k = robot.length - 1; k >= 0; k--) {
if (zombies[j].intersects(robot[k])) {
- robot[k].health = 0;
- robot[k].destroy();
- robot.splice(k, 1);
+ robot[k].health -= 5;
+ if (robot[k].health <= 0) {
+ robot[k].destroy();
+ robot.splice(k, 1);
+ }
+ zombies[j].destroy();
+ zombies.splice(j, 1);
}
}
}
}
Un zombie en 2D vue du dessus. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Bullet. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
top down shooter blood. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
top down shooter blood texture. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
top down character with gun de dos. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. topdown shooter
top down robot with gun. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. topdown shooter
2d top down zombie boss. Single Game Texture. In-Game asset. 2d. no background. High contrast. No shadows.
weapon reload 2d icon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
Dark background horror. 2d. Blank background. High contrast. No shadows.
replace robot by wall
barbelé militaire 2d
Arrière plan sombre d'horreur avec un angle vu depuis le haut. 2d. Blank background. High contrast. No shadows.