Code edit (1 edits merged)
Please save this source code
User prompt
Toca FaceTime Friends
Initial prompt
Toca FaceTime (2014). Let’s FaceTime Lucas 🦁, or ruby 🐰, or Lilly 🐱, or brody 🐻, or baby 🦁, or the powerpuff girls. Tap the green call button to make the iPad come to life, and then tap on the red done button to make the iPad say goodbye.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Character = Container.expand(function (name, color) {
var self = Container.call(this);
var face = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
var leftEye = self.attachAsset('eyes', {
anchorX: 0.5,
anchorY: 0.5,
x: -80,
y: -50
});
var rightEye = self.attachAsset('eyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 80,
y: -50
});
var mouth = self.attachAsset('mouth', {
anchorX: 0.5,
anchorY: 0.5,
y: 80
});
self.name = name;
self.animationState = 'idle';
self.lastAnimation = 0;
self.wave = function () {
tween(self, {
rotation: 0.3
}, {
duration: 300,
easing: tween.easeInOut
});
tween(self, {
rotation: -0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0.3
}, {
duration: 300,
easing: tween.easeInOut
});
tween(self, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
LK.getSound('wave').play();
};
self.blink = function () {
tween(leftEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeInOut
});
tween(rightEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeInOut
});
tween(leftEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeInOut
});
tween(rightEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeInOut
});
};
self.smile = function () {
tween(mouth, {
scaleX: 1.5,
scaleY: 0.7
}, {
duration: 500,
easing: tween.easeInOut
});
tween(mouth, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut
});
LK.getSound('laugh').play();
};
self.update = function () {
if (LK.ticks - self.lastAnimation > 180) {
// 3 seconds at 60fps
var randomAction = Math.floor(Math.random() * 3);
if (randomAction === 0) {
self.blink();
} else if (randomAction === 1 && Math.random() > 0.7) {
self.smile();
}
self.lastAnimation = LK.ticks;
}
};
self.down = function (x, y, obj) {
var actions = ['wave', 'smile', 'blink'];
var randomAction = actions[Math.floor(Math.random() * actions.length)];
self[randomAction]();
};
return self;
});
var ContactCard = Container.expand(function (characterName, color) {
var self = Container.call(this);
var background = self.attachAsset('contactCard', {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(characterName, {
size: 60,
fill: 0x333333
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 0;
nameText.y = 0;
self.addChild(nameText);
self.characterName = characterName;
self.characterColor = color;
self.down = function (x, y, obj) {
startCall(self.characterName, self.characterColor);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
var gameState = 'contacts'; // 'contacts', 'calling', 'incall'
var currentCharacter = null;
var callTimer = 0;
var callDuration = 1800; // 30 seconds at 60fps
var characters = [{
name: 'Lucas',
color: 0x4169e1
}, {
name: 'Ruby',
color: 0xff69b4
}, {
name: 'Lilly',
color: 0x98fb98
}, {
name: 'Brody',
color: 0xffa500
}, {
name: 'Baby',
color: 0xffb6c1
}, {
name: 'Powerpuff Girl',
color: 0xff1493
}];
// Contact list interface
var contactsList = new Container();
game.addChild(contactsList);
var titleText = new Text2('FaceTime Friends', {
size: 120,
fill: 0x333333
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 200;
contactsList.addChild(titleText);
// Create contact cards
var contactCards = [];
for (var i = 0; i < characters.length; i++) {
var card = new ContactCard(characters[i].name, characters[i].color);
card.x = 2048 / 2;
card.y = 600 + i * 200;
contactsList.addChild(card);
contactCards.push(card);
}
// Call interface
var callInterface = new Container();
callInterface.visible = false;
game.addChild(callInterface);
var videoBackground = callInterface.attachAsset('videoFrame', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
var callButton = callInterface.attachAsset('callButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 250,
y: 2732 - 200
});
var hangupButton = callInterface.attachAsset('hangupButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 250,
y: 2732 - 200
});
var callingText = new Text2('Calling...', {
size: 80,
fill: 0xFFFFFF
});
callingText.anchor.set(0.5, 0.5);
callingText.x = 2048 / 2;
callingText.y = 300;
callInterface.addChild(callingText);
function startCall(characterName, characterColor) {
gameState = 'calling';
contactsList.visible = false;
callInterface.visible = true;
callTimer = 0;
callingText.setText('Calling ' + characterName + '...');
callingText.visible = true;
LK.getSound('ring').play();
LK.setTimeout(function () {
answerCall(characterName, characterColor);
}, 2000);
}
function answerCall(characterName, characterColor) {
gameState = 'incall';
callingText.visible = false;
currentCharacter = new Character(characterName, characterColor);
currentCharacter.x = 2048 / 2;
currentCharacter.y = 2732 / 2;
callInterface.addChild(currentCharacter);
LK.getSound('hello').play();
currentCharacter.wave();
callTimer = 0;
}
function endCall() {
if (currentCharacter) {
currentCharacter.wave();
LK.getSound('goodbye').play();
LK.setTimeout(function () {
currentCharacter.destroy();
currentCharacter = null;
gameState = 'contacts';
contactsList.visible = true;
callInterface.visible = false;
callTimer = 0;
}, 1500);
}
}
callButton.down = function (x, y, obj) {
if (gameState === 'calling') {
// Skip to answer immediately
answerCall(callingText.text.replace('Calling ', '').replace('...', ''), 0x87ceeb);
}
};
hangupButton.down = function (x, y, obj) {
if (gameState === 'incall' || gameState === 'calling') {
endCall();
}
};
game.update = function () {
if (gameState === 'incall') {
callTimer++;
// Auto end call after duration
if (callTimer >= callDuration) {
endCall();
}
// Random character actions during call
if (currentCharacter && callTimer % 300 === 0) {
// Every 5 seconds
var actions = ['wave', 'smile'];
var randomAction = actions[Math.floor(Math.random() * actions.length)];
currentCharacter[randomAction]();
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Character = Container.expand(function (name, color) {
var self = Container.call(this);
var face = self.attachAsset('character', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
var leftEye = self.attachAsset('eyes', {
anchorX: 0.5,
anchorY: 0.5,
x: -80,
y: -50
});
var rightEye = self.attachAsset('eyes', {
anchorX: 0.5,
anchorY: 0.5,
x: 80,
y: -50
});
var mouth = self.attachAsset('mouth', {
anchorX: 0.5,
anchorY: 0.5,
y: 80
});
self.name = name;
self.animationState = 'idle';
self.lastAnimation = 0;
self.wave = function () {
tween(self, {
rotation: 0.3
}, {
duration: 300,
easing: tween.easeInOut
});
tween(self, {
rotation: -0.3
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0.3
}, {
duration: 300,
easing: tween.easeInOut
});
tween(self, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
LK.getSound('wave').play();
};
self.blink = function () {
tween(leftEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeInOut
});
tween(rightEye, {
scaleY: 0.1
}, {
duration: 100,
easing: tween.easeInOut
});
tween(leftEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeInOut
});
tween(rightEye, {
scaleY: 1
}, {
duration: 100,
easing: tween.easeInOut
});
};
self.smile = function () {
tween(mouth, {
scaleX: 1.5,
scaleY: 0.7
}, {
duration: 500,
easing: tween.easeInOut
});
tween(mouth, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut
});
LK.getSound('laugh').play();
};
self.update = function () {
if (LK.ticks - self.lastAnimation > 180) {
// 3 seconds at 60fps
var randomAction = Math.floor(Math.random() * 3);
if (randomAction === 0) {
self.blink();
} else if (randomAction === 1 && Math.random() > 0.7) {
self.smile();
}
self.lastAnimation = LK.ticks;
}
};
self.down = function (x, y, obj) {
var actions = ['wave', 'smile', 'blink'];
var randomAction = actions[Math.floor(Math.random() * actions.length)];
self[randomAction]();
};
return self;
});
var ContactCard = Container.expand(function (characterName, color) {
var self = Container.call(this);
var background = self.attachAsset('contactCard', {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(characterName, {
size: 60,
fill: 0x333333
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 0;
nameText.y = 0;
self.addChild(nameText);
self.characterName = characterName;
self.characterColor = color;
self.down = function (x, y, obj) {
startCall(self.characterName, self.characterColor);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xffffff
});
/****
* Game Code
****/
var gameState = 'contacts'; // 'contacts', 'calling', 'incall'
var currentCharacter = null;
var callTimer = 0;
var callDuration = 1800; // 30 seconds at 60fps
var characters = [{
name: 'Lucas',
color: 0x4169e1
}, {
name: 'Ruby',
color: 0xff69b4
}, {
name: 'Lilly',
color: 0x98fb98
}, {
name: 'Brody',
color: 0xffa500
}, {
name: 'Baby',
color: 0xffb6c1
}, {
name: 'Powerpuff Girl',
color: 0xff1493
}];
// Contact list interface
var contactsList = new Container();
game.addChild(contactsList);
var titleText = new Text2('FaceTime Friends', {
size: 120,
fill: 0x333333
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 200;
contactsList.addChild(titleText);
// Create contact cards
var contactCards = [];
for (var i = 0; i < characters.length; i++) {
var card = new ContactCard(characters[i].name, characters[i].color);
card.x = 2048 / 2;
card.y = 600 + i * 200;
contactsList.addChild(card);
contactCards.push(card);
}
// Call interface
var callInterface = new Container();
callInterface.visible = false;
game.addChild(callInterface);
var videoBackground = callInterface.attachAsset('videoFrame', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
var callButton = callInterface.attachAsset('callButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 250,
y: 2732 - 200
});
var hangupButton = callInterface.attachAsset('hangupButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 250,
y: 2732 - 200
});
var callingText = new Text2('Calling...', {
size: 80,
fill: 0xFFFFFF
});
callingText.anchor.set(0.5, 0.5);
callingText.x = 2048 / 2;
callingText.y = 300;
callInterface.addChild(callingText);
function startCall(characterName, characterColor) {
gameState = 'calling';
contactsList.visible = false;
callInterface.visible = true;
callTimer = 0;
callingText.setText('Calling ' + characterName + '...');
callingText.visible = true;
LK.getSound('ring').play();
LK.setTimeout(function () {
answerCall(characterName, characterColor);
}, 2000);
}
function answerCall(characterName, characterColor) {
gameState = 'incall';
callingText.visible = false;
currentCharacter = new Character(characterName, characterColor);
currentCharacter.x = 2048 / 2;
currentCharacter.y = 2732 / 2;
callInterface.addChild(currentCharacter);
LK.getSound('hello').play();
currentCharacter.wave();
callTimer = 0;
}
function endCall() {
if (currentCharacter) {
currentCharacter.wave();
LK.getSound('goodbye').play();
LK.setTimeout(function () {
currentCharacter.destroy();
currentCharacter = null;
gameState = 'contacts';
contactsList.visible = true;
callInterface.visible = false;
callTimer = 0;
}, 1500);
}
}
callButton.down = function (x, y, obj) {
if (gameState === 'calling') {
// Skip to answer immediately
answerCall(callingText.text.replace('Calling ', '').replace('...', ''), 0x87ceeb);
}
};
hangupButton.down = function (x, y, obj) {
if (gameState === 'incall' || gameState === 'calling') {
endCall();
}
};
game.update = function () {
if (gameState === 'incall') {
callTimer++;
// Auto end call after duration
if (callTimer >= callDuration) {
endCall();
}
// Random character actions during call
if (currentCharacter && callTimer % 300 === 0) {
// Every 5 seconds
var actions = ['wave', 'smile'];
var randomAction = actions[Math.floor(Math.random() * actions.length)];
currentCharacter[randomAction]();
}
}
};