/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ChainLetter = Container.expand(function (letter, targetX, targetY) {
var self = Container.call(this);
var graphics = self.attachAsset('chainLetter', {
anchorX: 0.5,
anchorY: 0.5
});
var letterText = new Text2(letter, {
size: 60,
fill: 0xFFFFFF
});
letterText.anchor.set(0.5, 0.5);
self.addChild(letterText);
self.letter = letter;
self.targetX = targetX;
self.targetY = targetY;
self.followDistance = 150;
return self;
});
var LetterD = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('letterD', {
anchorX: 0.5,
anchorY: 0.5
});
var letterText = new Text2('Д', {
size: 80,
fill: 0xFFFFFF
});
letterText.anchor.set(0.5, 0.5);
self.addChild(letterText);
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
self.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F4F4F
});
/****
* Game Code
****/
var cyrillicAlphabet = ['Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь'];
var letterD = game.addChild(new LetterD());
letterD.x = 1024;
letterD.y = 1366;
var chainLetters = [];
var targets = [];
var obstacles = [];
var currentLetterIndex = 0;
var birthTimer = 0;
var birthInterval = 180; // 3 seconds at 60fps
var level = 1;
var targetsCollected = 0;
var targetsRequired = 5;
var dragNode = null;
// Level text
var levelText = new Text2('Level ' + level, {
size: 100,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
// Score text
var scoreText = new Text2('Chain: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 50;
scoreText.y = 50;
game.addChild(scoreText);
// Progress text
var progressText = new Text2('Targets: 0/' + targetsRequired, {
size: 60,
fill: 0xFFFFFF
});
progressText.anchor.set(1, 0);
progressText.x = 1998;
progressText.y = 50;
game.addChild(progressText);
function createLevel() {
// Clear existing targets and obstacles
for (var i = targets.length - 1; i >= 0; i--) {
targets[i].destroy();
targets.splice(i, 1);
}
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
// Create targets
for (var i = 0; i < targetsRequired; i++) {
var target = game.addChild(new Target());
target.x = Math.random() * 1800 + 124;
target.y = Math.random() * 2400 + 166;
targets.push(target);
}
// Create obstacles
var numObstacles = Math.min(level + 2, 8);
for (var i = 0; i < numObstacles; i++) {
var obstacle = game.addChild(new Obstacle());
obstacle.x = Math.random() * 1800 + 124;
obstacle.y = Math.random() * 2400 + 166;
// Make sure obstacles don't spawn too close to player start
var distToPlayer = Math.sqrt(Math.pow(obstacle.x - letterD.x, 2) + Math.pow(obstacle.y - letterD.y, 2));
if (distToPlayer < 300) {
obstacle.x = Math.random() * 1000 + 1000;
obstacle.y = Math.random() * 1000 + 1500;
}
obstacles.push(obstacle);
}
targetsCollected = 0;
progressText.setText('Targets: 0/' + targetsRequired);
}
function giveBirth() {
if (currentLetterIndex < cyrillicAlphabet.length) {
var newLetter = game.addChild(new ChainLetter(cyrillicAlphabet[currentLetterIndex]));
newLetter.x = letterD.x;
newLetter.y = letterD.y;
chainLetters.push(newLetter);
currentLetterIndex++;
LK.getSound('birth').play();
scoreText.setText('Chain: ' + chainLetters.length);
// Flash effect for birth
LK.effects.flashObject(letterD, 0xFFFFFF, 300);
}
}
function updateChain() {
if (chainLetters.length > 0) {
// First letter follows D
var firstLetter = chainLetters[0];
var dx = letterD.x - firstLetter.x;
var dy = letterD.y - firstLetter.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > firstLetter.followDistance) {
var moveX = dx / distance * 3;
var moveY = dy / distance * 3;
firstLetter.x += moveX;
firstLetter.y += moveY;
}
// Other letters follow the previous letter
for (var i = 1; i < chainLetters.length; i++) {
var currentLetter = chainLetters[i];
var previousLetter = chainLetters[i - 1];
dx = previousLetter.x - currentLetter.x;
dy = previousLetter.y - currentLetter.y;
distance = Math.sqrt(dx * dx + dy * dy);
if (distance > currentLetter.followDistance) {
moveX = dx / distance * 3;
moveY = dy / distance * 3;
currentLetter.x += moveX;
currentLetter.y += moveY;
}
}
}
}
function checkCollisions() {
// Check D collision with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (letterD.intersects(obstacles[i])) {
// Game over - chain broken
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
}
// Check chain collision with obstacles
for (var i = 0; i < chainLetters.length; i++) {
for (var j = 0; j < obstacles.length; j++) {
if (chainLetters[i].intersects(obstacles[j])) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
}
}
// Check target collection
for (var i = targets.length - 1; i >= 0; i--) {
var target = targets[i];
if (!target.collected && letterD.intersects(target)) {
target.collected = true;
target.destroy();
targets.splice(i, 1);
targetsCollected++;
LK.setScore(LK.getScore() + 10);
LK.getSound('collect').play();
progressText.setText('Targets: ' + targetsCollected + '/' + targetsRequired);
if (targetsCollected >= targetsRequired) {
// Level complete
level++;
targetsRequired = Math.min(targetsRequired + 2, 10);
levelText.setText('Level ' + level);
LK.getSound('complete').play();
LK.effects.flashScreen(0x00FF00, 500);
// Check win condition
if (currentLetterIndex >= cyrillicAlphabet.length && level > 3) {
LK.showYouWin();
return;
}
createLevel();
}
}
}
}
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Keep D within bounds
dragNode.x = Math.max(60, Math.min(dragNode.x, 1988));
dragNode.y = Math.max(60, Math.min(dragNode.y, 2672));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = letterD;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
birthTimer++;
if (birthTimer >= birthInterval) {
giveBirth();
birthTimer = 0;
// Decrease birth interval slightly each time for increasing difficulty
birthInterval = Math.max(120, birthInterval - 2);
}
updateChain();
checkCollisions();
};
// Initialize first level
createLevel(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ChainLetter = Container.expand(function (letter, targetX, targetY) {
var self = Container.call(this);
var graphics = self.attachAsset('chainLetter', {
anchorX: 0.5,
anchorY: 0.5
});
var letterText = new Text2(letter, {
size: 60,
fill: 0xFFFFFF
});
letterText.anchor.set(0.5, 0.5);
self.addChild(letterText);
self.letter = letter;
self.targetX = targetX;
self.targetY = targetY;
self.followDistance = 150;
return self;
});
var LetterD = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('letterD', {
anchorX: 0.5,
anchorY: 0.5
});
var letterText = new Text2('Д', {
size: 80,
fill: 0xFFFFFF
});
letterText.anchor.set(0.5, 0.5);
self.addChild(letterText);
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.update = function () {
self.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2F4F4F
});
/****
* Game Code
****/
var cyrillicAlphabet = ['Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь'];
var letterD = game.addChild(new LetterD());
letterD.x = 1024;
letterD.y = 1366;
var chainLetters = [];
var targets = [];
var obstacles = [];
var currentLetterIndex = 0;
var birthTimer = 0;
var birthInterval = 180; // 3 seconds at 60fps
var level = 1;
var targetsCollected = 0;
var targetsRequired = 5;
var dragNode = null;
// Level text
var levelText = new Text2('Level ' + level, {
size: 100,
fill: 0xFFFFFF
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
// Score text
var scoreText = new Text2('Chain: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
scoreText.x = 50;
scoreText.y = 50;
game.addChild(scoreText);
// Progress text
var progressText = new Text2('Targets: 0/' + targetsRequired, {
size: 60,
fill: 0xFFFFFF
});
progressText.anchor.set(1, 0);
progressText.x = 1998;
progressText.y = 50;
game.addChild(progressText);
function createLevel() {
// Clear existing targets and obstacles
for (var i = targets.length - 1; i >= 0; i--) {
targets[i].destroy();
targets.splice(i, 1);
}
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
// Create targets
for (var i = 0; i < targetsRequired; i++) {
var target = game.addChild(new Target());
target.x = Math.random() * 1800 + 124;
target.y = Math.random() * 2400 + 166;
targets.push(target);
}
// Create obstacles
var numObstacles = Math.min(level + 2, 8);
for (var i = 0; i < numObstacles; i++) {
var obstacle = game.addChild(new Obstacle());
obstacle.x = Math.random() * 1800 + 124;
obstacle.y = Math.random() * 2400 + 166;
// Make sure obstacles don't spawn too close to player start
var distToPlayer = Math.sqrt(Math.pow(obstacle.x - letterD.x, 2) + Math.pow(obstacle.y - letterD.y, 2));
if (distToPlayer < 300) {
obstacle.x = Math.random() * 1000 + 1000;
obstacle.y = Math.random() * 1000 + 1500;
}
obstacles.push(obstacle);
}
targetsCollected = 0;
progressText.setText('Targets: 0/' + targetsRequired);
}
function giveBirth() {
if (currentLetterIndex < cyrillicAlphabet.length) {
var newLetter = game.addChild(new ChainLetter(cyrillicAlphabet[currentLetterIndex]));
newLetter.x = letterD.x;
newLetter.y = letterD.y;
chainLetters.push(newLetter);
currentLetterIndex++;
LK.getSound('birth').play();
scoreText.setText('Chain: ' + chainLetters.length);
// Flash effect for birth
LK.effects.flashObject(letterD, 0xFFFFFF, 300);
}
}
function updateChain() {
if (chainLetters.length > 0) {
// First letter follows D
var firstLetter = chainLetters[0];
var dx = letterD.x - firstLetter.x;
var dy = letterD.y - firstLetter.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > firstLetter.followDistance) {
var moveX = dx / distance * 3;
var moveY = dy / distance * 3;
firstLetter.x += moveX;
firstLetter.y += moveY;
}
// Other letters follow the previous letter
for (var i = 1; i < chainLetters.length; i++) {
var currentLetter = chainLetters[i];
var previousLetter = chainLetters[i - 1];
dx = previousLetter.x - currentLetter.x;
dy = previousLetter.y - currentLetter.y;
distance = Math.sqrt(dx * dx + dy * dy);
if (distance > currentLetter.followDistance) {
moveX = dx / distance * 3;
moveY = dy / distance * 3;
currentLetter.x += moveX;
currentLetter.y += moveY;
}
}
}
}
function checkCollisions() {
// Check D collision with obstacles
for (var i = 0; i < obstacles.length; i++) {
if (letterD.intersects(obstacles[i])) {
// Game over - chain broken
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
}
// Check chain collision with obstacles
for (var i = 0; i < chainLetters.length; i++) {
for (var j = 0; j < obstacles.length; j++) {
if (chainLetters[i].intersects(obstacles[j])) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
}
}
// Check target collection
for (var i = targets.length - 1; i >= 0; i--) {
var target = targets[i];
if (!target.collected && letterD.intersects(target)) {
target.collected = true;
target.destroy();
targets.splice(i, 1);
targetsCollected++;
LK.setScore(LK.getScore() + 10);
LK.getSound('collect').play();
progressText.setText('Targets: ' + targetsCollected + '/' + targetsRequired);
if (targetsCollected >= targetsRequired) {
// Level complete
level++;
targetsRequired = Math.min(targetsRequired + 2, 10);
levelText.setText('Level ' + level);
LK.getSound('complete').play();
LK.effects.flashScreen(0x00FF00, 500);
// Check win condition
if (currentLetterIndex >= cyrillicAlphabet.length && level > 3) {
LK.showYouWin();
return;
}
createLevel();
}
}
}
}
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Keep D within bounds
dragNode.x = Math.max(60, Math.min(dragNode.x, 1988));
dragNode.y = Math.max(60, Math.min(dragNode.y, 2672));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = letterD;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
birthTimer++;
if (birthTimer >= birthInterval) {
giveBirth();
birthTimer = 0;
// Decrease birth interval slightly each time for increasing difficulty
birthInterval = Math.max(120, birthInterval - 2);
}
updateChain();
checkCollisions();
};
// Initialize first level
createLevel();