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]();
}
}
};