/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bee = Container.expand(function () {
var self = Container.call(this);
var beeGraphics = self.attachAsset('bee', {
anchorX: 0.5,
anchorY: 0.5
});
// Define bee properties
self.velocityX = 0;
self.velocityY = 0;
self.speed = 12;
self.active = true;
// Direction indicators
var wingLeft = self.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.2,
x: -20,
y: 0,
tint: 0xFFFFFF
}));
var wingRight = self.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.2,
x: 20,
y: 0,
tint: 0xFFFFFF
}));
// Wing animation
var _animateWings = function animateWings() {
tween(wingLeft, {
scaleY: 0.4
}, {
duration: 100,
onFinish: function onFinish() {
tween(wingLeft, {
scaleY: 0.2
}, {
duration: 100,
onFinish: _animateWings
});
}
});
tween(wingRight, {
scaleY: 0.4
}, {
duration: 100,
onFinish: function onFinish() {
tween(wingRight, {
scaleY: 0.2
}, {
duration: 100
});
}
});
};
_animateWings();
// Set launch direction
self.launch = function (directionX, directionY) {
var magnitude = Math.sqrt(directionX * directionX + directionY * directionY);
self.velocityX = directionX / magnitude * self.speed;
self.velocityY = directionY / magnitude * self.speed;
// Rotate bee to face direction of travel
self.rotation = Math.atan2(directionY, directionX);
};
self.update = function () {
if (self.active) {
self.x += self.velocityX;
self.y += self.velocityY;
// Check if bee is off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.active = false;
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Add some visual interest with a pattern
var pattern = self.addChild(LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
tint: 0xC2185B
}));
// Define enemy properties
self.speed = 2 + Math.random() * 2; // Random speed between 2 and 4
self.health = 1;
self.active = true;
self.targetX = 0;
self.targetY = 0;
// Set target for the enemy to move toward
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function () {
self.health -= 1;
if (self.health <= 0) {
self.active = false;
// Flash before destruction
LK.effects.flashObject(self, 0xFFFFFF, 200);
LK.getSound('enemyHit').play();
} else {
// Flash red when hit but not destroyed
LK.effects.flashObject(self, 0xFF0000, 200);
}
};
self.update = function () {
if (self.active) {
// Calculate direction to target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize and apply speed
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
// Rotate enemy to face direction of travel
self.rotation = Math.atan2(dy, dx);
}
}
};
return self;
});
var Honeycomb = Container.expand(function () {
var self = Container.call(this);
var honeycombGraphics = self.attachAsset('honeycomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Add beehive in the center of honeycomb
var beehive = self.addChild(LK.getAsset('beehive', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
}));
// Add honey pots
var honeyPots = [];
for (var i = 0; i < 3; i++) {
var honey = self.addChild(LK.getAsset('honey', {
anchorX: 0.5,
anchorY: 0.5,
x: (i - 1) * 120,
y: 80
}));
honeyPots.push(honey);
}
// Set honeycomb properties
self.health = 3;
self.takeDamage = function () {
if (self.health > 0) {
self.health--;
// Remove a honey pot
if (honeyPots[self.health]) {
tween(honeyPots[self.health], {
alpha: 0
}, {
duration: 500
});
}
// Flash the beehive red
LK.effects.flashObject(beehive, 0xFF0000, 500);
LK.getSound('beehiveHit').play();
// Game over if health reaches 0
if (self.health <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// New background asset
// Game variables
var honeycomb;
var bees = [];
var enemies = [];
var score = 0;
var wave = 1;
var enemiesThisWave = 5;
var enemiesRemaining = 0;
var waveDelay = 5000; // 5 seconds between waves
var swipeStartX = 0;
var swipeStartY = 0;
var isSwipeActive = false;
var swipeLine = null;
// Initialize game elements
function initGame() {
// Attach background image
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
// Create honeycomb
honeycomb = new Honeycomb();
honeycomb.x = 2048 / 2;
honeycomb.y = 200;
game.addChild(honeycomb);
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0); // Top right alignment
LK.gui.topRight.addChild(scoreTxt);
// Initialize wave display
var waveTxt = new Text2('Wave: 1', {
size: 70,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0); // Top left alignment
waveTxt.x = 120; // Avoid the top-left 100x100 area
LK.gui.topLeft.addChild(waveTxt);
// Start the first wave
startWave();
// Start background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
// Update score and wave displays
function updateDisplay() {
scoreTxt.setText('Score: ' + score);
waveTxt.setText('Wave: ' + wave);
}
// Game swipe mechanics
game.down = function (x, y) {
// Start the swipe
swipeStartX = x;
swipeStartY = y;
isSwipeActive = true;
// Create visual indicator for the swipe
if (swipeLine) {
game.removeChild(swipeLine);
}
swipeLine = new Container();
var lineStart = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: swipeStartX,
y: swipeStartY,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFFFFFF
}));
game.addChild(swipeLine);
};
game.move = function (x, y) {
if (isSwipeActive && swipeLine) {
// Update the visual indicator
if (swipeLine.children.length > 1) {
game.removeChild(swipeLine);
swipeLine = new Container();
game.addChild(swipeLine);
}
var lineStart = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: swipeStartX,
y: swipeStartY,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFFFFFF
}));
var lineEnd = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFFFFFF
}));
// Draw a line of small dots between start and end
var dx = x - swipeStartX;
var dy = y - swipeStartY;
var distance = Math.sqrt(dx * dx + dy * dy);
var steps = Math.min(Math.floor(distance / 30), 10);
for (var i = 1; i < steps; i++) {
var dotX = swipeStartX + dx * i / steps;
var dotY = swipeStartY + dy * i / steps;
var dot = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: dotX,
y: dotY,
scaleX: 0.3,
scaleY: 0.3,
tint: 0xFFFFFF
}));
}
}
};
game.up = function (x, y) {
if (isSwipeActive) {
// Calculate swipe direction
var dx = x - swipeStartX;
var dy = y - swipeStartY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Minimum swipe distance to register
if (distance > 50) {
// Launch a bee in the swipe direction
var bee = new Bee();
bee.x = honeycomb.x;
bee.y = honeycomb.y;
bee.launch(dx, dy);
bees.push(bee);
game.addChild(bee);
LK.getSound('beeShoot').play();
}
// Reset swipe
isSwipeActive = false;
if (swipeLine) {
game.removeChild(swipeLine);
swipeLine = null;
}
}
};
// Start a new wave of enemies
function startWave() {
enemiesThisWave = 5 + (wave - 1) * 2; // Increase enemies per wave
enemiesRemaining = enemiesThisWave;
var _spawnEnemy = function spawnEnemy() {
if (enemiesRemaining <= 0) {
return;
}
// Determine spawn position (from edges of the screen)
var spawnSide = Math.floor(Math.random() * 3) + 1; // 1: right, 2: bottom, 3: left
var spawnX, spawnY;
switch (spawnSide) {
case 0:
// Top
spawnX = Math.random() * 2048;
spawnY = -100;
break;
case 1:
// Right
spawnX = 2148;
spawnY = Math.random() * 2732;
break;
case 2:
// Bottom
spawnX = Math.random() * 2048;
spawnY = 2832;
break;
case 3:
// Left
spawnX = -100;
spawnY = Math.random() * 2732;
break;
}
// Create and add enemy
var enemy = new Enemy();
enemy.x = spawnX;
enemy.y = spawnY;
enemy.setTarget(honeycomb.x, honeycomb.y);
enemy.health = Math.min(Math.floor(wave / 3) + 1, 3); // Increase enemy health based on wave
enemies.push(enemy);
game.addChild(enemy);
enemiesRemaining--;
// Schedule next enemy spawn
if (enemiesRemaining > 0) {
LK.setTimeout(_spawnEnemy, 1000 + Math.random() * 1000);
}
};
// Start spawning enemies
_spawnEnemy();
// Update wave display
updateDisplay();
}
// Check if wave is complete
function checkWaveCompletion() {
if (enemiesRemaining <= 0 && enemies.length === 0) {
// Start next wave after delay
wave++;
LK.setTimeout(function () {
startWave();
}, waveDelay);
// Show wave notification
var waveBanner = new Text2('Wave ' + wave + ' incoming!', {
size: 120,
fill: 0xFFFFFF
});
waveBanner.anchor.set(0.5, 0.5);
LK.gui.center.addChild(waveBanner);
// Remove the banner after a delay
LK.setTimeout(function () {
LK.gui.center.removeChild(waveBanner);
}, waveDelay - 500);
}
}
// Game update function
game.update = function () {
// Update bees
for (var i = bees.length - 1; i >= 0; i--) {
var bee = bees[i];
if (!bee.active) {
game.removeChild(bee);
bees.splice(i, 1);
continue;
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (!enemy.active) {
game.removeChild(enemy);
enemies.splice(j, 1);
score += 10 * wave; // Score based on wave
updateDisplay();
checkWaveCompletion();
continue;
}
// Check if enemy has reached the honeycomb
if (enemy.active && enemy.intersects(honeycomb)) {
honeycomb.takeDamage();
enemy.active = false;
game.removeChild(enemy);
enemies.splice(j, 1);
continue;
}
// Check for collisions with bees
for (var k = bees.length - 1; k >= 0; k--) {
var bee = bees[k];
if (bee.active && enemy.active && bee.intersects(enemy)) {
enemy.takeDamage();
bee.active = false;
game.removeChild(bee);
bees.splice(k, 1);
break;
}
}
}
};
}
// Initialize the game
initGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bee = Container.expand(function () {
var self = Container.call(this);
var beeGraphics = self.attachAsset('bee', {
anchorX: 0.5,
anchorY: 0.5
});
// Define bee properties
self.velocityX = 0;
self.velocityY = 0;
self.speed = 12;
self.active = true;
// Direction indicators
var wingLeft = self.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.2,
x: -20,
y: 0,
tint: 0xFFFFFF
}));
var wingRight = self.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.2,
x: 20,
y: 0,
tint: 0xFFFFFF
}));
// Wing animation
var _animateWings = function animateWings() {
tween(wingLeft, {
scaleY: 0.4
}, {
duration: 100,
onFinish: function onFinish() {
tween(wingLeft, {
scaleY: 0.2
}, {
duration: 100,
onFinish: _animateWings
});
}
});
tween(wingRight, {
scaleY: 0.4
}, {
duration: 100,
onFinish: function onFinish() {
tween(wingRight, {
scaleY: 0.2
}, {
duration: 100
});
}
});
};
_animateWings();
// Set launch direction
self.launch = function (directionX, directionY) {
var magnitude = Math.sqrt(directionX * directionX + directionY * directionY);
self.velocityX = directionX / magnitude * self.speed;
self.velocityY = directionY / magnitude * self.speed;
// Rotate bee to face direction of travel
self.rotation = Math.atan2(directionY, directionX);
};
self.update = function () {
if (self.active) {
self.x += self.velocityX;
self.y += self.velocityY;
// Check if bee is off screen
if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) {
self.active = false;
}
}
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Add some visual interest with a pattern
var pattern = self.addChild(LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
tint: 0xC2185B
}));
// Define enemy properties
self.speed = 2 + Math.random() * 2; // Random speed between 2 and 4
self.health = 1;
self.active = true;
self.targetX = 0;
self.targetY = 0;
// Set target for the enemy to move toward
self.setTarget = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.takeDamage = function () {
self.health -= 1;
if (self.health <= 0) {
self.active = false;
// Flash before destruction
LK.effects.flashObject(self, 0xFFFFFF, 200);
LK.getSound('enemyHit').play();
} else {
// Flash red when hit but not destroyed
LK.effects.flashObject(self, 0xFF0000, 200);
}
};
self.update = function () {
if (self.active) {
// Calculate direction to target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Normalize and apply speed
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
// Rotate enemy to face direction of travel
self.rotation = Math.atan2(dy, dx);
}
}
};
return self;
});
var Honeycomb = Container.expand(function () {
var self = Container.call(this);
var honeycombGraphics = self.attachAsset('honeycomb', {
anchorX: 0.5,
anchorY: 0.5
});
// Add beehive in the center of honeycomb
var beehive = self.addChild(LK.getAsset('beehive', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
}));
// Add honey pots
var honeyPots = [];
for (var i = 0; i < 3; i++) {
var honey = self.addChild(LK.getAsset('honey', {
anchorX: 0.5,
anchorY: 0.5,
x: (i - 1) * 120,
y: 80
}));
honeyPots.push(honey);
}
// Set honeycomb properties
self.health = 3;
self.takeDamage = function () {
if (self.health > 0) {
self.health--;
// Remove a honey pot
if (honeyPots[self.health]) {
tween(honeyPots[self.health], {
alpha: 0
}, {
duration: 500
});
}
// Flash the beehive red
LK.effects.flashObject(beehive, 0xFF0000, 500);
LK.getSound('beehiveHit').play();
// Game over if health reaches 0
if (self.health <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// New background asset
// Game variables
var honeycomb;
var bees = [];
var enemies = [];
var score = 0;
var wave = 1;
var enemiesThisWave = 5;
var enemiesRemaining = 0;
var waveDelay = 5000; // 5 seconds between waves
var swipeStartX = 0;
var swipeStartY = 0;
var isSwipeActive = false;
var swipeLine = null;
// Initialize game elements
function initGame() {
// Attach background image
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
// Create honeycomb
honeycomb = new Honeycomb();
honeycomb.x = 2048 / 2;
honeycomb.y = 200;
game.addChild(honeycomb);
// Initialize score display
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0); // Top right alignment
LK.gui.topRight.addChild(scoreTxt);
// Initialize wave display
var waveTxt = new Text2('Wave: 1', {
size: 70,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0); // Top left alignment
waveTxt.x = 120; // Avoid the top-left 100x100 area
LK.gui.topLeft.addChild(waveTxt);
// Start the first wave
startWave();
// Start background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
// Update score and wave displays
function updateDisplay() {
scoreTxt.setText('Score: ' + score);
waveTxt.setText('Wave: ' + wave);
}
// Game swipe mechanics
game.down = function (x, y) {
// Start the swipe
swipeStartX = x;
swipeStartY = y;
isSwipeActive = true;
// Create visual indicator for the swipe
if (swipeLine) {
game.removeChild(swipeLine);
}
swipeLine = new Container();
var lineStart = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: swipeStartX,
y: swipeStartY,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFFFFFF
}));
game.addChild(swipeLine);
};
game.move = function (x, y) {
if (isSwipeActive && swipeLine) {
// Update the visual indicator
if (swipeLine.children.length > 1) {
game.removeChild(swipeLine);
swipeLine = new Container();
game.addChild(swipeLine);
}
var lineStart = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: swipeStartX,
y: swipeStartY,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFFFFFF
}));
var lineEnd = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y,
scaleX: 0.5,
scaleY: 0.5,
tint: 0xFFFFFF
}));
// Draw a line of small dots between start and end
var dx = x - swipeStartX;
var dy = y - swipeStartY;
var distance = Math.sqrt(dx * dx + dy * dy);
var steps = Math.min(Math.floor(distance / 30), 10);
for (var i = 1; i < steps; i++) {
var dotX = swipeStartX + dx * i / steps;
var dotY = swipeStartY + dy * i / steps;
var dot = swipeLine.addChild(LK.getAsset('bee', {
anchorX: 0.5,
anchorY: 0.5,
x: dotX,
y: dotY,
scaleX: 0.3,
scaleY: 0.3,
tint: 0xFFFFFF
}));
}
}
};
game.up = function (x, y) {
if (isSwipeActive) {
// Calculate swipe direction
var dx = x - swipeStartX;
var dy = y - swipeStartY;
var distance = Math.sqrt(dx * dx + dy * dy);
// Minimum swipe distance to register
if (distance > 50) {
// Launch a bee in the swipe direction
var bee = new Bee();
bee.x = honeycomb.x;
bee.y = honeycomb.y;
bee.launch(dx, dy);
bees.push(bee);
game.addChild(bee);
LK.getSound('beeShoot').play();
}
// Reset swipe
isSwipeActive = false;
if (swipeLine) {
game.removeChild(swipeLine);
swipeLine = null;
}
}
};
// Start a new wave of enemies
function startWave() {
enemiesThisWave = 5 + (wave - 1) * 2; // Increase enemies per wave
enemiesRemaining = enemiesThisWave;
var _spawnEnemy = function spawnEnemy() {
if (enemiesRemaining <= 0) {
return;
}
// Determine spawn position (from edges of the screen)
var spawnSide = Math.floor(Math.random() * 3) + 1; // 1: right, 2: bottom, 3: left
var spawnX, spawnY;
switch (spawnSide) {
case 0:
// Top
spawnX = Math.random() * 2048;
spawnY = -100;
break;
case 1:
// Right
spawnX = 2148;
spawnY = Math.random() * 2732;
break;
case 2:
// Bottom
spawnX = Math.random() * 2048;
spawnY = 2832;
break;
case 3:
// Left
spawnX = -100;
spawnY = Math.random() * 2732;
break;
}
// Create and add enemy
var enemy = new Enemy();
enemy.x = spawnX;
enemy.y = spawnY;
enemy.setTarget(honeycomb.x, honeycomb.y);
enemy.health = Math.min(Math.floor(wave / 3) + 1, 3); // Increase enemy health based on wave
enemies.push(enemy);
game.addChild(enemy);
enemiesRemaining--;
// Schedule next enemy spawn
if (enemiesRemaining > 0) {
LK.setTimeout(_spawnEnemy, 1000 + Math.random() * 1000);
}
};
// Start spawning enemies
_spawnEnemy();
// Update wave display
updateDisplay();
}
// Check if wave is complete
function checkWaveCompletion() {
if (enemiesRemaining <= 0 && enemies.length === 0) {
// Start next wave after delay
wave++;
LK.setTimeout(function () {
startWave();
}, waveDelay);
// Show wave notification
var waveBanner = new Text2('Wave ' + wave + ' incoming!', {
size: 120,
fill: 0xFFFFFF
});
waveBanner.anchor.set(0.5, 0.5);
LK.gui.center.addChild(waveBanner);
// Remove the banner after a delay
LK.setTimeout(function () {
LK.gui.center.removeChild(waveBanner);
}, waveDelay - 500);
}
}
// Game update function
game.update = function () {
// Update bees
for (var i = bees.length - 1; i >= 0; i--) {
var bee = bees[i];
if (!bee.active) {
game.removeChild(bee);
bees.splice(i, 1);
continue;
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (!enemy.active) {
game.removeChild(enemy);
enemies.splice(j, 1);
score += 10 * wave; // Score based on wave
updateDisplay();
checkWaveCompletion();
continue;
}
// Check if enemy has reached the honeycomb
if (enemy.active && enemy.intersects(honeycomb)) {
honeycomb.takeDamage();
enemy.active = false;
game.removeChild(enemy);
enemies.splice(j, 1);
continue;
}
// Check for collisions with bees
for (var k = bees.length - 1; k >= 0; k--) {
var bee = bees[k];
if (bee.active && enemy.active && bee.intersects(enemy)) {
enemy.takeDamage();
bee.active = false;
game.removeChild(bee);
bees.splice(k, 1);
break;
}
}
}
};
}
// Initialize the game
initGame();
2d colorfull ghibli image style. forest quite one beehive at a tree body of forest Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
beehive patter 2d color. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows