/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); var greetingBubble = self.attachAsset('greeting', { anchorX: 0.5, anchorY: 1.0, x: 0, y: -70 }); var greetingText = new Text2('¡Hola!', { size: 30, fill: '#000000' }); greetingText.anchor.set(0.5, 0.5); greetingText.x = 0; greetingText.y = -70; self.addChild(greetingText); greetingBubble.visible = false; greetingText.visible = false; self.showGreeting = function () { greetingBubble.visible = true; greetingText.visible = true; greetingBubble.alpha = 1; greetingText.alpha = 1; tween(greetingBubble, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { greetingBubble.visible = false; } }); tween(greetingText, { alpha: 0 }, { duration: 800, onFinish: function onFinish() { greetingText.visible = false; } }); }; self.isGreeting = false; self.greetingCooldown = 0; self.update = function () { if (self.greetingCooldown > 0) { self.greetingCooldown--; } }; self.greet = function () { if (self.greetingCooldown <= 0) { self.isGreeting = true; self.showGreeting(); self.greetingCooldown = 15; // Short cooldown to prevent spam LK.setTimeout(function () { self.isGreeting = false; }, 250); return true; } return false; }; return self; }); var Townsperson = Container.expand(function (isSpecial) { var self = Container.call(this); self.isSpecial = isSpecial || false; var assetId = self.isSpecial ? 'specialPerson' : 'townsperson'; var personGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.greeted = false; self.speed = 1 + Math.random() * 2; self.direction = Math.random() * Math.PI * 2; self.targetX = null; self.targetY = null; self.moveTimeout = 0; self.setRandomDirection = function () { self.direction = Math.random() * Math.PI * 2; }; self.setRandomTarget = function () { self.targetX = 100 + Math.random() * (2048 - 200); self.targetY = 100 + Math.random() * (2732 - 200); // Calculate direction to target var dx = self.targetX - self.x; var dy = self.targetY - self.y; self.direction = Math.atan2(dy, dx); // Reset timeout self.moveTimeout = 60 + Math.floor(Math.random() * 120); // 1-3 seconds }; self.update = function () { if (self.moveTimeout <= 0) { self.setRandomTarget(); } else { self.moveTimeout--; } if (self.targetX !== null && self.targetY !== null) { // Move toward target var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 5) { // Close enough, get new target self.setRandomTarget(); } else { var moveX = Math.cos(self.direction) * self.speed; var moveY = Math.sin(self.direction) * self.speed; self.x += moveX; self.y += moveY; // Boundary check if (self.x < 50) { self.x = 50; } if (self.x > 2048 - 50) { self.x = 2048 - 50; } if (self.y < 50) { self.y = 50; } if (self.y > 2732 - 50) { self.y = 2732 - 50; } } } else { self.setRandomTarget(); } }; self.greet = function () { if (!self.greeted) { self.greeted = true; // Flash effect LK.effects.flashObject(self, 0x00FF00, 300); // Slight movement bounce var currentX = self.x; var currentY = self.y; tween(self, { x: currentX + Math.cos(self.direction) * 20, y: currentY + Math.sin(self.direction) * 20 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { x: currentX, y: currentY }, { duration: 150, easing: tween.easeIn }); } }); return true; } return false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x88CC99 }); /**** * Game Code ****/ // Define gameplay variables var player = null; var townspeople = []; var score = 0; var combo = 0; var maxCombo = 0; var level = 1; var spawnTimer = 0; var dragNode = null; var gameTime = 0; var gameActive = true; // UI elements var scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(1, 0); LK.gui.topRight.addChild(scoreTxt); var comboTxt = new Text2('Combo: 0', { size: 40, fill: 0xFFFFFF }); comboTxt.anchor.set(1, 0); comboTxt.y = 70; LK.gui.topRight.addChild(comboTxt); var levelTxt = new Text2('Level: 1', { size: 40, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); levelTxt.x = 120; // Leave space for platform menu icon LK.gui.topLeft.addChild(levelTxt); var timeTxt = new Text2('Time: 60', { size: 40, fill: 0xFFFFFF }); timeTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timeTxt); // Start the game function initGame() { // Reset game state townspeople.forEach(function (person) { person.destroy(); }); townspeople = []; score = 0; combo = 0; maxCombo = 0; level = 1; gameTime = 60; // 60 second game gameActive = true; // Reset UI updateUI(); // Create player if (player) { player.destroy(); } player = new Player(); player.x = 2048 / 2; player.y = 2732 / 2; game.addChild(player); // Initial townspeople spawnTownspeople(5); // Play music LK.playMusic('fiestaMusic'); } function spawnTownspeople(count) { for (var i = 0; i < count; i++) { spawnTownsperson(); } } function spawnTownsperson() { var isSpecial = Math.random() < 0.2; // 20% chance for special person var person = new Townsperson(isSpecial); // Position on the edge of the screen var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top person.x = Math.random() * 2048; person.y = 50; break; case 1: // Right person.x = 2048 - 50; person.y = Math.random() * 2732; break; case 2: // Bottom person.x = Math.random() * 2048; person.y = 2732 - 50; break; case 3: // Left person.x = 50; person.y = Math.random() * 2732; break; } // Make sure it's not too close to the player var dx = person.x - player.x; var dy = person.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 300) { person.x = Math.random() * 2048; person.y = Math.random() * 2732; } game.addChild(person); townspeople.push(person); return person; } function updateUI() { scoreTxt.setText('Score: ' + score); comboTxt.setText('Combo: x' + combo); levelTxt.setText('Level: ' + level); timeTxt.setText('Time: ' + Math.ceil(gameTime)); } function updateLevel() { var previousLevel = level; // Calculate level based on score level = Math.floor(score / 500) + 1; // Cap at level 10 if (level > 10) { level = 10; } // If level increased if (level > previousLevel) { // Spawn more townspeople for each level spawnTownspeople(level); // Update UI levelTxt.setText('Level: ' + level); // Flash level text tween(levelTxt, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { tween(levelTxt, { alpha: 1 }, { duration: 200 }); } }); } } function handleMove(x, y, obj) { if (dragNode) { dragNode.x = x; dragNode.y = y; // Keep player within bounds if (dragNode.x < 50) { dragNode.x = 50; } if (dragNode.x > 2048 - 50) { dragNode.x = 2048 - 50; } if (dragNode.y < 50) { dragNode.y = 50; } if (dragNode.y > 2732 - 50) { dragNode.y = 2732 - 50; } // Check for greetings when player moves if (player.isGreeting) { checkGreetings(); } } } function checkGreetings() { var greetedSomeone = false; for (var i = 0; i < townspeople.length; i++) { var person = townspeople[i]; // Only check for non-greeted people if (!person.greeted && player.intersects(person)) { if (person.greet()) { greetedSomeone = true; // Add score var pointsEarned = 10 * combo * (person.isSpecial ? 3 : 1); score += pointsEarned; // Show points gained var pointsTxt = new Text2("+" + pointsEarned, { size: 40, fill: person.isSpecial ? "#FFD700" : "#FFFFFF" }); pointsTxt.anchor.set(0.5, 0.5); pointsTxt.x = person.x; pointsTxt.y = person.y - 60; game.addChild(pointsTxt); tween(pointsTxt, { y: pointsTxt.y - 80, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { pointsTxt.destroy(); } }); // Update combo combo++; if (combo > maxCombo) { maxCombo = combo; } // Play sound if (person.isSpecial) { LK.getSound('specialGreet').play(); } else { LK.getSound('greet').play(); } // Update level based on score updateLevel(); } } } if (greetedSomeone) { // Play combo sound if it's getting high if (combo > 1 && combo % 5 === 0) { LK.getSound('combo').play(); // Flash combo text tween(comboTxt, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } } // Update UI updateUI(); } game.down = function (x, y, obj) { if (!gameActive) { return; } dragNode = player; handleMove(x, y, obj); // Greet if (player.greet()) { checkGreetings(); } }; game.up = function (x, y, obj) { dragNode = null; }; game.move = handleMove; game.update = function () { if (!gameActive) { return; } // Update game time gameTime -= 1 / 60; // Assuming 60 FPS if (gameTime <= 0) { gameOver(); return; } // Update UI updateUI(); // Spawn new townspeople occasionally spawnTimer++; if (spawnTimer >= 180) { // Every 3 seconds spawnTimer = 0; // Chance to spawn increases with level if (Math.random() < 0.2 + level * 0.05) { spawnTownsperson(); } } // Reset combo if no greets for a while if (player.greetingCooldown <= 0 && combo > 0) { var comboDecayRate = 1 / 180; // Lose combo after 3 seconds of inactivity combo = Math.max(0, combo - comboDecayRate); if (combo < 1) { combo = 0; updateUI(); } } // Update all townspeople for (var i = townspeople.length - 1; i >= 0; i--) { var person = townspeople[i]; // Remove greeted people after a while if (person.greeted) { person.alpha -= 0.01; if (person.alpha <= 0) { person.destroy(); townspeople.splice(i, 1); continue; } } } }; function gameOver() { gameActive = false; // Set final score LK.setScore(score); // Show game over LK.showGameOver(); } // Initialize the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
var greetingBubble = self.attachAsset('greeting', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -70
});
var greetingText = new Text2('¡Hola!', {
size: 30,
fill: '#000000'
});
greetingText.anchor.set(0.5, 0.5);
greetingText.x = 0;
greetingText.y = -70;
self.addChild(greetingText);
greetingBubble.visible = false;
greetingText.visible = false;
self.showGreeting = function () {
greetingBubble.visible = true;
greetingText.visible = true;
greetingBubble.alpha = 1;
greetingText.alpha = 1;
tween(greetingBubble, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
greetingBubble.visible = false;
}
});
tween(greetingText, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
greetingText.visible = false;
}
});
};
self.isGreeting = false;
self.greetingCooldown = 0;
self.update = function () {
if (self.greetingCooldown > 0) {
self.greetingCooldown--;
}
};
self.greet = function () {
if (self.greetingCooldown <= 0) {
self.isGreeting = true;
self.showGreeting();
self.greetingCooldown = 15; // Short cooldown to prevent spam
LK.setTimeout(function () {
self.isGreeting = false;
}, 250);
return true;
}
return false;
};
return self;
});
var Townsperson = Container.expand(function (isSpecial) {
var self = Container.call(this);
self.isSpecial = isSpecial || false;
var assetId = self.isSpecial ? 'specialPerson' : 'townsperson';
var personGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.greeted = false;
self.speed = 1 + Math.random() * 2;
self.direction = Math.random() * Math.PI * 2;
self.targetX = null;
self.targetY = null;
self.moveTimeout = 0;
self.setRandomDirection = function () {
self.direction = Math.random() * Math.PI * 2;
};
self.setRandomTarget = function () {
self.targetX = 100 + Math.random() * (2048 - 200);
self.targetY = 100 + Math.random() * (2732 - 200);
// Calculate direction to target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
self.direction = Math.atan2(dy, dx);
// Reset timeout
self.moveTimeout = 60 + Math.floor(Math.random() * 120); // 1-3 seconds
};
self.update = function () {
if (self.moveTimeout <= 0) {
self.setRandomTarget();
} else {
self.moveTimeout--;
}
if (self.targetX !== null && self.targetY !== null) {
// Move toward target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 5) {
// Close enough, get new target
self.setRandomTarget();
} else {
var moveX = Math.cos(self.direction) * self.speed;
var moveY = Math.sin(self.direction) * self.speed;
self.x += moveX;
self.y += moveY;
// Boundary check
if (self.x < 50) {
self.x = 50;
}
if (self.x > 2048 - 50) {
self.x = 2048 - 50;
}
if (self.y < 50) {
self.y = 50;
}
if (self.y > 2732 - 50) {
self.y = 2732 - 50;
}
}
} else {
self.setRandomTarget();
}
};
self.greet = function () {
if (!self.greeted) {
self.greeted = true;
// Flash effect
LK.effects.flashObject(self, 0x00FF00, 300);
// Slight movement bounce
var currentX = self.x;
var currentY = self.y;
tween(self, {
x: currentX + Math.cos(self.direction) * 20,
y: currentY + Math.sin(self.direction) * 20
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
x: currentX,
y: currentY
}, {
duration: 150,
easing: tween.easeIn
});
}
});
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x88CC99
});
/****
* Game Code
****/
// Define gameplay variables
var player = null;
var townspeople = [];
var score = 0;
var combo = 0;
var maxCombo = 0;
var level = 1;
var spawnTimer = 0;
var dragNode = null;
var gameTime = 0;
var gameActive = true;
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreTxt);
var comboTxt = new Text2('Combo: 0', {
size: 40,
fill: 0xFFFFFF
});
comboTxt.anchor.set(1, 0);
comboTxt.y = 70;
LK.gui.topRight.addChild(comboTxt);
var levelTxt = new Text2('Level: 1', {
size: 40,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
levelTxt.x = 120; // Leave space for platform menu icon
LK.gui.topLeft.addChild(levelTxt);
var timeTxt = new Text2('Time: 60', {
size: 40,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timeTxt);
// Start the game
function initGame() {
// Reset game state
townspeople.forEach(function (person) {
person.destroy();
});
townspeople = [];
score = 0;
combo = 0;
maxCombo = 0;
level = 1;
gameTime = 60; // 60 second game
gameActive = true;
// Reset UI
updateUI();
// Create player
if (player) {
player.destroy();
}
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// Initial townspeople
spawnTownspeople(5);
// Play music
LK.playMusic('fiestaMusic');
}
function spawnTownspeople(count) {
for (var i = 0; i < count; i++) {
spawnTownsperson();
}
}
function spawnTownsperson() {
var isSpecial = Math.random() < 0.2; // 20% chance for special person
var person = new Townsperson(isSpecial);
// Position on the edge of the screen
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
person.x = Math.random() * 2048;
person.y = 50;
break;
case 1:
// Right
person.x = 2048 - 50;
person.y = Math.random() * 2732;
break;
case 2:
// Bottom
person.x = Math.random() * 2048;
person.y = 2732 - 50;
break;
case 3:
// Left
person.x = 50;
person.y = Math.random() * 2732;
break;
}
// Make sure it's not too close to the player
var dx = person.x - player.x;
var dy = person.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 300) {
person.x = Math.random() * 2048;
person.y = Math.random() * 2732;
}
game.addChild(person);
townspeople.push(person);
return person;
}
function updateUI() {
scoreTxt.setText('Score: ' + score);
comboTxt.setText('Combo: x' + combo);
levelTxt.setText('Level: ' + level);
timeTxt.setText('Time: ' + Math.ceil(gameTime));
}
function updateLevel() {
var previousLevel = level;
// Calculate level based on score
level = Math.floor(score / 500) + 1;
// Cap at level 10
if (level > 10) {
level = 10;
}
// If level increased
if (level > previousLevel) {
// Spawn more townspeople for each level
spawnTownspeople(level);
// Update UI
levelTxt.setText('Level: ' + level);
// Flash level text
tween(levelTxt, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
tween(levelTxt, {
alpha: 1
}, {
duration: 200
});
}
});
}
}
function handleMove(x, y, obj) {
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
// Keep player within bounds
if (dragNode.x < 50) {
dragNode.x = 50;
}
if (dragNode.x > 2048 - 50) {
dragNode.x = 2048 - 50;
}
if (dragNode.y < 50) {
dragNode.y = 50;
}
if (dragNode.y > 2732 - 50) {
dragNode.y = 2732 - 50;
}
// Check for greetings when player moves
if (player.isGreeting) {
checkGreetings();
}
}
}
function checkGreetings() {
var greetedSomeone = false;
for (var i = 0; i < townspeople.length; i++) {
var person = townspeople[i];
// Only check for non-greeted people
if (!person.greeted && player.intersects(person)) {
if (person.greet()) {
greetedSomeone = true;
// Add score
var pointsEarned = 10 * combo * (person.isSpecial ? 3 : 1);
score += pointsEarned;
// Show points gained
var pointsTxt = new Text2("+" + pointsEarned, {
size: 40,
fill: person.isSpecial ? "#FFD700" : "#FFFFFF"
});
pointsTxt.anchor.set(0.5, 0.5);
pointsTxt.x = person.x;
pointsTxt.y = person.y - 60;
game.addChild(pointsTxt);
tween(pointsTxt, {
y: pointsTxt.y - 80,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
pointsTxt.destroy();
}
});
// Update combo
combo++;
if (combo > maxCombo) {
maxCombo = combo;
}
// Play sound
if (person.isSpecial) {
LK.getSound('specialGreet').play();
} else {
LK.getSound('greet').play();
}
// Update level based on score
updateLevel();
}
}
}
if (greetedSomeone) {
// Play combo sound if it's getting high
if (combo > 1 && combo % 5 === 0) {
LK.getSound('combo').play();
// Flash combo text
tween(comboTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
}
// Update UI
updateUI();
}
game.down = function (x, y, obj) {
if (!gameActive) {
return;
}
dragNode = player;
handleMove(x, y, obj);
// Greet
if (player.greet()) {
checkGreetings();
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.move = handleMove;
game.update = function () {
if (!gameActive) {
return;
}
// Update game time
gameTime -= 1 / 60; // Assuming 60 FPS
if (gameTime <= 0) {
gameOver();
return;
}
// Update UI
updateUI();
// Spawn new townspeople occasionally
spawnTimer++;
if (spawnTimer >= 180) {
// Every 3 seconds
spawnTimer = 0;
// Chance to spawn increases with level
if (Math.random() < 0.2 + level * 0.05) {
spawnTownsperson();
}
}
// Reset combo if no greets for a while
if (player.greetingCooldown <= 0 && combo > 0) {
var comboDecayRate = 1 / 180; // Lose combo after 3 seconds of inactivity
combo = Math.max(0, combo - comboDecayRate);
if (combo < 1) {
combo = 0;
updateUI();
}
}
// Update all townspeople
for (var i = townspeople.length - 1; i >= 0; i--) {
var person = townspeople[i];
// Remove greeted people after a while
if (person.greeted) {
person.alpha -= 0.01;
if (person.alpha <= 0) {
person.destroy();
townspeople.splice(i, 1);
continue;
}
}
}
};
function gameOver() {
gameActive = false;
// Set final score
LK.setScore(score);
// Show game over
LK.showGameOver();
}
// Initialize the game
initGame();