/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var BiedronkaShop = Container.expand(function () { var self = Container.call(this); var shopGraphics = self.attachAsset('biedronka', { anchorX: 0, anchorY: 0 }); return self; }); var Building = Container.expand(function () { var self = Container.call(this); var buildingGraphics = self.attachAsset('building', { anchorX: 0, anchorY: 0 }); return self; }); var Destination = Container.expand(function () { var self = Container.call(this); var destinationGraphics = self.attachAsset('destination', { anchorX: 0.5, anchorY: 0.5 }); self.pulse = function () { tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { self.pulse(); } }); } }); }; return self; }); var GroceryStore = Container.expand(function () { var self = Container.call(this); self.items = [{ name: 'Bread', price: 10, health: 5 }, { name: 'Milk', price: 15, health: 8 }, { name: 'Apples', price: 12, health: 6 }, { name: 'Cheese', price: 20, health: 10 }, { name: 'Water', price: 5, health: 3 }]; self.show = function () { // Create store background var storeBg = LK.getAsset('road', { scaleX: 15, scaleY: 18, x: 1024, y: 1366, anchorX: 0.5, anchorY: 0.5 }); storeBg.alpha = 0.95; game.addChild(storeBg); // Store title - change to Zabka in Czech Republic or Romania var storeName = 'Biedronka Grocery Store'; if (currentCountry === 1 || currentCountry === 4) { // Czech Republic or Romania storeName = 'Zabka Grocery Store'; } var storeTitle = new Text2(storeName, { size: 70, fill: 0x00ff00 }); storeTitle.anchor.set(0.5, 0); storeTitle.x = 1024; storeTitle.y = 800; game.addChild(storeTitle); // Player stats var playerCoins = storage.coins || 0; var playerHealth = storage.health || 100; var statsText = new Text2('Coins: ' + playerCoins + ' | Health: ' + playerHealth, { size: 50, fill: 0xffffff }); statsText.anchor.set(0.5, 0); statsText.x = 1024; statsText.y = 900; game.addChild(statsText); // Items display var itemsContainer = new Container(); itemsContainer.x = 1024; itemsContainer.y = 1100; game.addChild(itemsContainer); for (var i = 0; i < self.items.length; i++) { var item = self.items[i]; var itemBg = LK.getAsset('road', { scaleX: 6, scaleY: 1.5, x: 0, y: i * 120, anchorX: 0.5, anchorY: 0.5 }); itemBg.alpha = 0.7; itemsContainer.addChild(itemBg); var itemText = new Text2(item.name + ' - ' + item.price + ' coins (+' + item.health + ' health)', { size: 45, fill: playerCoins >= item.price ? 0x00ff00 : 0xff0000 }); itemText.anchor.set(0.5, 0.5); itemText.x = 0; itemText.y = i * 120; itemsContainer.addChild(itemText); // Store item data for click detection itemBg.itemData = item; itemBg.itemIndex = i; } // Travel button var travelButton = LK.getAsset('road', { scaleX: 4, scaleY: 1.5, x: 1024, y: 1700, anchorX: 0.5, anchorY: 0.5 }); travelButton.alpha = 0.6; game.addChild(travelButton); var travelText = new Text2('Travel to Country', { size: 45, fill: 0xffff00 }); travelText.anchor.set(0.5, 0.5); travelText.x = 1024; travelText.y = 1700; game.addChild(travelText); // Close button var closeButton = LK.getAsset('road', { scaleX: 4, scaleY: 1.5, x: 1024, y: 1800, anchorX: 0.5, anchorY: 0.5 }); closeButton.alpha = 0.8; game.addChild(closeButton); var closeText = new Text2('Close Shop', { size: 50, fill: 0xffffff }); closeText.anchor.set(0.5, 0.5); closeText.x = 1024; closeText.y = 1800; game.addChild(closeText); // Store references for cleanup self.storeElements = [storeBg, storeTitle, statsText, itemsContainer, travelButton, travelText, closeButton, closeText]; // Handle purchases var handlePurchase = function handlePurchase(x, y, obj) { // Check if clicking on items var localPos = itemsContainer.toLocal({ x: x, y: y }); var itemIndex = Math.floor((localPos.y + 60) / 120); if (itemIndex >= 0 && itemIndex < self.items.length) { var item = self.items[itemIndex]; var currentCoins = storage.coins || 0; if (currentCoins >= item.price) { // Purchase item storage.coins = currentCoins - item.price; storage.health = Math.min(100, (storage.health || 100) + item.health); // Update score LK.setScore(LK.getScore() + item.health * 2); scoreTxt.setText('Score: ' + LK.getScore()); // Flash green for successful purchase LK.effects.flashScreen(0x00ff00, 300); // Close and reopen to refresh display self.close(); LK.setTimeout(function () { self.show(); }, 100); } else { // Not enough coins LK.effects.flashScreen(0xff0000, 300); } return; } // Check if clicking travel button if (Math.abs(x - 1024) < 240 && Math.abs(y - 1700) < 90) { self.close(); self.showTravelMenu(); return; } // Check if clicking close button if (Math.abs(x - 1024) < 240 && Math.abs(y - 1800) < 90) { self.close(); } }; game.down = handlePurchase; }; self.close = function () { if (self.storeElements) { for (var i = 0; i < self.storeElements.length; i++) { self.storeElements[i].destroy(); } self.storeElements = null; } // Restore game activity and normal game controls isGameActive = true; game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; initializeLevel(); } lastTouchX = x; lastTouchY = y; }; game.up = function (x, y, obj) { if (!gameStarted || !isGameActive) return; var deltaX = x - lastTouchX; var deltaY = y - lastTouchY; if (Math.abs(deltaX) > minSwipeDistance || Math.abs(deltaY) > minSwipeDistance) { if (Math.abs(deltaX) > Math.abs(deltaY)) { handleMovement(deltaX > 0 ? 1 : -1, 0); } else { handleMovement(0, deltaY > 0 ? 1 : -1); } } }; }; self.showTravelMenu = function () { // Disable game activity to prevent character movement isGameActive = false; // Create travel background var travelBg = LK.getAsset('road', { scaleX: 15, scaleY: 18, x: 1024, y: 1366, anchorX: 0.5, anchorY: 0.5 }); travelBg.alpha = 0.95; game.addChild(travelBg); // Travel title var travelTitle = new Text2('Travel to Eastern Bloc', { size: 70, fill: 0xffff00 }); travelTitle.anchor.set(0.5, 0); travelTitle.x = 1024; travelTitle.y = 800; game.addChild(travelTitle); // Current country display var currentCountryText = new Text2('Current: ' + easternBlocCountries[currentCountry].name, { size: 50, fill: 0x00ff00 }); currentCountryText.anchor.set(0.5, 0); currentCountryText.x = 1024; currentCountryText.y = 900; game.addChild(currentCountryText); // Player coins display var playerCoins = storage.coins || 0; var coinsText = new Text2('Coins: ' + playerCoins, { size: 50, fill: 0xffffff }); coinsText.anchor.set(0.5, 0); coinsText.x = 1024; coinsText.y = 960; game.addChild(coinsText); // Countries list var countriesContainer = new Container(); countriesContainer.x = 1024; countriesContainer.y = 1100; game.addChild(countriesContainer); for (var i = 0; i < easternBlocCountries.length; i++) { var country = easternBlocCountries[i]; if (i === currentCountry) continue; // Skip current country var countryBg = LK.getAsset('road', { scaleX: 8, scaleY: 1.5, x: 0, y: (i - (i > currentCountry ? 1 : 0)) * 100, anchorX: 0.5, anchorY: 0.5 }); countryBg.alpha = country.unlocked || playerCoins >= country.cost ? 0.7 : 0.3; countriesContainer.addChild(countryBg); var countryText = new Text2(country.name + (country.cost > 0 ? ' - ' + country.cost + ' coins' : ''), { size: 40, fill: country.unlocked || playerCoins >= country.cost ? 0x00ff00 : 0xff0000 }); countryText.anchor.set(0.5, 0.5); countryText.x = 0; countryText.y = (i - (i > currentCountry ? 1 : 0)) * 100; countriesContainer.addChild(countryText); countryBg.countryIndex = i; } // Close travel button var closeTravelButton = LK.getAsset('road', { scaleX: 4, scaleY: 1.5, x: 1024, y: 1800, anchorX: 0.5, anchorY: 0.5 }); closeTravelButton.alpha = 0.8; game.addChild(closeTravelButton); var closeTravelText = new Text2('Back to Shop', { size: 50, fill: 0xffffff }); closeTravelText.anchor.set(0.5, 0.5); closeTravelText.x = 1024; closeTravelText.y = 1800; game.addChild(closeTravelText); // Store elements for cleanup self.travelElements = [travelBg, travelTitle, currentCountryText, coinsText, countriesContainer, closeTravelButton, closeTravelText]; // Handle travel selection var handleTravel = function handleTravel(x, y, obj) { // Check countries list var localPos = countriesContainer.toLocal({ x: x, y: y }); var countryIndex = Math.floor((localPos.y + 50) / 100); // Adjust for skipped current country var actualIndex = countryIndex >= currentCountry ? countryIndex + 1 : countryIndex; if (actualIndex >= 0 && actualIndex < easternBlocCountries.length && actualIndex !== currentCountry) { var country = easternBlocCountries[actualIndex]; var currentCoins = storage.coins || 0; if (country.unlocked || currentCoins >= country.cost) { if (!country.unlocked && country.cost > 0) { storage.coins = currentCoins - country.cost; country.unlocked = true; } currentCountry = actualIndex; // Travel successful LK.effects.flashScreen(0x00ff00, 500); LK.setScore(LK.getScore() + 100); scoreTxt.setText('Score: ' + LK.getScore()); self.closeTravelMenu(); self.show(); // Return to shop } else { // Can't afford travel LK.effects.flashScreen(0xff0000, 300); } return; } // Check close button if (Math.abs(x - 1024) < 240 && Math.abs(y - 1800) < 90) { self.closeTravelMenu(); self.show(); // Return to shop } }; game.down = handleTravel; }; self.closeTravelMenu = function () { if (self.travelElements) { for (var i = 0; i < self.travelElements.length; i++) { self.travelElements[i].destroy(); } self.travelElements = null; } // Restore game activity when closing travel menu isGameActive = true; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 0; self.gridY = 0; self.isMoving = false; self.moveToGrid = function (newGridX, newGridY) { if (self.isMoving) return false; var targetX = newGridX * GRID_SIZE + GRID_SIZE / 2; var targetY = newGridY * GRID_SIZE + GRID_SIZE / 2; self.isMoving = true; self.gridX = newGridX; self.gridY = newGridY; tween(self, { x: targetX, y: targetY }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { self.isMoving = false; LK.getSound('move').play(); } }); return true; }; return self; }); var Road = Container.expand(function () { var self = Container.call(this); var roadGraphics = self.attachAsset('road', { anchorX: 0, anchorY: 0 }); return self; }); var SovietGuard = Container.expand(function () { var self = Container.call(this); var guardGraphics = self.attachAsset('guard', { anchorX: 0.5, anchorY: 0.5 }); self.centerX = 0; self.centerY = 0; self.radius = 60; self.angle = 0; self.speed = 0.05; self.startCircularMovement = function () { self.angle = 0; self.circularTween(); }; self.circularTween = function () { tween(self, { angle: self.angle + Math.PI * 2 }, { duration: 4000, easing: tween.linear, onFinish: function onFinish() { self.circularTween(); } }); }; self.update = function () { self.x = self.centerX + Math.cos(self.angle) * self.radius; self.y = self.centerY + Math.sin(self.angle) * self.radius; }; return self; }); var ZabkaShop = Container.expand(function () { var self = Container.call(this); var shopGraphics = self.attachAsset('zabka', { anchorX: 0, anchorY: 0 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x263238 }); /**** * Game Code ****/ var GRID_SIZE = 120; var GRID_WIDTH = 17; var GRID_HEIGHT = 22; var currentLevel = 1; var timeLeft = 60; var isGameActive = true; var gameStarted = false; var cityNames = ['Toruń', 'Białystok', 'Lublin', 'Katowice', 'Gdańsk', 'Wrocław', 'Poznań', 'Kraków', 'Łódź', 'Warsaw']; var easternBlocCountries = [{ name: 'Poland', cost: 0, unlocked: true }, { name: 'Czech Republic', cost: 100, unlocked: false }, { name: 'Hungary', cost: 200, unlocked: false }, { name: 'East Germany', cost: 300, unlocked: false }, { name: 'Romania', cost: 400, unlocked: false }, { name: 'Bulgaria', cost: 500, unlocked: false }, { name: 'Yugoslavia', cost: 600, unlocked: false }, { name: 'Soviet Union', cost: 1000, unlocked: false }]; var currentCountry = 0; // Initialize storage with defaults if (storage.coins === undefined) storage.coins = 50; if (storage.health === undefined) storage.health = 100; var groceryStore = new GroceryStore(); var cityGrid = []; var player; var destination; var obstacles = []; var buildings = []; var guards = []; var biedronkas = []; var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var timeTxt = new Text2('Time: 60', { size: 60, fill: 0xFFFFFF }); timeTxt.anchor.set(0.5, 0); timeTxt.y = 80; LK.gui.top.addChild(timeTxt); var levelTxt = new Text2('Village', { size: 50, fill: 0xFFFFFF }); levelTxt.anchor.set(1, 0); LK.gui.topRight.addChild(levelTxt); levelTxt.x = -20; levelTxt.y = 20; function initializeGrid() { cityGrid = []; for (var x = 0; x < GRID_WIDTH; x++) { cityGrid[x] = []; for (var y = 0; y < GRID_HEIGHT; y++) { cityGrid[x][y] = 'road'; } } } function createBuildings() { buildings = []; var buildingCount = Math.min(8 + currentLevel * 2, 20); for (var i = 0; i < buildingCount; i++) { var building = new Building(); var gridX = Math.floor(Math.random() * (GRID_WIDTH - 2)) + 1; var gridY = Math.floor(Math.random() * (GRID_HEIGHT - 2)) + 1; building.x = gridX * GRID_SIZE; building.y = gridY * GRID_SIZE; game.addChild(building); buildings.push(building); cityGrid[gridX][gridY] = 'building'; if (gridX + 1 < GRID_WIDTH) cityGrid[gridX + 1][gridY] = 'building'; } } function createObstacles() { obstacles = []; var obstacleCount = Math.min(3 + currentLevel, 12); for (var i = 0; i < obstacleCount; i++) { var attempts = 0; var gridX, gridY; do { gridX = Math.floor(Math.random() * GRID_WIDTH); gridY = Math.floor(Math.random() * GRID_HEIGHT); attempts++; } while (cityGrid[gridX][gridY] !== 'road' && attempts < 50); if (attempts < 50) { var obstacle = new Obstacle(); obstacle.x = gridX * GRID_SIZE + GRID_SIZE / 2; obstacle.y = gridY * GRID_SIZE + GRID_SIZE / 2; game.addChild(obstacle); obstacles.push(obstacle); cityGrid[gridX][gridY] = 'obstacle'; } } } function createGuards() { guards = []; var guardCount = Math.min(2 + Math.floor(currentLevel / 2), 6); for (var i = 0; i < guardCount; i++) { var attempts = 0; var gridX, gridY; do { gridX = Math.floor(Math.random() * GRID_WIDTH); gridY = Math.floor(Math.random() * GRID_HEIGHT); attempts++; } while (cityGrid[gridX][gridY] !== 'road' && attempts < 50); if (attempts < 50) { var guard = new SovietGuard(); guard.centerX = gridX * GRID_SIZE + GRID_SIZE / 2; guard.centerY = gridY * GRID_SIZE + GRID_SIZE / 2; guard.x = guard.centerX; guard.y = guard.centerY; game.addChild(guard); guards.push(guard); guard.startCircularMovement(); } } } function showGroceryStorePopup() { // Pause game activity isGameActive = false; // Show the grocery store groceryStore.show(); } function createBiedronkas() { biedronkas = []; var biedronkaCount = Math.min(1 + Math.floor(currentLevel / 3), 4); for (var i = 0; i < biedronkaCount; i++) { var attempts = 0; var gridX, gridY; do { gridX = Math.floor(Math.random() * (GRID_WIDTH - 2)) + 1; gridY = Math.floor(Math.random() * (GRID_HEIGHT - 2)) + 1; attempts++; } while (cityGrid[gridX][gridY] !== 'road' && attempts < 50); if (attempts < 50) { var biedronka; if (currentCountry === 1 || currentCountry === 4) { // Czech Republic or Romania - use Zabka biedronka = new ZabkaShop(); } else { // Other countries - use Biedronka biedronka = new BiedronkaShop(); } biedronka.x = gridX * GRID_SIZE; biedronka.y = gridY * GRID_SIZE; game.addChild(biedronka); biedronkas.push(biedronka); cityGrid[gridX][gridY] = 'biedronka'; if (gridX + 1 < GRID_WIDTH) cityGrid[gridX + 1][gridY] = 'biedronka'; } } } function createDestination() { var attempts = 0; var gridX, gridY; do { gridX = Math.floor(Math.random() * GRID_WIDTH); gridY = Math.floor(Math.random() * GRID_HEIGHT); attempts++; } while (cityGrid[gridX][gridY] !== 'road' && attempts < 100); destination = new Destination(); destination.x = gridX * GRID_SIZE + GRID_SIZE / 2; destination.y = gridY * GRID_SIZE + GRID_SIZE / 2; destination.gridX = gridX; destination.gridY = gridY; game.addChild(destination); destination.pulse(); cityGrid[gridX][gridY] = 'destination'; } function createPlayer() { var attempts = 0; var gridX, gridY; do { gridX = Math.floor(Math.random() * GRID_WIDTH); gridY = Math.floor(Math.random() * GRID_HEIGHT); attempts++; } while (cityGrid[gridX][gridY] !== 'road' && attempts < 100); player = new Player(); player.gridX = gridX; player.gridY = gridY; player.x = gridX * GRID_SIZE + GRID_SIZE / 2; player.y = gridY * GRID_SIZE + GRID_SIZE / 2; game.addChild(player); } function isValidMove(gridX, gridY) { if (gridX < 0 || gridX >= GRID_WIDTH || gridY < 0 || gridY >= GRID_HEIGHT) { return false; } var cellType = cityGrid[gridX][gridY]; return cellType === 'road' || cellType === 'destination' || cellType === 'biedronka'; } function checkWin() { // Check collision with guards for (var i = 0; i < guards.length; i++) { if (player.intersects(guards[i])) { LK.getSound('blocked').play(); LK.effects.flashScreen(0xff0000, 500); isGameActive = false; LK.showGameOver(); return; } } // Check interaction with Biedronka shops for (var i = 0; i < biedronkas.length; i++) { if (player.intersects(biedronkas[i])) { // Add coins for visiting Biedronka storage.coins = (storage.coins || 0) + 25; // Show grocery store showGroceryStorePopup(); // Give bonus points for visiting Biedronka LK.setScore(LK.getScore() + 50); scoreTxt.setText('Score: ' + LK.getScore()); // Flash green to show successful interaction LK.effects.flashScreen(0x00ff00, 300); // Remove the visited Biedronka biedronkas[i].destroy(); biedronkas.splice(i, 1); break; } } if (player.gridX === destination.gridX && player.gridY === destination.gridY) { var timeBonus = Math.floor(timeLeft * 10); var levelBonus = currentLevel * 100; LK.setScore(LK.getScore() + timeBonus + levelBonus); LK.getSound('complete').play(); LK.effects.flashScreen(0x4CAF50, 500); currentLevel++; if (currentLevel > 10) { LK.showYouWin(); } else { initializeLevel(); } } } function initializeLevel() { for (var i = buildings.length - 1; i >= 0; i--) { buildings[i].destroy(); } for (var i = obstacles.length - 1; i >= 0; i--) { obstacles[i].destroy(); } for (var i = guards.length - 1; i >= 0; i--) { guards[i].destroy(); } for (var i = biedronkas.length - 1; i >= 0; i--) { biedronkas[i].destroy(); } if (destination) destination.destroy(); if (player) player.destroy(); buildings = []; obstacles = []; guards = []; biedronkas = []; initializeGrid(); createBuildings(); createObstacles(); createGuards(); createBiedronkas(); createDestination(); createPlayer(); timeLeft = Math.max(30, 80 - currentLevel * 3); var cityName = cityNames[Math.min(currentLevel - 1, cityNames.length - 1)]; levelTxt.setText(cityName); scoreTxt.setText('Score: ' + LK.getScore()); timeTxt.setText('Time: ' + timeLeft); } function handleMovement(deltaX, deltaY) { if (!isGameActive || !gameStarted || player.isMoving) return; var newGridX = player.gridX + deltaX; var newGridY = player.gridY + deltaY; if (isValidMove(newGridX, newGridY)) { if (player.moveToGrid(newGridX, newGridY)) { checkWin(); } } else { LK.getSound('blocked').play(); } } var lastTouchX = 0; var lastTouchY = 0; var minSwipeDistance = 50; game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; initializeLevel(); } lastTouchX = x; lastTouchY = y; }; game.up = function (x, y, obj) { if (!gameStarted || !isGameActive) return; var deltaX = x - lastTouchX; var deltaY = y - lastTouchY; if (Math.abs(deltaX) > minSwipeDistance || Math.abs(deltaY) > minSwipeDistance) { if (Math.abs(deltaX) > Math.abs(deltaY)) { handleMovement(deltaX > 0 ? 1 : -1, 0); } else { handleMovement(0, deltaY > 0 ? 1 : -1); } } }; var gameTimer = null; game.update = function () { if (!gameStarted || !isGameActive) return; if (LK.ticks % 60 === 0 && timeLeft > 0) { timeLeft--; timeTxt.setText('Time: ' + timeLeft); if (timeLeft <= 0) { isGameActive = false; LK.showGameOver(); } } }; var instructionTxt = new Text2('Swipe to navigate through the city\nReach the golden destination!\nTap to start', { size: 50, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 0.5); instructionTxt.x = 1024; instructionTxt.y = 1366; game.addChild(instructionTxt);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var BiedronkaShop = Container.expand(function () {
var self = Container.call(this);
var shopGraphics = self.attachAsset('biedronka', {
anchorX: 0,
anchorY: 0
});
return self;
});
var Building = Container.expand(function () {
var self = Container.call(this);
var buildingGraphics = self.attachAsset('building', {
anchorX: 0,
anchorY: 0
});
return self;
});
var Destination = Container.expand(function () {
var self = Container.call(this);
var destinationGraphics = self.attachAsset('destination', {
anchorX: 0.5,
anchorY: 0.5
});
self.pulse = function () {
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.pulse();
}
});
}
});
};
return self;
});
var GroceryStore = Container.expand(function () {
var self = Container.call(this);
self.items = [{
name: 'Bread',
price: 10,
health: 5
}, {
name: 'Milk',
price: 15,
health: 8
}, {
name: 'Apples',
price: 12,
health: 6
}, {
name: 'Cheese',
price: 20,
health: 10
}, {
name: 'Water',
price: 5,
health: 3
}];
self.show = function () {
// Create store background
var storeBg = LK.getAsset('road', {
scaleX: 15,
scaleY: 18,
x: 1024,
y: 1366,
anchorX: 0.5,
anchorY: 0.5
});
storeBg.alpha = 0.95;
game.addChild(storeBg);
// Store title - change to Zabka in Czech Republic or Romania
var storeName = 'Biedronka Grocery Store';
if (currentCountry === 1 || currentCountry === 4) {
// Czech Republic or Romania
storeName = 'Zabka Grocery Store';
}
var storeTitle = new Text2(storeName, {
size: 70,
fill: 0x00ff00
});
storeTitle.anchor.set(0.5, 0);
storeTitle.x = 1024;
storeTitle.y = 800;
game.addChild(storeTitle);
// Player stats
var playerCoins = storage.coins || 0;
var playerHealth = storage.health || 100;
var statsText = new Text2('Coins: ' + playerCoins + ' | Health: ' + playerHealth, {
size: 50,
fill: 0xffffff
});
statsText.anchor.set(0.5, 0);
statsText.x = 1024;
statsText.y = 900;
game.addChild(statsText);
// Items display
var itemsContainer = new Container();
itemsContainer.x = 1024;
itemsContainer.y = 1100;
game.addChild(itemsContainer);
for (var i = 0; i < self.items.length; i++) {
var item = self.items[i];
var itemBg = LK.getAsset('road', {
scaleX: 6,
scaleY: 1.5,
x: 0,
y: i * 120,
anchorX: 0.5,
anchorY: 0.5
});
itemBg.alpha = 0.7;
itemsContainer.addChild(itemBg);
var itemText = new Text2(item.name + ' - ' + item.price + ' coins (+' + item.health + ' health)', {
size: 45,
fill: playerCoins >= item.price ? 0x00ff00 : 0xff0000
});
itemText.anchor.set(0.5, 0.5);
itemText.x = 0;
itemText.y = i * 120;
itemsContainer.addChild(itemText);
// Store item data for click detection
itemBg.itemData = item;
itemBg.itemIndex = i;
}
// Travel button
var travelButton = LK.getAsset('road', {
scaleX: 4,
scaleY: 1.5,
x: 1024,
y: 1700,
anchorX: 0.5,
anchorY: 0.5
});
travelButton.alpha = 0.6;
game.addChild(travelButton);
var travelText = new Text2('Travel to Country', {
size: 45,
fill: 0xffff00
});
travelText.anchor.set(0.5, 0.5);
travelText.x = 1024;
travelText.y = 1700;
game.addChild(travelText);
// Close button
var closeButton = LK.getAsset('road', {
scaleX: 4,
scaleY: 1.5,
x: 1024,
y: 1800,
anchorX: 0.5,
anchorY: 0.5
});
closeButton.alpha = 0.8;
game.addChild(closeButton);
var closeText = new Text2('Close Shop', {
size: 50,
fill: 0xffffff
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 1024;
closeText.y = 1800;
game.addChild(closeText);
// Store references for cleanup
self.storeElements = [storeBg, storeTitle, statsText, itemsContainer, travelButton, travelText, closeButton, closeText];
// Handle purchases
var handlePurchase = function handlePurchase(x, y, obj) {
// Check if clicking on items
var localPos = itemsContainer.toLocal({
x: x,
y: y
});
var itemIndex = Math.floor((localPos.y + 60) / 120);
if (itemIndex >= 0 && itemIndex < self.items.length) {
var item = self.items[itemIndex];
var currentCoins = storage.coins || 0;
if (currentCoins >= item.price) {
// Purchase item
storage.coins = currentCoins - item.price;
storage.health = Math.min(100, (storage.health || 100) + item.health);
// Update score
LK.setScore(LK.getScore() + item.health * 2);
scoreTxt.setText('Score: ' + LK.getScore());
// Flash green for successful purchase
LK.effects.flashScreen(0x00ff00, 300);
// Close and reopen to refresh display
self.close();
LK.setTimeout(function () {
self.show();
}, 100);
} else {
// Not enough coins
LK.effects.flashScreen(0xff0000, 300);
}
return;
}
// Check if clicking travel button
if (Math.abs(x - 1024) < 240 && Math.abs(y - 1700) < 90) {
self.close();
self.showTravelMenu();
return;
}
// Check if clicking close button
if (Math.abs(x - 1024) < 240 && Math.abs(y - 1800) < 90) {
self.close();
}
};
game.down = handlePurchase;
};
self.close = function () {
if (self.storeElements) {
for (var i = 0; i < self.storeElements.length; i++) {
self.storeElements[i].destroy();
}
self.storeElements = null;
}
// Restore game activity and normal game controls
isGameActive = true;
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
initializeLevel();
}
lastTouchX = x;
lastTouchY = y;
};
game.up = function (x, y, obj) {
if (!gameStarted || !isGameActive) return;
var deltaX = x - lastTouchX;
var deltaY = y - lastTouchY;
if (Math.abs(deltaX) > minSwipeDistance || Math.abs(deltaY) > minSwipeDistance) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
handleMovement(deltaX > 0 ? 1 : -1, 0);
} else {
handleMovement(0, deltaY > 0 ? 1 : -1);
}
}
};
};
self.showTravelMenu = function () {
// Disable game activity to prevent character movement
isGameActive = false;
// Create travel background
var travelBg = LK.getAsset('road', {
scaleX: 15,
scaleY: 18,
x: 1024,
y: 1366,
anchorX: 0.5,
anchorY: 0.5
});
travelBg.alpha = 0.95;
game.addChild(travelBg);
// Travel title
var travelTitle = new Text2('Travel to Eastern Bloc', {
size: 70,
fill: 0xffff00
});
travelTitle.anchor.set(0.5, 0);
travelTitle.x = 1024;
travelTitle.y = 800;
game.addChild(travelTitle);
// Current country display
var currentCountryText = new Text2('Current: ' + easternBlocCountries[currentCountry].name, {
size: 50,
fill: 0x00ff00
});
currentCountryText.anchor.set(0.5, 0);
currentCountryText.x = 1024;
currentCountryText.y = 900;
game.addChild(currentCountryText);
// Player coins display
var playerCoins = storage.coins || 0;
var coinsText = new Text2('Coins: ' + playerCoins, {
size: 50,
fill: 0xffffff
});
coinsText.anchor.set(0.5, 0);
coinsText.x = 1024;
coinsText.y = 960;
game.addChild(coinsText);
// Countries list
var countriesContainer = new Container();
countriesContainer.x = 1024;
countriesContainer.y = 1100;
game.addChild(countriesContainer);
for (var i = 0; i < easternBlocCountries.length; i++) {
var country = easternBlocCountries[i];
if (i === currentCountry) continue; // Skip current country
var countryBg = LK.getAsset('road', {
scaleX: 8,
scaleY: 1.5,
x: 0,
y: (i - (i > currentCountry ? 1 : 0)) * 100,
anchorX: 0.5,
anchorY: 0.5
});
countryBg.alpha = country.unlocked || playerCoins >= country.cost ? 0.7 : 0.3;
countriesContainer.addChild(countryBg);
var countryText = new Text2(country.name + (country.cost > 0 ? ' - ' + country.cost + ' coins' : ''), {
size: 40,
fill: country.unlocked || playerCoins >= country.cost ? 0x00ff00 : 0xff0000
});
countryText.anchor.set(0.5, 0.5);
countryText.x = 0;
countryText.y = (i - (i > currentCountry ? 1 : 0)) * 100;
countriesContainer.addChild(countryText);
countryBg.countryIndex = i;
}
// Close travel button
var closeTravelButton = LK.getAsset('road', {
scaleX: 4,
scaleY: 1.5,
x: 1024,
y: 1800,
anchorX: 0.5,
anchorY: 0.5
});
closeTravelButton.alpha = 0.8;
game.addChild(closeTravelButton);
var closeTravelText = new Text2('Back to Shop', {
size: 50,
fill: 0xffffff
});
closeTravelText.anchor.set(0.5, 0.5);
closeTravelText.x = 1024;
closeTravelText.y = 1800;
game.addChild(closeTravelText);
// Store elements for cleanup
self.travelElements = [travelBg, travelTitle, currentCountryText, coinsText, countriesContainer, closeTravelButton, closeTravelText];
// Handle travel selection
var handleTravel = function handleTravel(x, y, obj) {
// Check countries list
var localPos = countriesContainer.toLocal({
x: x,
y: y
});
var countryIndex = Math.floor((localPos.y + 50) / 100);
// Adjust for skipped current country
var actualIndex = countryIndex >= currentCountry ? countryIndex + 1 : countryIndex;
if (actualIndex >= 0 && actualIndex < easternBlocCountries.length && actualIndex !== currentCountry) {
var country = easternBlocCountries[actualIndex];
var currentCoins = storage.coins || 0;
if (country.unlocked || currentCoins >= country.cost) {
if (!country.unlocked && country.cost > 0) {
storage.coins = currentCoins - country.cost;
country.unlocked = true;
}
currentCountry = actualIndex;
// Travel successful
LK.effects.flashScreen(0x00ff00, 500);
LK.setScore(LK.getScore() + 100);
scoreTxt.setText('Score: ' + LK.getScore());
self.closeTravelMenu();
self.show(); // Return to shop
} else {
// Can't afford travel
LK.effects.flashScreen(0xff0000, 300);
}
return;
}
// Check close button
if (Math.abs(x - 1024) < 240 && Math.abs(y - 1800) < 90) {
self.closeTravelMenu();
self.show(); // Return to shop
}
};
game.down = handleTravel;
};
self.closeTravelMenu = function () {
if (self.travelElements) {
for (var i = 0; i < self.travelElements.length; i++) {
self.travelElements[i].destroy();
}
self.travelElements = null;
}
// Restore game activity when closing travel menu
isGameActive = true;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.gridX = 0;
self.gridY = 0;
self.isMoving = false;
self.moveToGrid = function (newGridX, newGridY) {
if (self.isMoving) return false;
var targetX = newGridX * GRID_SIZE + GRID_SIZE / 2;
var targetY = newGridY * GRID_SIZE + GRID_SIZE / 2;
self.isMoving = true;
self.gridX = newGridX;
self.gridY = newGridY;
tween(self, {
x: targetX,
y: targetY
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isMoving = false;
LK.getSound('move').play();
}
});
return true;
};
return self;
});
var Road = Container.expand(function () {
var self = Container.call(this);
var roadGraphics = self.attachAsset('road', {
anchorX: 0,
anchorY: 0
});
return self;
});
var SovietGuard = Container.expand(function () {
var self = Container.call(this);
var guardGraphics = self.attachAsset('guard', {
anchorX: 0.5,
anchorY: 0.5
});
self.centerX = 0;
self.centerY = 0;
self.radius = 60;
self.angle = 0;
self.speed = 0.05;
self.startCircularMovement = function () {
self.angle = 0;
self.circularTween();
};
self.circularTween = function () {
tween(self, {
angle: self.angle + Math.PI * 2
}, {
duration: 4000,
easing: tween.linear,
onFinish: function onFinish() {
self.circularTween();
}
});
};
self.update = function () {
self.x = self.centerX + Math.cos(self.angle) * self.radius;
self.y = self.centerY + Math.sin(self.angle) * self.radius;
};
return self;
});
var ZabkaShop = Container.expand(function () {
var self = Container.call(this);
var shopGraphics = self.attachAsset('zabka', {
anchorX: 0,
anchorY: 0
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x263238
});
/****
* Game Code
****/
var GRID_SIZE = 120;
var GRID_WIDTH = 17;
var GRID_HEIGHT = 22;
var currentLevel = 1;
var timeLeft = 60;
var isGameActive = true;
var gameStarted = false;
var cityNames = ['Toruń', 'Białystok', 'Lublin', 'Katowice', 'Gdańsk', 'Wrocław', 'Poznań', 'Kraków', 'Łódź', 'Warsaw'];
var easternBlocCountries = [{
name: 'Poland',
cost: 0,
unlocked: true
}, {
name: 'Czech Republic',
cost: 100,
unlocked: false
}, {
name: 'Hungary',
cost: 200,
unlocked: false
}, {
name: 'East Germany',
cost: 300,
unlocked: false
}, {
name: 'Romania',
cost: 400,
unlocked: false
}, {
name: 'Bulgaria',
cost: 500,
unlocked: false
}, {
name: 'Yugoslavia',
cost: 600,
unlocked: false
}, {
name: 'Soviet Union',
cost: 1000,
unlocked: false
}];
var currentCountry = 0;
// Initialize storage with defaults
if (storage.coins === undefined) storage.coins = 50;
if (storage.health === undefined) storage.health = 100;
var groceryStore = new GroceryStore();
var cityGrid = [];
var player;
var destination;
var obstacles = [];
var buildings = [];
var guards = [];
var biedronkas = [];
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var timeTxt = new Text2('Time: 60', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
timeTxt.y = 80;
LK.gui.top.addChild(timeTxt);
var levelTxt = new Text2('Village', {
size: 50,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -20;
levelTxt.y = 20;
function initializeGrid() {
cityGrid = [];
for (var x = 0; x < GRID_WIDTH; x++) {
cityGrid[x] = [];
for (var y = 0; y < GRID_HEIGHT; y++) {
cityGrid[x][y] = 'road';
}
}
}
function createBuildings() {
buildings = [];
var buildingCount = Math.min(8 + currentLevel * 2, 20);
for (var i = 0; i < buildingCount; i++) {
var building = new Building();
var gridX = Math.floor(Math.random() * (GRID_WIDTH - 2)) + 1;
var gridY = Math.floor(Math.random() * (GRID_HEIGHT - 2)) + 1;
building.x = gridX * GRID_SIZE;
building.y = gridY * GRID_SIZE;
game.addChild(building);
buildings.push(building);
cityGrid[gridX][gridY] = 'building';
if (gridX + 1 < GRID_WIDTH) cityGrid[gridX + 1][gridY] = 'building';
}
}
function createObstacles() {
obstacles = [];
var obstacleCount = Math.min(3 + currentLevel, 12);
for (var i = 0; i < obstacleCount; i++) {
var attempts = 0;
var gridX, gridY;
do {
gridX = Math.floor(Math.random() * GRID_WIDTH);
gridY = Math.floor(Math.random() * GRID_HEIGHT);
attempts++;
} while (cityGrid[gridX][gridY] !== 'road' && attempts < 50);
if (attempts < 50) {
var obstacle = new Obstacle();
obstacle.x = gridX * GRID_SIZE + GRID_SIZE / 2;
obstacle.y = gridY * GRID_SIZE + GRID_SIZE / 2;
game.addChild(obstacle);
obstacles.push(obstacle);
cityGrid[gridX][gridY] = 'obstacle';
}
}
}
function createGuards() {
guards = [];
var guardCount = Math.min(2 + Math.floor(currentLevel / 2), 6);
for (var i = 0; i < guardCount; i++) {
var attempts = 0;
var gridX, gridY;
do {
gridX = Math.floor(Math.random() * GRID_WIDTH);
gridY = Math.floor(Math.random() * GRID_HEIGHT);
attempts++;
} while (cityGrid[gridX][gridY] !== 'road' && attempts < 50);
if (attempts < 50) {
var guard = new SovietGuard();
guard.centerX = gridX * GRID_SIZE + GRID_SIZE / 2;
guard.centerY = gridY * GRID_SIZE + GRID_SIZE / 2;
guard.x = guard.centerX;
guard.y = guard.centerY;
game.addChild(guard);
guards.push(guard);
guard.startCircularMovement();
}
}
}
function showGroceryStorePopup() {
// Pause game activity
isGameActive = false;
// Show the grocery store
groceryStore.show();
}
function createBiedronkas() {
biedronkas = [];
var biedronkaCount = Math.min(1 + Math.floor(currentLevel / 3), 4);
for (var i = 0; i < biedronkaCount; i++) {
var attempts = 0;
var gridX, gridY;
do {
gridX = Math.floor(Math.random() * (GRID_WIDTH - 2)) + 1;
gridY = Math.floor(Math.random() * (GRID_HEIGHT - 2)) + 1;
attempts++;
} while (cityGrid[gridX][gridY] !== 'road' && attempts < 50);
if (attempts < 50) {
var biedronka;
if (currentCountry === 1 || currentCountry === 4) {
// Czech Republic or Romania - use Zabka
biedronka = new ZabkaShop();
} else {
// Other countries - use Biedronka
biedronka = new BiedronkaShop();
}
biedronka.x = gridX * GRID_SIZE;
biedronka.y = gridY * GRID_SIZE;
game.addChild(biedronka);
biedronkas.push(biedronka);
cityGrid[gridX][gridY] = 'biedronka';
if (gridX + 1 < GRID_WIDTH) cityGrid[gridX + 1][gridY] = 'biedronka';
}
}
}
function createDestination() {
var attempts = 0;
var gridX, gridY;
do {
gridX = Math.floor(Math.random() * GRID_WIDTH);
gridY = Math.floor(Math.random() * GRID_HEIGHT);
attempts++;
} while (cityGrid[gridX][gridY] !== 'road' && attempts < 100);
destination = new Destination();
destination.x = gridX * GRID_SIZE + GRID_SIZE / 2;
destination.y = gridY * GRID_SIZE + GRID_SIZE / 2;
destination.gridX = gridX;
destination.gridY = gridY;
game.addChild(destination);
destination.pulse();
cityGrid[gridX][gridY] = 'destination';
}
function createPlayer() {
var attempts = 0;
var gridX, gridY;
do {
gridX = Math.floor(Math.random() * GRID_WIDTH);
gridY = Math.floor(Math.random() * GRID_HEIGHT);
attempts++;
} while (cityGrid[gridX][gridY] !== 'road' && attempts < 100);
player = new Player();
player.gridX = gridX;
player.gridY = gridY;
player.x = gridX * GRID_SIZE + GRID_SIZE / 2;
player.y = gridY * GRID_SIZE + GRID_SIZE / 2;
game.addChild(player);
}
function isValidMove(gridX, gridY) {
if (gridX < 0 || gridX >= GRID_WIDTH || gridY < 0 || gridY >= GRID_HEIGHT) {
return false;
}
var cellType = cityGrid[gridX][gridY];
return cellType === 'road' || cellType === 'destination' || cellType === 'biedronka';
}
function checkWin() {
// Check collision with guards
for (var i = 0; i < guards.length; i++) {
if (player.intersects(guards[i])) {
LK.getSound('blocked').play();
LK.effects.flashScreen(0xff0000, 500);
isGameActive = false;
LK.showGameOver();
return;
}
}
// Check interaction with Biedronka shops
for (var i = 0; i < biedronkas.length; i++) {
if (player.intersects(biedronkas[i])) {
// Add coins for visiting Biedronka
storage.coins = (storage.coins || 0) + 25;
// Show grocery store
showGroceryStorePopup();
// Give bonus points for visiting Biedronka
LK.setScore(LK.getScore() + 50);
scoreTxt.setText('Score: ' + LK.getScore());
// Flash green to show successful interaction
LK.effects.flashScreen(0x00ff00, 300);
// Remove the visited Biedronka
biedronkas[i].destroy();
biedronkas.splice(i, 1);
break;
}
}
if (player.gridX === destination.gridX && player.gridY === destination.gridY) {
var timeBonus = Math.floor(timeLeft * 10);
var levelBonus = currentLevel * 100;
LK.setScore(LK.getScore() + timeBonus + levelBonus);
LK.getSound('complete').play();
LK.effects.flashScreen(0x4CAF50, 500);
currentLevel++;
if (currentLevel > 10) {
LK.showYouWin();
} else {
initializeLevel();
}
}
}
function initializeLevel() {
for (var i = buildings.length - 1; i >= 0; i--) {
buildings[i].destroy();
}
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
}
for (var i = guards.length - 1; i >= 0; i--) {
guards[i].destroy();
}
for (var i = biedronkas.length - 1; i >= 0; i--) {
biedronkas[i].destroy();
}
if (destination) destination.destroy();
if (player) player.destroy();
buildings = [];
obstacles = [];
guards = [];
biedronkas = [];
initializeGrid();
createBuildings();
createObstacles();
createGuards();
createBiedronkas();
createDestination();
createPlayer();
timeLeft = Math.max(30, 80 - currentLevel * 3);
var cityName = cityNames[Math.min(currentLevel - 1, cityNames.length - 1)];
levelTxt.setText(cityName);
scoreTxt.setText('Score: ' + LK.getScore());
timeTxt.setText('Time: ' + timeLeft);
}
function handleMovement(deltaX, deltaY) {
if (!isGameActive || !gameStarted || player.isMoving) return;
var newGridX = player.gridX + deltaX;
var newGridY = player.gridY + deltaY;
if (isValidMove(newGridX, newGridY)) {
if (player.moveToGrid(newGridX, newGridY)) {
checkWin();
}
} else {
LK.getSound('blocked').play();
}
}
var lastTouchX = 0;
var lastTouchY = 0;
var minSwipeDistance = 50;
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
initializeLevel();
}
lastTouchX = x;
lastTouchY = y;
};
game.up = function (x, y, obj) {
if (!gameStarted || !isGameActive) return;
var deltaX = x - lastTouchX;
var deltaY = y - lastTouchY;
if (Math.abs(deltaX) > minSwipeDistance || Math.abs(deltaY) > minSwipeDistance) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
handleMovement(deltaX > 0 ? 1 : -1, 0);
} else {
handleMovement(0, deltaY > 0 ? 1 : -1);
}
}
};
var gameTimer = null;
game.update = function () {
if (!gameStarted || !isGameActive) return;
if (LK.ticks % 60 === 0 && timeLeft > 0) {
timeLeft--;
timeTxt.setText('Time: ' + timeLeft);
if (timeLeft <= 0) {
isGameActive = false;
LK.showGameOver();
}
}
};
var instructionTxt = new Text2('Swipe to navigate through the city\nReach the golden destination!\nTap to start', {
size: 50,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.x = 1024;
instructionTxt.y = 1366;
game.addChild(instructionTxt);