/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Character = Container.expand(function () {
var self = Container.call(this);
// Create base circle under character
var base = self.attachAsset('characterBase', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
// Character type (boy or girl)
self.type = "";
// Character containers
self.bodyContainer = new Container();
self.headContainer = new Container();
self.armsContainer = new Container();
self.legsContainer = new Container();
self.facialContainer = new Container();
// Add all containers to self
self.addChild(self.legsContainer);
self.addChild(self.bodyContainer);
self.addChild(self.armsContainer);
self.addChild(self.headContainer);
self.addChild(self.facialContainer);
// Animation properties
self.bobTimer = 0;
self.blinkTimer = 0;
self.isBlinking = false;
self.armSwingDirection = 1;
// Initialize with type
self.initialize = function (characterType) {
self.type = characterType;
// Reset containers
self.bodyContainer.removeChildren();
self.headContainer.removeChildren();
self.armsContainer.removeChildren();
self.legsContainer.removeChildren();
self.facialContainer.removeChildren();
// Build character based on type
if (characterType === "boy") {
// Body
var body = self.bodyContainer.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 0.5,
y: 30
});
// Head
var head = self.headContainer.attachAsset('boyHead', {
anchorX: 0.5,
anchorY: 0.5,
y: -80
});
// Hair for boy character - simple short hair that sticks to the head
var boyHairTop = self.headContainer.attachAsset('boyHair', {
anchorX: 0.5,
anchorY: 0.5,
y: -120,
width: 130,
height: 40,
scaleX: 1.1
});
// Left Eye
var leftEye = self.facialContainer.attachAsset('boyEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -90
});
// Right Eye
var rightEye = self.facialContainer.attachAsset('boyEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -90
});
// Mouth
var mouth = self.facialContainer.attachAsset('boyMouth', {
anchorX: 0.5,
anchorY: 0.5,
y: -60
});
// Left Arm
var leftArm = self.armsContainer.attachAsset('boyArm', {
anchorX: 0.5,
anchorY: 0,
x: -65,
y: -20,
rotation: 0.2
});
// Right Arm
var rightArm = self.armsContainer.attachAsset('boyArm', {
anchorX: 0.5,
anchorY: 0,
x: 65,
y: -20,
rotation: -0.2
});
// Left Leg
var leftLeg = self.legsContainer.attachAsset('boyLeg', {
anchorX: 0.5,
anchorY: 0,
x: -30,
y: 100
});
// Right Leg
var rightLeg = self.legsContainer.attachAsset('boyLeg', {
anchorX: 0.5,
anchorY: 0,
x: 30,
y: 100
});
} else {
// Body
var body = self.bodyContainer.attachAsset('girlBody', {
anchorX: 0.5,
anchorY: 0.5,
y: 30
});
// Head
var head = self.headContainer.attachAsset('girlHead', {
anchorX: 0.5,
anchorY: 0.5,
y: -80
});
// Hair - main part
var hair = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
y: -100
});
// Add additional hair sections for a more styled look
var hairBangs = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
y: -120,
width: 130,
height: 50,
scaleX: 1.1,
scaleY: 0.6
});
// Side hair strands
var leftHairStrand = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0,
x: -60,
y: -100,
width: 40,
height: 120,
scaleY: 1.2
});
var rightHairStrand = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0,
x: 60,
y: -100,
width: 40,
height: 120,
scaleY: 1.2
});
// Left Eye
var leftEye = self.facialContainer.attachAsset('girlEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -90
});
// Right Eye
var rightEye = self.facialContainer.attachAsset('girlEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -90
});
// Mouth
var mouth = self.facialContainer.attachAsset('girlMouth', {
anchorX: 0.5,
anchorY: 0.5,
y: -60
});
// Left Arm
var leftArm = self.armsContainer.attachAsset('girlArm', {
anchorX: 0.5,
anchorY: 0,
x: -65,
y: -20,
rotation: 0.2
});
// Right Arm
var rightArm = self.armsContainer.attachAsset('girlArm', {
anchorX: 0.5,
anchorY: 0,
x: 65,
y: -20,
rotation: -0.2
});
// Left Leg
var leftLeg = self.legsContainer.attachAsset('girlLeg', {
anchorX: 0.5,
anchorY: 0,
x: -30,
y: 100
});
// Right Leg
var rightLeg = self.legsContainer.attachAsset('girlLeg', {
anchorX: 0.5,
anchorY: 0,
x: 30,
y: 100
});
}
;
LK.setInterval(function () {
self.blink();
}, 3000);
// Start with scale 0
self.scaleX = 0;
self.scaleY = 0;
};
// Blink animation
self.blink = function () {
if (self.isBlinking) {
return;
}
var leftEye = self.facialContainer.children[0];
var rightEye = self.facialContainer.children[1];
self.isBlinking = true;
// Close eyes
tween(leftEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Open eyes
tween(leftEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isBlinking = false;
}
});
}
});
};
// Continuous update for idle animations
self.update = function () {
// Bob up and down
self.bobTimer += 0.05;
var bobOffset = Math.sin(self.bobTimer) * 5;
self.headContainer.y = bobOffset * 0.5;
self.bodyContainer.y = bobOffset * 0.3;
// Swing arms slightly
if (self.armsContainer.children.length >= 2) {
var leftArm = self.armsContainer.children[0];
var rightArm = self.armsContainer.children[1];
leftArm.rotation = 0.2 + Math.sin(self.bobTimer) * 0.1;
rightArm.rotation = -0.2 - Math.sin(self.bobTimer) * 0.1;
}
};
// Animate character appearance
self.appear = function () {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.elasticOut
});
// Add a little jump after appearing
LK.setTimeout(function () {
tween(self, {
y: self.y - 30
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 30
}, {
duration: 400,
easing: tween.bounceOut
});
}
});
}, 600);
};
// Handle selection
self.down = function (x, y, obj) {
// Shrink when pressed
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Make eyes bigger on press
if (self.facialContainer.children.length >= 2) {
var leftEye = self.facialContainer.children[0];
var rightEye = self.facialContainer.children[1];
var mouth = self.facialContainer.children[2];
tween(leftEye, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
// Make the character smile when clicked
if (mouth) {
tween(mouth, {
scaleX: 1.5,
scaleY: 1.7,
y: -55
}, {
duration: 200,
easing: tween.elasticOut
});
}
}
};
self.up = function (x, y, obj) {
// Play sound only if settingsButton.soundOn is true
if (!settingsButton || settingsButton.soundOn) {
LK.getSound('buttonClick').play();
}
// Return eyes to normal
if (self.facialContainer.children.length >= 2) {
var leftEye = self.facialContainer.children[0];
var rightEye = self.facialContainer.children[1];
var mouth = self.facialContainer.children[2];
tween(leftEye, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
// Return mouth to normal
if (mouth) {
tween(mouth, {
scaleX: 1.0,
scaleY: 1.0,
y: -60
}, {
duration: 300,
easing: tween.easeOut
});
}
}
// Check if character is on a raft after startGame was called
var parentIsRaft = obj.parent instanceof Raft;
if (parentIsRaft) {
// Get the raft instance
var raft = obj.parent;
// Show "Let's go!" text when clicked on raft
var goText = new Text2("Let's go!", {
size: 80,
fill: 0xFF4500
});
goText.anchor.set(0.5, 0.5);
goText.x = 0;
goText.y = -150;
goText.alpha = 0;
self.addChild(goText);
// Animate text appearance and fade away
tween(goText, {
alpha: 1,
y: goText.y - 50
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// After appearing, fade out
LK.setTimeout(function () {
tween(goText, {
alpha: 0,
y: goText.y - 30
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
self.removeChild(goText);
}
});
}, 1000);
}
});
// Animate the raft moving down with character on it
tween(raft, {
y: 3000 // Move down beyond the screen
}, {
duration: 5000,
easing: tween.easeIn,
onFinish: function onFinish() {
// Game completed or next scene could be triggered here
LK.showYouWin();
}
});
return; // Skip the rest of the function
}
// Show "Hello!" text when clicked (only in character selection)
var helloText = new Text2("Hello!", {
size: 80,
fill: 0xFF4500
});
helloText.anchor.set(0.5, 0.5);
helloText.x = 0;
helloText.y = -150;
helloText.alpha = 0;
self.addChild(helloText);
// Animate text appearance and fade away
tween(helloText, {
alpha: 1,
y: helloText.y - 50
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// After appearing, fade out
LK.setTimeout(function () {
tween(helloText, {
alpha: 0,
y: helloText.y - 30
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
self.removeChild(helloText);
}
});
}, 1000);
}
});
// Expand then return to normal size
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Celebrate selection with a spin
tween(self.headContainer, {
rotation: Math.PI * 2
}, {
duration: 500,
easing: tween.elasticOut
});
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Character selected!
characterSelected(self.type);
}
});
}
});
};
return self;
});
var Ocean = Container.expand(function () {
var self = Container.call(this);
// Water layers
var waterBg = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x0066CC,
// Deep blue
width: 4096,
// Double screen width
height: 3000
});
// Create waves
self.waves = [];
for (var i = 0; i < 8; i++) {
var wave = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x55AADD,
// Lighter blue
alpha: 0.4,
width: 500 + Math.random() * 700,
height: 30,
x: Math.random() * 2048 - 1024,
y: Math.random() * 1000 - 500
});
self.waves.push(wave);
}
// Animation properties
self.waveTimer = 0;
// Update wave positions
self.update = function () {
self.waveTimer += 0.02;
// Animate each wave
for (var i = 0; i < self.waves.length; i++) {
var wave = self.waves[i];
wave.x += 0.5; // Slow movement right
// Loop waves back to the left side when they go off screen
if (wave.x > 2048 + wave.width / 2) {
wave.x = -wave.width / 2;
wave.y = Math.random() * 1000 - 500;
}
// Slight bobbing
wave.y += Math.sin(self.waveTimer + i) * 0.5;
}
};
return self;
});
var PlayButton = Container.expand(function () {
var self = Container.call(this);
// Create shadow first so it appears behind the button
var shadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 10,
y: 10
});
// Create base circle
var buttonBase = self.attachAsset('playButtonBase', {
anchorX: 0.5,
anchorY: 0.5
});
// Create play triangle and rotate it to point right
var playIcon = self.attachAsset('playTriangle', {
anchorX: 0.5,
anchorY: 0.5,
x: 15,
// Offset slightly to the right for better visual centering
rotation: Math.PI / 4 // 45 degrees in radians
});
// Variables to track button state
self.isPressed = false;
self.isAnimating = false;
// Set interactive state functions
self.down = function (x, y, obj) {
if (self.isAnimating) {
return;
}
self.isPressed = true;
// Shrink button when pressed
tween(buttonBase, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
tween(playIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Move shadow closer
tween(shadow, {
x: 5,
y: 5
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.isPressed || self.isAnimating) {
return;
}
self.isPressed = false;
self.isAnimating = true;
// Play sound only if settingsButton.soundOn is true
if (!settingsButton || settingsButton.soundOn) {
LK.getSound('buttonClick').play();
}
// Return to normal size with a bounce
tween(buttonBase, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(buttonBase, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
// Trigger the "play" action
self.triggerPlay();
}
});
}
});
// Return play icon to normal with a bounce
tween(playIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(playIcon, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Return shadow to normal position
tween(shadow, {
x: 10,
y: 10
}, {
duration: 200,
easing: tween.easeOut
});
};
// Function called when button is clicked
self.triggerPlay = function () {
// Spin the button when clicked
self.isAnimating = true;
// Celebrate by spinning the button
tween(self, {
rotation: Math.PI * 2
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
self.rotation = 0;
self.isAnimating = false;
// Show character selection
showCharacterSelection();
}
});
};
// Idle animation to make the button more playful
self.startIdleAnimation = function () {
function pulseButton() {
if (self.isPressed || self.isAnimating) {
LK.setTimeout(pulseButton, 2000);
return;
}
tween(buttonBase, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(buttonBase, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(pulseButton, 2000);
}
});
}
});
}
// Start the idle animation
LK.setTimeout(pulseButton, 2000);
};
// Initial scale effect when the button appears
buttonBase.scaleX = 0;
buttonBase.scaleY = 0;
playIcon.scaleX = 0;
playIcon.scaleY = 0;
shadow.scaleX = 0;
shadow.scaleY = 0;
self.appear = function () {
tween(shadow, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.elasticOut
});
tween(buttonBase, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
tween(playIcon, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut,
onFinish: function onFinish() {
self.startIdleAnimation();
}
});
};
return self;
});
var Raft = Container.expand(function () {
var self = Container.call(this);
// Create raft base
var raftBase = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8B4513,
// Brown color for wood
width: 400,
height: 200
});
// Create wood planks
for (var i = 0; i < 5; i++) {
var plank = self.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x995533,
// Slightly different brown
width: 350,
height: 30,
y: -80 + i * 40
});
}
// Bob animation values
self.bobTimer = 0;
self.bobAmount = 5;
// Update for bobbing animation
self.update = function () {
self.bobTimer += 0.03;
self.y = self.bobAmount * Math.sin(self.bobTimer);
// Slight rotation to simulate waves
self.rotation = Math.sin(self.bobTimer * 0.7) * 0.02;
};
return self;
});
var SettingsButton = Container.expand(function () {
var self = Container.call(this);
// Create shadow for button
var shadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 5,
y: 5,
scaleX: 0.6,
scaleY: 0.6
});
// Create button base
var buttonBase = self.attachAsset('playButtonBase', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x555555,
scaleX: 0.6,
scaleY: 0.6
});
// Track sound state
self.soundOn = true;
// Add text to button
var buttonText = new Text2("Sound ON", {
size: 50,
fill: '#FFFFFF'
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Variables to track button state
self.isPressed = false;
self.isAnimating = false;
// Set interactive state functions
self.down = function (x, y, obj) {
if (self.isAnimating) {
return;
}
self.isPressed = true;
// Shrink button when pressed
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.isPressed || self.isAnimating) {
return;
}
self.isPressed = false;
self.isAnimating = true;
// Play sound only if sound is still on
if (self.soundOn) {
LK.getSound('buttonClick').play();
}
// Return to normal size with a bounce
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
// Toggle sound
self.toggleSound();
}
});
}
});
};
// Toggle sound on/off
self.toggleSound = function () {
self.soundOn = !self.soundOn;
// Update button text
buttonText.setText(self.soundOn ? "Sound ON" : "Sound OFF");
// Update button color
tween(buttonBase, {
tint: self.soundOn ? 0x555555 : 0x993333
}, {
duration: 300,
easing: tween.easeOut
});
// Set global sound mute state using available methods
if (self.soundOn) {
// Use LK.getSound() to control individual sounds
// Set volume back to normal for any future sounds
var buttonSound = LK.getSound('buttonClick');
var gameMusic = LK.getSound('TheCool9');
if (buttonSound) {
buttonSound.volume = 0.7;
}
if (gameMusic) {
gameMusic.volume = 1.0;
}
} else {
// Mute all sounds by setting their volume to 0
var buttonSound = LK.getSound('buttonClick');
var gameMusic = LK.getSound('TheCool9');
if (buttonSound) {
buttonSound.volume = 0;
}
if (gameMusic) {
gameMusic.volume = 0;
}
}
};
// Initial animation when button appears
self.appear = function () {
self.scaleX = 0;
self.scaleY = 0;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
};
return self;
});
var Shore = Container.expand(function () {
var self = Container.call(this);
// Create sandy beach
var sand = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xF4D03F,
// Sandy color
width: 800,
height: 500
});
// Create some palm trees
var palm1 = self.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 1.0,
tint: 0x6E2C00,
// Brown trunk
width: 40,
height: 200,
x: -150,
y: -100,
rotation: -0.1
});
var palm2 = self.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 1.0,
tint: 0x6E2C00,
// Brown trunk
width: 40,
height: 180,
x: 180,
y: -120,
rotation: 0.15
});
// Create palm leaves
var leaves1 = self.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2ECC71,
// Green
width: 200,
height: 150,
x: -150,
y: -250
});
var leaves2 = self.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2ECC71,
// Green
width: 200,
height: 150,
x: 180,
y: -270
});
return self;
});
var StartGameButton = Container.expand(function () {
var self = Container.call(this);
// Create shadow for button
var shadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 10,
y: 10
});
// Create button base
var buttonBase = self.attachAsset('playButtonBase', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4CAF50 // Green color for start button
});
// Add text to button
var buttonText = new Text2("Start Game", {
size: 80,
fill: '#FFFFFF'
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Variables to track button state
self.isPressed = false;
self.isAnimating = false;
// Set interactive state functions
self.down = function (x, y, obj) {
if (self.isAnimating) {
return;
}
self.isPressed = true;
// Shrink button when pressed
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Move shadow closer
tween(shadow, {
x: 5,
y: 5
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.isPressed || self.isAnimating) {
return;
}
self.isPressed = false;
self.isAnimating = true;
// Play sound only if settingsButton.soundOn is true
if (!settingsButton || settingsButton.soundOn) {
LK.getSound('buttonClick').play();
}
// Return to normal size with a bounce
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
// Make button disappear
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove button
if (self.parent) {
self.parent.removeChild(self);
}
// Find raft and character
var raft = null;
var shore = null;
var character = null;
// Find raft and shore in the scene
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof Raft) {
raft = game.children[i];
}
if (game.children[i] instanceof Shore) {
shore = game.children[i];
}
}
if (raft && raft.children.length > 0) {
// Find the character in the raft
for (var j = 0; j < raft.children.length; j++) {
if (raft.children[j] instanceof Character) {
character = raft.children[j];
}
}
if (character && shore) {
// Move character out of raft
var globalCharPos = raft.toGlobal(character.position);
game.addChild(character);
character.position = globalCharPos;
// Make character swim animation
var swimToShore = function swimToShore() {
// Make character "swim" by moving arms and legs
if (character.armsContainer && character.armsContainer.children.length >= 2) {
var leftArm = character.armsContainer.children[0];
var rightArm = character.armsContainer.children[1];
// Animate arms in swimming motion
tween.loop(leftArm, {
rotation: [-0.2, 0.8, -0.2]
}, {
duration: 800
});
tween.loop(rightArm, {
rotation: [0.2, -0.8, 0.2]
}, {
duration: 800
});
}
if (character.legsContainer && character.legsContainer.children.length >= 2) {
var leftLeg = character.legsContainer.children[0];
var rightLeg = character.legsContainer.children[1];
// Animate legs in swimming motion
tween.loop(leftLeg, {
rotation: [0, 0.3, 0]
}, {
duration: 600
});
tween.loop(rightLeg, {
rotation: [0, -0.3, 0]
}, {
duration: 600
});
}
// Move character toward shore
tween(character, {
y: shore.y - 100 // Stop just above shore
}, {
duration: 5000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Character reached the shore
// Stop swimming animation
if (character.armsContainer && character.armsContainer.children.length >= 2) {
tween.stopAll(character.armsContainer.children[0]);
tween.stopAll(character.armsContainer.children[1]);
}
if (character.legsContainer && character.legsContainer.children.length >= 2) {
tween.stopAll(character.legsContainer.children[0]);
tween.stopAll(character.legsContainer.children[1]);
}
// Show celebration
var celebrateText = new Text2("Made it to shore!", {
size: 100,
fill: 0xFF4500
});
celebrateText.anchor.set(0.5, 0.5);
celebrateText.x = 2048 / 2;
celebrateText.y = 500;
celebrateText.alpha = 0;
game.addChild(celebrateText);
tween(celebrateText, {
alpha: 1,
y: celebrateText.y - 50
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Show win screen after delay
LK.setTimeout(function () {
LK.showYouWin();
}, 2000);
}
});
}
});
};
// Move raft away to simulate "exiting" the raft
tween(raft, {
y: raft.y - 150,
rotation: 0.3
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: swimToShore
});
}
}
}
});
}
});
}
});
// Return shadow to normal position
tween(shadow, {
x: 10,
y: 10
}, {
duration: 200,
easing: tween.easeOut
});
};
// Initial animation when button appears
self.appear = function () {
self.scaleX = 0;
self.scaleY = 0;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x00FF00
});
/****
* Game Code
****/
// Set the game's background color to a softer green
game.setBackgroundColor(0x66CC99);
// Game state variables
var showingCharacterSelection = false;
var selectedCharacter = null;
var boyCharacter = null;
var girlCharacter = null;
// Create and add settings button
var settingsButton = new SettingsButton();
game.addChild(settingsButton);
// Position in top right with some margin
settingsButton.x = 2048 - 120;
settingsButton.y = 120;
// Make the button appear with animation
settingsButton.appear();
// Update function for character animations and ocean/raft
game.update = function () {
// Update character animations if they exist
if (boyCharacter) {
boyCharacter.update();
}
if (girlCharacter) {
girlCharacter.update();
}
// Update ocean and raft if they exist
for (var i = 0; i < game.children.length; i++) {
var child = game.children[i];
if (child instanceof Ocean) {
child.update();
}
if (child instanceof Raft) {
child.update();
}
}
};
// Create the play button and center it on screen
var playButton = new PlayButton();
game.addChild(playButton);
// Position the button in the center of the screen
playButton.x = 2048 / 2;
playButton.y = 2732 / 2;
// Make the button appear with animation
playButton.appear();
// Function to show character selection screen
function showCharacterSelection() {
if (showingCharacterSelection) {
return;
}
showingCharacterSelection = true;
// Make play button disappear
tween(playButton, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove play button from display
game.removeChild(playButton);
// Create character options
boyCharacter = new Character();
boyCharacter.initialize("boy");
game.addChild(boyCharacter);
boyCharacter.x = 2048 / 3;
boyCharacter.y = 2732 / 2;
girlCharacter = new Character();
girlCharacter.initialize("girl");
game.addChild(girlCharacter);
girlCharacter.x = 2048 * 2 / 3;
girlCharacter.y = 2732 / 2;
// Make characters appear with animation
boyCharacter.appear();
girlCharacter.appear();
}
});
}
// Function called when a character is selected
function characterSelected(characterType) {
selectedCharacter = characterType;
console.log("Selected character: " + characterType);
// Make the non-selected character sad and disappear
var nonSelectedCharacter = characterType === "boy" ? girlCharacter : boyCharacter;
var selectedCharacterObj = characterType === "boy" ? boyCharacter : girlCharacter;
// Make selected character happy
if (selectedCharacterObj.facialContainer.children.length >= 3) {
var mouth = selectedCharacterObj.facialContainer.children[2];
// Make mouth bigger and smile
tween(mouth, {
scaleX: 1.5,
scaleY: 1.5,
y: -55
}, {
duration: 300,
easing: tween.elasticOut
});
}
// Make non-selected character sad
if (nonSelectedCharacter.facialContainer.children.length >= 3) {
var sadMouth = nonSelectedCharacter.facialContainer.children[2];
// Make mouth smaller and frown
tween(sadMouth, {
scaleX: 0.8,
scaleY: -1.2,
y: -50
}, {
duration: 300,
easing: tween.easeOut
});
}
// Fade out and shrink non-selected character
tween(nonSelectedCharacter, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(nonSelectedCharacter);
}
});
// Jump and move the selected character to center
LK.setTimeout(function () {
// Jump up first
tween(selectedCharacterObj, {
y: selectedCharacterObj.y - 100
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move to center while in air
tween(selectedCharacterObj, {
x: 2048 / 2
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
// Land with bounce
tween(selectedCharacterObj, {
y: 2732 / 2,
scaleY: 0.7,
scaleX: 1.3
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
// Bounce back to normal
tween(selectedCharacterObj, {
scaleY: 1.1,
scaleX: 0.9
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to normal scale
tween(selectedCharacterObj, {
scaleY: 1.0,
scaleX: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Celebrate with a spin
tween(selectedCharacterObj.headContainer, {
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Reset rotation
selectedCharacterObj.headContainer.rotation = 0;
// Add start game button
var startGameBtn = new StartGameButton();
game.addChild(startGameBtn);
startGameBtn.x = 2048 / 2;
startGameBtn.y = 2732 / 2 + 350; // Position below character
startGameBtn.appear();
}
});
}
});
}
});
}
});
}
});
}
});
}, 300);
}
// Function to start the game
function startGame() {
console.log("Starting game with character: " + selectedCharacter);
// Store the current background color
var originalBackgroundColor = game.backgroundColor;
// Create a black overlay for the screen
var blackOverlay = new Container();
var blackBg = blackOverlay.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: 4096,
// Make it twice the screen width to ensure full coverage
height: 5464,
// Make it twice the screen height to ensure full coverage
tint: 0x000000,
// Pure black
alpha: 0
});
game.addChild(blackOverlay);
blackOverlay.x = 2048 / 2;
blackOverlay.y = 2732 / 2;
// Fade to black
tween(blackBg, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Wait for 3 seconds with black screen
LK.setTimeout(function () {
// Create ocean scene
var ocean = new Ocean();
ocean.x = 2048 / 2;
ocean.y = 2732 / 2;
game.addChild(ocean);
// Create shore at the far side
var shore = new Shore();
shore.x = 2048 / 2;
shore.y = 3000; // Position below the screen
game.addChild(shore);
// Create raft and position it in the center
var raft = new Raft();
raft.x = 2048 / 2;
raft.y = 2732 / 2;
game.addChild(raft);
// Add the selected character to the raft
var selectedCharacterObj = selectedCharacter === "boy" ? boyCharacter : girlCharacter;
// Move character to raft
raft.addChild(selectedCharacterObj);
selectedCharacterObj.x = 0;
selectedCharacterObj.y = -80; // Position on raft
// Remove settings button and any remaining UI
if (settingsButton && settingsButton.parent) {
game.removeChild(settingsButton);
}
// Create start game button to trigger swimming animation
var startGameBtn = new StartGameButton();
game.addChild(startGameBtn);
startGameBtn.x = 2048 / 2;
startGameBtn.y = 2732 - 200; // Position near bottom
startGameBtn.appear();
// Fade the black screen out
tween(blackBg, {
alpha: 0
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
// Remove the black overlay
game.removeChild(blackOverlay);
// Set game background to sky blue
game.setBackgroundColor(0x87CEEB);
}
});
}, 3000);
}
});
}
// Rainbow effect for the background
var rainbowColors = [0x66CC99, 0x66CCFF, 0xCC99FF, 0xFF99CC, 0xFFCC66, 0x99FF99];
var currentColorIndex = 0;
// A function to cycle through background colors
function cycleBackgroundColor() {
currentColorIndex = (currentColorIndex + 1) % rainbowColors.length;
// Animate the color change
var targetColor = rainbowColors[currentColorIndex];
tween(game, {
backgroundColor: targetColor
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Schedule the next color change
LK.setTimeout(cycleBackgroundColor, 4000);
}
});
}
// Start the background color animation after a delay
LK.setTimeout(cycleBackgroundColor, 4000); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Character = Container.expand(function () {
var self = Container.call(this);
// Create base circle under character
var base = self.attachAsset('characterBase', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
// Character type (boy or girl)
self.type = "";
// Character containers
self.bodyContainer = new Container();
self.headContainer = new Container();
self.armsContainer = new Container();
self.legsContainer = new Container();
self.facialContainer = new Container();
// Add all containers to self
self.addChild(self.legsContainer);
self.addChild(self.bodyContainer);
self.addChild(self.armsContainer);
self.addChild(self.headContainer);
self.addChild(self.facialContainer);
// Animation properties
self.bobTimer = 0;
self.blinkTimer = 0;
self.isBlinking = false;
self.armSwingDirection = 1;
// Initialize with type
self.initialize = function (characterType) {
self.type = characterType;
// Reset containers
self.bodyContainer.removeChildren();
self.headContainer.removeChildren();
self.armsContainer.removeChildren();
self.legsContainer.removeChildren();
self.facialContainer.removeChildren();
// Build character based on type
if (characterType === "boy") {
// Body
var body = self.bodyContainer.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 0.5,
y: 30
});
// Head
var head = self.headContainer.attachAsset('boyHead', {
anchorX: 0.5,
anchorY: 0.5,
y: -80
});
// Hair for boy character - simple short hair that sticks to the head
var boyHairTop = self.headContainer.attachAsset('boyHair', {
anchorX: 0.5,
anchorY: 0.5,
y: -120,
width: 130,
height: 40,
scaleX: 1.1
});
// Left Eye
var leftEye = self.facialContainer.attachAsset('boyEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -90
});
// Right Eye
var rightEye = self.facialContainer.attachAsset('boyEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -90
});
// Mouth
var mouth = self.facialContainer.attachAsset('boyMouth', {
anchorX: 0.5,
anchorY: 0.5,
y: -60
});
// Left Arm
var leftArm = self.armsContainer.attachAsset('boyArm', {
anchorX: 0.5,
anchorY: 0,
x: -65,
y: -20,
rotation: 0.2
});
// Right Arm
var rightArm = self.armsContainer.attachAsset('boyArm', {
anchorX: 0.5,
anchorY: 0,
x: 65,
y: -20,
rotation: -0.2
});
// Left Leg
var leftLeg = self.legsContainer.attachAsset('boyLeg', {
anchorX: 0.5,
anchorY: 0,
x: -30,
y: 100
});
// Right Leg
var rightLeg = self.legsContainer.attachAsset('boyLeg', {
anchorX: 0.5,
anchorY: 0,
x: 30,
y: 100
});
} else {
// Body
var body = self.bodyContainer.attachAsset('girlBody', {
anchorX: 0.5,
anchorY: 0.5,
y: 30
});
// Head
var head = self.headContainer.attachAsset('girlHead', {
anchorX: 0.5,
anchorY: 0.5,
y: -80
});
// Hair - main part
var hair = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
y: -100
});
// Add additional hair sections for a more styled look
var hairBangs = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
y: -120,
width: 130,
height: 50,
scaleX: 1.1,
scaleY: 0.6
});
// Side hair strands
var leftHairStrand = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0,
x: -60,
y: -100,
width: 40,
height: 120,
scaleY: 1.2
});
var rightHairStrand = self.headContainer.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0,
x: 60,
y: -100,
width: 40,
height: 120,
scaleY: 1.2
});
// Left Eye
var leftEye = self.facialContainer.attachAsset('girlEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: -90
});
// Right Eye
var rightEye = self.facialContainer.attachAsset('girlEyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: -90
});
// Mouth
var mouth = self.facialContainer.attachAsset('girlMouth', {
anchorX: 0.5,
anchorY: 0.5,
y: -60
});
// Left Arm
var leftArm = self.armsContainer.attachAsset('girlArm', {
anchorX: 0.5,
anchorY: 0,
x: -65,
y: -20,
rotation: 0.2
});
// Right Arm
var rightArm = self.armsContainer.attachAsset('girlArm', {
anchorX: 0.5,
anchorY: 0,
x: 65,
y: -20,
rotation: -0.2
});
// Left Leg
var leftLeg = self.legsContainer.attachAsset('girlLeg', {
anchorX: 0.5,
anchorY: 0,
x: -30,
y: 100
});
// Right Leg
var rightLeg = self.legsContainer.attachAsset('girlLeg', {
anchorX: 0.5,
anchorY: 0,
x: 30,
y: 100
});
}
;
LK.setInterval(function () {
self.blink();
}, 3000);
// Start with scale 0
self.scaleX = 0;
self.scaleY = 0;
};
// Blink animation
self.blink = function () {
if (self.isBlinking) {
return;
}
var leftEye = self.facialContainer.children[0];
var rightEye = self.facialContainer.children[1];
self.isBlinking = true;
// Close eyes
tween(leftEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Open eyes
tween(leftEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isBlinking = false;
}
});
}
});
};
// Continuous update for idle animations
self.update = function () {
// Bob up and down
self.bobTimer += 0.05;
var bobOffset = Math.sin(self.bobTimer) * 5;
self.headContainer.y = bobOffset * 0.5;
self.bodyContainer.y = bobOffset * 0.3;
// Swing arms slightly
if (self.armsContainer.children.length >= 2) {
var leftArm = self.armsContainer.children[0];
var rightArm = self.armsContainer.children[1];
leftArm.rotation = 0.2 + Math.sin(self.bobTimer) * 0.1;
rightArm.rotation = -0.2 - Math.sin(self.bobTimer) * 0.1;
}
};
// Animate character appearance
self.appear = function () {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.elasticOut
});
// Add a little jump after appearing
LK.setTimeout(function () {
tween(self, {
y: self.y - 30
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 30
}, {
duration: 400,
easing: tween.bounceOut
});
}
});
}, 600);
};
// Handle selection
self.down = function (x, y, obj) {
// Shrink when pressed
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Make eyes bigger on press
if (self.facialContainer.children.length >= 2) {
var leftEye = self.facialContainer.children[0];
var rightEye = self.facialContainer.children[1];
var mouth = self.facialContainer.children[2];
tween(leftEye, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
// Make the character smile when clicked
if (mouth) {
tween(mouth, {
scaleX: 1.5,
scaleY: 1.7,
y: -55
}, {
duration: 200,
easing: tween.elasticOut
});
}
}
};
self.up = function (x, y, obj) {
// Play sound only if settingsButton.soundOn is true
if (!settingsButton || settingsButton.soundOn) {
LK.getSound('buttonClick').play();
}
// Return eyes to normal
if (self.facialContainer.children.length >= 2) {
var leftEye = self.facialContainer.children[0];
var rightEye = self.facialContainer.children[1];
var mouth = self.facialContainer.children[2];
tween(leftEye, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
tween(rightEye, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
// Return mouth to normal
if (mouth) {
tween(mouth, {
scaleX: 1.0,
scaleY: 1.0,
y: -60
}, {
duration: 300,
easing: tween.easeOut
});
}
}
// Check if character is on a raft after startGame was called
var parentIsRaft = obj.parent instanceof Raft;
if (parentIsRaft) {
// Get the raft instance
var raft = obj.parent;
// Show "Let's go!" text when clicked on raft
var goText = new Text2("Let's go!", {
size: 80,
fill: 0xFF4500
});
goText.anchor.set(0.5, 0.5);
goText.x = 0;
goText.y = -150;
goText.alpha = 0;
self.addChild(goText);
// Animate text appearance and fade away
tween(goText, {
alpha: 1,
y: goText.y - 50
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// After appearing, fade out
LK.setTimeout(function () {
tween(goText, {
alpha: 0,
y: goText.y - 30
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
self.removeChild(goText);
}
});
}, 1000);
}
});
// Animate the raft moving down with character on it
tween(raft, {
y: 3000 // Move down beyond the screen
}, {
duration: 5000,
easing: tween.easeIn,
onFinish: function onFinish() {
// Game completed or next scene could be triggered here
LK.showYouWin();
}
});
return; // Skip the rest of the function
}
// Show "Hello!" text when clicked (only in character selection)
var helloText = new Text2("Hello!", {
size: 80,
fill: 0xFF4500
});
helloText.anchor.set(0.5, 0.5);
helloText.x = 0;
helloText.y = -150;
helloText.alpha = 0;
self.addChild(helloText);
// Animate text appearance and fade away
tween(helloText, {
alpha: 1,
y: helloText.y - 50
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// After appearing, fade out
LK.setTimeout(function () {
tween(helloText, {
alpha: 0,
y: helloText.y - 30
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
self.removeChild(helloText);
}
});
}, 1000);
}
});
// Expand then return to normal size
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Celebrate selection with a spin
tween(self.headContainer, {
rotation: Math.PI * 2
}, {
duration: 500,
easing: tween.elasticOut
});
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Character selected!
characterSelected(self.type);
}
});
}
});
};
return self;
});
var Ocean = Container.expand(function () {
var self = Container.call(this);
// Water layers
var waterBg = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x0066CC,
// Deep blue
width: 4096,
// Double screen width
height: 3000
});
// Create waves
self.waves = [];
for (var i = 0; i < 8; i++) {
var wave = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x55AADD,
// Lighter blue
alpha: 0.4,
width: 500 + Math.random() * 700,
height: 30,
x: Math.random() * 2048 - 1024,
y: Math.random() * 1000 - 500
});
self.waves.push(wave);
}
// Animation properties
self.waveTimer = 0;
// Update wave positions
self.update = function () {
self.waveTimer += 0.02;
// Animate each wave
for (var i = 0; i < self.waves.length; i++) {
var wave = self.waves[i];
wave.x += 0.5; // Slow movement right
// Loop waves back to the left side when they go off screen
if (wave.x > 2048 + wave.width / 2) {
wave.x = -wave.width / 2;
wave.y = Math.random() * 1000 - 500;
}
// Slight bobbing
wave.y += Math.sin(self.waveTimer + i) * 0.5;
}
};
return self;
});
var PlayButton = Container.expand(function () {
var self = Container.call(this);
// Create shadow first so it appears behind the button
var shadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 10,
y: 10
});
// Create base circle
var buttonBase = self.attachAsset('playButtonBase', {
anchorX: 0.5,
anchorY: 0.5
});
// Create play triangle and rotate it to point right
var playIcon = self.attachAsset('playTriangle', {
anchorX: 0.5,
anchorY: 0.5,
x: 15,
// Offset slightly to the right for better visual centering
rotation: Math.PI / 4 // 45 degrees in radians
});
// Variables to track button state
self.isPressed = false;
self.isAnimating = false;
// Set interactive state functions
self.down = function (x, y, obj) {
if (self.isAnimating) {
return;
}
self.isPressed = true;
// Shrink button when pressed
tween(buttonBase, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
tween(playIcon, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Move shadow closer
tween(shadow, {
x: 5,
y: 5
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.isPressed || self.isAnimating) {
return;
}
self.isPressed = false;
self.isAnimating = true;
// Play sound only if settingsButton.soundOn is true
if (!settingsButton || settingsButton.soundOn) {
LK.getSound('buttonClick').play();
}
// Return to normal size with a bounce
tween(buttonBase, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(buttonBase, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
// Trigger the "play" action
self.triggerPlay();
}
});
}
});
// Return play icon to normal with a bounce
tween(playIcon, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(playIcon, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Return shadow to normal position
tween(shadow, {
x: 10,
y: 10
}, {
duration: 200,
easing: tween.easeOut
});
};
// Function called when button is clicked
self.triggerPlay = function () {
// Spin the button when clicked
self.isAnimating = true;
// Celebrate by spinning the button
tween(self, {
rotation: Math.PI * 2
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
self.rotation = 0;
self.isAnimating = false;
// Show character selection
showCharacterSelection();
}
});
};
// Idle animation to make the button more playful
self.startIdleAnimation = function () {
function pulseButton() {
if (self.isPressed || self.isAnimating) {
LK.setTimeout(pulseButton, 2000);
return;
}
tween(buttonBase, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(buttonBase, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(pulseButton, 2000);
}
});
}
});
}
// Start the idle animation
LK.setTimeout(pulseButton, 2000);
};
// Initial scale effect when the button appears
buttonBase.scaleX = 0;
buttonBase.scaleY = 0;
playIcon.scaleX = 0;
playIcon.scaleY = 0;
shadow.scaleX = 0;
shadow.scaleY = 0;
self.appear = function () {
tween(shadow, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.elasticOut
});
tween(buttonBase, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
tween(playIcon, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut,
onFinish: function onFinish() {
self.startIdleAnimation();
}
});
};
return self;
});
var Raft = Container.expand(function () {
var self = Container.call(this);
// Create raft base
var raftBase = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x8B4513,
// Brown color for wood
width: 400,
height: 200
});
// Create wood planks
for (var i = 0; i < 5; i++) {
var plank = self.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x995533,
// Slightly different brown
width: 350,
height: 30,
y: -80 + i * 40
});
}
// Bob animation values
self.bobTimer = 0;
self.bobAmount = 5;
// Update for bobbing animation
self.update = function () {
self.bobTimer += 0.03;
self.y = self.bobAmount * Math.sin(self.bobTimer);
// Slight rotation to simulate waves
self.rotation = Math.sin(self.bobTimer * 0.7) * 0.02;
};
return self;
});
var SettingsButton = Container.expand(function () {
var self = Container.call(this);
// Create shadow for button
var shadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 5,
y: 5,
scaleX: 0.6,
scaleY: 0.6
});
// Create button base
var buttonBase = self.attachAsset('playButtonBase', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x555555,
scaleX: 0.6,
scaleY: 0.6
});
// Track sound state
self.soundOn = true;
// Add text to button
var buttonText = new Text2("Sound ON", {
size: 50,
fill: '#FFFFFF'
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Variables to track button state
self.isPressed = false;
self.isAnimating = false;
// Set interactive state functions
self.down = function (x, y, obj) {
if (self.isAnimating) {
return;
}
self.isPressed = true;
// Shrink button when pressed
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.isPressed || self.isAnimating) {
return;
}
self.isPressed = false;
self.isAnimating = true;
// Play sound only if sound is still on
if (self.soundOn) {
LK.getSound('buttonClick').play();
}
// Return to normal size with a bounce
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
// Toggle sound
self.toggleSound();
}
});
}
});
};
// Toggle sound on/off
self.toggleSound = function () {
self.soundOn = !self.soundOn;
// Update button text
buttonText.setText(self.soundOn ? "Sound ON" : "Sound OFF");
// Update button color
tween(buttonBase, {
tint: self.soundOn ? 0x555555 : 0x993333
}, {
duration: 300,
easing: tween.easeOut
});
// Set global sound mute state using available methods
if (self.soundOn) {
// Use LK.getSound() to control individual sounds
// Set volume back to normal for any future sounds
var buttonSound = LK.getSound('buttonClick');
var gameMusic = LK.getSound('TheCool9');
if (buttonSound) {
buttonSound.volume = 0.7;
}
if (gameMusic) {
gameMusic.volume = 1.0;
}
} else {
// Mute all sounds by setting their volume to 0
var buttonSound = LK.getSound('buttonClick');
var gameMusic = LK.getSound('TheCool9');
if (buttonSound) {
buttonSound.volume = 0;
}
if (gameMusic) {
gameMusic.volume = 0;
}
}
};
// Initial animation when button appears
self.appear = function () {
self.scaleX = 0;
self.scaleY = 0;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
};
return self;
});
var Shore = Container.expand(function () {
var self = Container.call(this);
// Create sandy beach
var sand = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xF4D03F,
// Sandy color
width: 800,
height: 500
});
// Create some palm trees
var palm1 = self.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 1.0,
tint: 0x6E2C00,
// Brown trunk
width: 40,
height: 200,
x: -150,
y: -100,
rotation: -0.1
});
var palm2 = self.attachAsset('boyBody', {
anchorX: 0.5,
anchorY: 1.0,
tint: 0x6E2C00,
// Brown trunk
width: 40,
height: 180,
x: 180,
y: -120,
rotation: 0.15
});
// Create palm leaves
var leaves1 = self.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2ECC71,
// Green
width: 200,
height: 150,
x: -150,
y: -250
});
var leaves2 = self.attachAsset('girlHair', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x2ECC71,
// Green
width: 200,
height: 150,
x: 180,
y: -270
});
return self;
});
var StartGameButton = Container.expand(function () {
var self = Container.call(this);
// Create shadow for button
var shadow = self.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
x: 10,
y: 10
});
// Create button base
var buttonBase = self.attachAsset('playButtonBase', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x4CAF50 // Green color for start button
});
// Add text to button
var buttonText = new Text2("Start Game", {
size: 80,
fill: '#FFFFFF'
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
// Variables to track button state
self.isPressed = false;
self.isAnimating = false;
// Set interactive state functions
self.down = function (x, y, obj) {
if (self.isAnimating) {
return;
}
self.isPressed = true;
// Shrink button when pressed
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
// Move shadow closer
tween(shadow, {
x: 5,
y: 5
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function (x, y, obj) {
if (!self.isPressed || self.isAnimating) {
return;
}
self.isPressed = false;
self.isAnimating = true;
// Play sound only if settingsButton.soundOn is true
if (!settingsButton || settingsButton.soundOn) {
LK.getSound('buttonClick').play();
}
// Return to normal size with a bounce
tween(self, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isAnimating = false;
// Make button disappear
tween(self, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove button
if (self.parent) {
self.parent.removeChild(self);
}
// Find raft and character
var raft = null;
var shore = null;
var character = null;
// Find raft and shore in the scene
for (var i = 0; i < game.children.length; i++) {
if (game.children[i] instanceof Raft) {
raft = game.children[i];
}
if (game.children[i] instanceof Shore) {
shore = game.children[i];
}
}
if (raft && raft.children.length > 0) {
// Find the character in the raft
for (var j = 0; j < raft.children.length; j++) {
if (raft.children[j] instanceof Character) {
character = raft.children[j];
}
}
if (character && shore) {
// Move character out of raft
var globalCharPos = raft.toGlobal(character.position);
game.addChild(character);
character.position = globalCharPos;
// Make character swim animation
var swimToShore = function swimToShore() {
// Make character "swim" by moving arms and legs
if (character.armsContainer && character.armsContainer.children.length >= 2) {
var leftArm = character.armsContainer.children[0];
var rightArm = character.armsContainer.children[1];
// Animate arms in swimming motion
tween.loop(leftArm, {
rotation: [-0.2, 0.8, -0.2]
}, {
duration: 800
});
tween.loop(rightArm, {
rotation: [0.2, -0.8, 0.2]
}, {
duration: 800
});
}
if (character.legsContainer && character.legsContainer.children.length >= 2) {
var leftLeg = character.legsContainer.children[0];
var rightLeg = character.legsContainer.children[1];
// Animate legs in swimming motion
tween.loop(leftLeg, {
rotation: [0, 0.3, 0]
}, {
duration: 600
});
tween.loop(rightLeg, {
rotation: [0, -0.3, 0]
}, {
duration: 600
});
}
// Move character toward shore
tween(character, {
y: shore.y - 100 // Stop just above shore
}, {
duration: 5000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Character reached the shore
// Stop swimming animation
if (character.armsContainer && character.armsContainer.children.length >= 2) {
tween.stopAll(character.armsContainer.children[0]);
tween.stopAll(character.armsContainer.children[1]);
}
if (character.legsContainer && character.legsContainer.children.length >= 2) {
tween.stopAll(character.legsContainer.children[0]);
tween.stopAll(character.legsContainer.children[1]);
}
// Show celebration
var celebrateText = new Text2("Made it to shore!", {
size: 100,
fill: 0xFF4500
});
celebrateText.anchor.set(0.5, 0.5);
celebrateText.x = 2048 / 2;
celebrateText.y = 500;
celebrateText.alpha = 0;
game.addChild(celebrateText);
tween(celebrateText, {
alpha: 1,
y: celebrateText.y - 50
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Show win screen after delay
LK.setTimeout(function () {
LK.showYouWin();
}, 2000);
}
});
}
});
};
// Move raft away to simulate "exiting" the raft
tween(raft, {
y: raft.y - 150,
rotation: 0.3
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: swimToShore
});
}
}
}
});
}
});
}
});
// Return shadow to normal position
tween(shadow, {
x: 10,
y: 10
}, {
duration: 200,
easing: tween.easeOut
});
};
// Initial animation when button appears
self.appear = function () {
self.scaleX = 0;
self.scaleY = 0;
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 700,
easing: tween.elasticOut
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x00FF00
});
/****
* Game Code
****/
// Set the game's background color to a softer green
game.setBackgroundColor(0x66CC99);
// Game state variables
var showingCharacterSelection = false;
var selectedCharacter = null;
var boyCharacter = null;
var girlCharacter = null;
// Create and add settings button
var settingsButton = new SettingsButton();
game.addChild(settingsButton);
// Position in top right with some margin
settingsButton.x = 2048 - 120;
settingsButton.y = 120;
// Make the button appear with animation
settingsButton.appear();
// Update function for character animations and ocean/raft
game.update = function () {
// Update character animations if they exist
if (boyCharacter) {
boyCharacter.update();
}
if (girlCharacter) {
girlCharacter.update();
}
// Update ocean and raft if they exist
for (var i = 0; i < game.children.length; i++) {
var child = game.children[i];
if (child instanceof Ocean) {
child.update();
}
if (child instanceof Raft) {
child.update();
}
}
};
// Create the play button and center it on screen
var playButton = new PlayButton();
game.addChild(playButton);
// Position the button in the center of the screen
playButton.x = 2048 / 2;
playButton.y = 2732 / 2;
// Make the button appear with animation
playButton.appear();
// Function to show character selection screen
function showCharacterSelection() {
if (showingCharacterSelection) {
return;
}
showingCharacterSelection = true;
// Make play button disappear
tween(playButton, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove play button from display
game.removeChild(playButton);
// Create character options
boyCharacter = new Character();
boyCharacter.initialize("boy");
game.addChild(boyCharacter);
boyCharacter.x = 2048 / 3;
boyCharacter.y = 2732 / 2;
girlCharacter = new Character();
girlCharacter.initialize("girl");
game.addChild(girlCharacter);
girlCharacter.x = 2048 * 2 / 3;
girlCharacter.y = 2732 / 2;
// Make characters appear with animation
boyCharacter.appear();
girlCharacter.appear();
}
});
}
// Function called when a character is selected
function characterSelected(characterType) {
selectedCharacter = characterType;
console.log("Selected character: " + characterType);
// Make the non-selected character sad and disappear
var nonSelectedCharacter = characterType === "boy" ? girlCharacter : boyCharacter;
var selectedCharacterObj = characterType === "boy" ? boyCharacter : girlCharacter;
// Make selected character happy
if (selectedCharacterObj.facialContainer.children.length >= 3) {
var mouth = selectedCharacterObj.facialContainer.children[2];
// Make mouth bigger and smile
tween(mouth, {
scaleX: 1.5,
scaleY: 1.5,
y: -55
}, {
duration: 300,
easing: tween.elasticOut
});
}
// Make non-selected character sad
if (nonSelectedCharacter.facialContainer.children.length >= 3) {
var sadMouth = nonSelectedCharacter.facialContainer.children[2];
// Make mouth smaller and frown
tween(sadMouth, {
scaleX: 0.8,
scaleY: -1.2,
y: -50
}, {
duration: 300,
easing: tween.easeOut
});
}
// Fade out and shrink non-selected character
tween(nonSelectedCharacter, {
alpha: 0,
scaleX: 0,
scaleY: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(nonSelectedCharacter);
}
});
// Jump and move the selected character to center
LK.setTimeout(function () {
// Jump up first
tween(selectedCharacterObj, {
y: selectedCharacterObj.y - 100
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move to center while in air
tween(selectedCharacterObj, {
x: 2048 / 2
}, {
duration: 300,
easing: tween.linear,
onFinish: function onFinish() {
// Land with bounce
tween(selectedCharacterObj, {
y: 2732 / 2,
scaleY: 0.7,
scaleX: 1.3
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
// Bounce back to normal
tween(selectedCharacterObj, {
scaleY: 1.1,
scaleX: 0.9
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to normal scale
tween(selectedCharacterObj, {
scaleY: 1.0,
scaleX: 1.0
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
// Celebrate with a spin
tween(selectedCharacterObj.headContainer, {
rotation: Math.PI * 2
}, {
duration: 800,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Reset rotation
selectedCharacterObj.headContainer.rotation = 0;
// Add start game button
var startGameBtn = new StartGameButton();
game.addChild(startGameBtn);
startGameBtn.x = 2048 / 2;
startGameBtn.y = 2732 / 2 + 350; // Position below character
startGameBtn.appear();
}
});
}
});
}
});
}
});
}
});
}
});
}, 300);
}
// Function to start the game
function startGame() {
console.log("Starting game with character: " + selectedCharacter);
// Store the current background color
var originalBackgroundColor = game.backgroundColor;
// Create a black overlay for the screen
var blackOverlay = new Container();
var blackBg = blackOverlay.attachAsset('buttonShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: 4096,
// Make it twice the screen width to ensure full coverage
height: 5464,
// Make it twice the screen height to ensure full coverage
tint: 0x000000,
// Pure black
alpha: 0
});
game.addChild(blackOverlay);
blackOverlay.x = 2048 / 2;
blackOverlay.y = 2732 / 2;
// Fade to black
tween(blackBg, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Wait for 3 seconds with black screen
LK.setTimeout(function () {
// Create ocean scene
var ocean = new Ocean();
ocean.x = 2048 / 2;
ocean.y = 2732 / 2;
game.addChild(ocean);
// Create shore at the far side
var shore = new Shore();
shore.x = 2048 / 2;
shore.y = 3000; // Position below the screen
game.addChild(shore);
// Create raft and position it in the center
var raft = new Raft();
raft.x = 2048 / 2;
raft.y = 2732 / 2;
game.addChild(raft);
// Add the selected character to the raft
var selectedCharacterObj = selectedCharacter === "boy" ? boyCharacter : girlCharacter;
// Move character to raft
raft.addChild(selectedCharacterObj);
selectedCharacterObj.x = 0;
selectedCharacterObj.y = -80; // Position on raft
// Remove settings button and any remaining UI
if (settingsButton && settingsButton.parent) {
game.removeChild(settingsButton);
}
// Create start game button to trigger swimming animation
var startGameBtn = new StartGameButton();
game.addChild(startGameBtn);
startGameBtn.x = 2048 / 2;
startGameBtn.y = 2732 - 200; // Position near bottom
startGameBtn.appear();
// Fade the black screen out
tween(blackBg, {
alpha: 0
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
// Remove the black overlay
game.removeChild(blackOverlay);
// Set game background to sky blue
game.setBackgroundColor(0x87CEEB);
}
});
}, 3000);
}
});
}
// Rainbow effect for the background
var rainbowColors = [0x66CC99, 0x66CCFF, 0xCC99FF, 0xFF99CC, 0xFFCC66, 0x99FF99];
var currentColorIndex = 0;
// A function to cycle through background colors
function cycleBackgroundColor() {
currentColorIndex = (currentColorIndex + 1) % rainbowColors.length;
// Animate the color change
var targetColor = rainbowColors[currentColorIndex];
tween(game, {
backgroundColor: targetColor
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Schedule the next color change
LK.setTimeout(cycleBackgroundColor, 4000);
}
});
}
// Start the background color animation after a delay
LK.setTimeout(cycleBackgroundColor, 4000);