User prompt
Sağa ve Sola harket ederken kolları omuzlardan ve dirseklerden iki yana her kolu kendi tarafına yukarı kaldır. Hangi yöne gidiyorsa o kolu yukarı kaldır.
User prompt
Sağa ve Sola harket ederken kolları omuzlardan ve dirseklerden iki yana her kolu kendi tarafına aç.
User prompt
Sağa ve Sola harket ederken kolları omuzlardan ve dirseklerden iki yana aç.
User prompt
Sola harket ederken kolları omuzlardan iki yana aç.
User prompt
Sola hareket ederken kolları iki yana aç
User prompt
Sola pozunda kolları aç
User prompt
Sola saga pozlarda kollari iki yana ac ve kapat ik.
User prompt
Zıplamada sol alt bacak bağlı değil
User prompt
Zıplamada sol alt bacak ik iyileştir
User prompt
Zıplamada sol ayak aşağıda olmalı.
User prompt
Varsayılan pozisyon zıplama olsun
User prompt
Ilk açılışta jump pozisyonunda kal.
User prompt
Oturmada boyun ik ye gore hareket etsin.
User prompt
Boynu vücuda bağla ik.
User prompt
Oturmada dizler zemine deyecek şekilde kalçayı aşağıya çek.
User prompt
Oturmada bacak hareketini değiştir. Bacaklar dizde birleşik olmalı. Ik ya göre davran.
User prompt
Zıplamada bacak hareketini değiştir. Bacaklar dizde birleşik olmalı. Ik ya göre davran.
User prompt
Arkaplan müziklerini kontrol et sürekli ve rastgele sırada çalsınlar.
User prompt
Dizlerdeki bağlantı sit poz da kopuyor
User prompt
Kalçaların gövdedeki bağlantı pozisyonu degısmesin
User prompt
Bacaklara rotate ayarı yap.
User prompt
Bacakları biraz kapat.
User prompt
Sağ ve sol Üst bacakları ve alt bacakları dizlerle birbirine bağla ve tüm pozlarda bağlı kalsın.
User prompt
Bacaklar aşağıda olsun
User prompt
Üst bacakları ve alt bacakları dizlerle bağla ve tüm pozlarda bağlı kalsın.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Drum class
var Drum = Container.expand(function () {
var self = Container.call(this);
self.drumType = 'none'; // 'large', 'left', 'right', 'sit', 'stand'
self.action = null; // function to call on tap
// Set up drum asset
self.setDrum = function (type) {
self.drumType = type;
var assetId = type === 'large' ? 'drum_large' : 'drum_medium';
var drum = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// (Drum label removed)
};
// Drum tap effect
self.flash = function () {
tween(self, {
scaleX: 1.18,
scaleY: 0.92
}, {
duration: 80,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 120
});
}
});
};
// Touch event
self.down = function (x, y, obj) {
self.flash();
// Play unique sound for each drum type
if (self.drumType === 'large') {
LK.getSound('drum_tap_center').play();
} else if (self.drumType === 'left') {
// Play with very long reverb effect
if (typeof reverb !== "undefined" && reverb.add) {
var leftSound = LK.getSound('drum_tap_left');
reverb.add(leftSound, {
reverbTime: 3.5
}); // simulate very long reverb (if plugin supports param)
leftSound.play();
} else {
LK.getSound('drum_tap_left').play();
}
} else if (self.drumType === 'right') {
// Play with very long reverb effect
if (typeof reverb !== "undefined" && reverb.add) {
var rightSound = LK.getSound('drum_tap_right');
reverb.add(rightSound, {
reverbTime: 3.5
}); // simulate very long reverb (if plugin supports param)
rightSound.play();
} else {
LK.getSound('drum_tap_right').play();
}
} else if (self.drumType === 'sit') {
var sitSound = LK.getSound('drum_tap_sit');
sitSound.play();
LK.setTimeout(function () {
sitSound.play();
}, 120);
} else if (self.drumType === 'stand') {
// Play the sound with 3 fast delay effects (echoes)
var base = LK.getSound('drum_tap_stand');
base.play();
LK.setTimeout(function () {
base.play();
}, 45);
LK.setTimeout(function () {
base.play();
}, 90);
} else {
// No fallback sound
}
if (self.action) self.action();
};
return self;
});
// Puppet class: articulated body with simple kinematics
var Puppet = Container.expand(function () {
var self = Container.call(this);
// --- Body part sizes (for positioning) ---
var headH = 120 * 1.5,
headW = 120 * 1.5;
var bodyH = 200 * 1.5,
bodyW = 80 * 1.5;
var upperArmH = 100 * 1.5,
upperArmW = 40 * 1.5;
var lowerArmH = 90 * 1.5,
lowerArmW = 32 * 1.5;
var upperLegH = 120 * 1.5,
upperLegW = 48 * 1.5;
var lowerLegH = 110 * 1.5,
lowerLegW = 40 * 1.5;
// --- Create body parts ---
// Head
var head = self.attachAsset('puppet_head', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Neck (between head and body, sized to match hip)
var neck = self.attachAsset('puppet_neck', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
// match hip scale
scaleY: 1.5
});
// Shoulders (left and right)
var lShoulder = self.attachAsset('puppet_shoulder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
var rShoulder = self.attachAsset('puppet_shoulder', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Body
var body = self.attachAsset('puppet_body', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Dual hips (left and right)
var lHip = self.attachAsset('puppet_hip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
var rHip = self.attachAsset('puppet_hip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Left upper arm
var lUpperArm = self.attachAsset('puppet_upperarm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Left elbow
var lElbow = self.attachAsset('puppet_elbow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Left lower arm
var lLowerArm = self.attachAsset('puppet_lowerarm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Right upper arm
var rUpperArm = self.attachAsset('puppet_upperarm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Right elbow
var rElbow = self.attachAsset('puppet_elbow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Right lower arm
var rLowerArm = self.attachAsset('puppet_lowerarm', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Left upper leg
var lUpperLeg = self.attachAsset('puppet_upperleg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Left knee
var lKnee = self.attachAsset('puppet_knee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Left lower leg
var lLowerLeg = self.attachAsset('puppet_lowerleg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Right upper leg
var rUpperLeg = self.attachAsset('puppet_upperleg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// Right knee
var rKnee = self.attachAsset('puppet_knee', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Right lower leg
var rLowerLeg = self.attachAsset('puppet_lowerleg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
// --- Initial pose state ---
self.state = {
vx: 0,
// horizontal velocity
vy: 0,
// vertical velocity
grounded: false,
pose: 'stand',
// 'stand', 'sit', 'jump'
headAngle: 0,
// radians, for "pull head" actions
x: 0,
// world position
y: 0,
// --- Ava: Leg rotation controls ---
lUpperLegRotation: 0,
// additional rotation for left upper leg
rUpperLegRotation: 0,
// additional rotation for right upper leg
lLowerLegRotation: 0,
// additional rotation for left lower leg
rLowerLegRotation: 0 // additional rotation for right lower leg
};
// --- Positioning offsets (relative to puppet center) ---
function updateBodyParts() {
// Head
head.x = 0;
// Move head higher above the neck for a more natural look (was +10, now -30 for more separation)
head.y = -bodyH / 2 - headH / 2 - 30;
head.rotation = self.state.headAngle;
// Neck: place between head and body, sized to match hip
// Use hip asset size for neck size/placement
var hipH = 44 * 1.5; // puppet_hip height * scale
var neckH = hipH;
neck.x = 0;
neck.y = -bodyH / 2 - neckH / 2 + 38; // 38 is a small offset to visually connect neck, adjust as needed
neck.rotation = 0;
// Body
body.x = 0;
body.y = -bodyH / 2;
// Arms
var armY = -bodyH / 2 + 30;
var armX = bodyW / 2 + upperArmW / 2 - 10;
// Shoulder positions
var lShoulderX = -armX;
var lShoulderY = armY;
var rShoulderX = armX;
var rShoulderY = armY;
// Place shoulder assets at shoulder positions
lShoulder.x = lShoulderX;
lShoulder.y = lShoulderY;
rShoulder.x = rShoulderX;
rShoulder.y = rShoulderY;
// --- Improved arm kinematics ---
// Default arm pose angles (arms down, but slightly outward)
var armAbduction = 0.32; // outward angle in radians (~18deg)
var lUpperArmAngle = -armAbduction; // left arm slightly outward
var rUpperArmAngle = armAbduction; // right arm slightly outward
var lLowerArmAngle = 0; // straight
var rLowerArmAngle = 0; // straight
// Pose-based arm animation
if (self.state.pose === 'sit') {
lUpperArmAngle = -1.25 - armAbduction;
rUpperArmAngle = 1.25 + armAbduction;
lLowerArmAngle = 1.5;
rLowerArmAngle = -1.5;
} else if (self.state.pose === 'jump') {
// In jump pose, upper arms are raised up and slightly outward
lUpperArmAngle = -1.6 - armAbduction; // sol üst kol yukarı ve dışa
rUpperArmAngle = 1.6 + armAbduction; // sağ üst kol yukarı ve dışa
lLowerArmAngle = 2.0;
rLowerArmAngle = -2.0;
// --- Maintain shoulder-elbow connection in jump pose ---
var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH;
var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH;
lElbow.x = lElbowX;
lElbow.y = lElbowY;
var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH;
var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH;
rElbow.x = rElbowX;
rElbow.y = rElbowY;
} else if (self.state.pose === 'stand') {
// Gentle swing based on horizontal velocity for more life
lUpperArmAngle += self.state.vx * 0.01;
rUpperArmAngle -= self.state.vx * 0.01;
lLowerArmAngle += Math.sin(Date.now() * 0.003) * 0.08;
rLowerArmAngle -= Math.sin(Date.now() * 0.003) * 0.08;
} else if (self.state.pose === 'left') {
// Open both arms to the left and right using IK
lUpperArmAngle = -Math.PI / 2; // left arm straight left
rUpperArmAngle = Math.PI / 2; // right arm straight right
lLowerArmAngle = 0;
rLowerArmAngle = 0;
// Place elbows at the end of upper arms
var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH;
var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH;
lElbow.x = lElbowX;
lElbow.y = lElbowY;
var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH;
var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH;
rElbow.x = rElbowX;
rElbow.y = rElbowY;
} else if (self.state.pose === 'right') {
// Open both arms to the left and right using IK
lUpperArmAngle = -Math.PI / 2; // left arm straight left
rUpperArmAngle = Math.PI / 2; // right arm straight right
lLowerArmAngle = 0;
rLowerArmAngle = 0;
// Place elbows at the end of upper arms
var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH;
var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH;
lElbow.x = lElbowX;
lElbow.y = lElbowY;
var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH;
var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH;
rElbow.x = rElbowX;
rElbow.y = rElbowY;
}
// Left upper arm: connect from shoulder to elbow
lUpperArm.x = lShoulderX;
lUpperArm.y = lShoulderY;
lUpperArm.rotation = Math.atan2(
// target: elbow - shoulder
lElbow.y - lShoulderY, lElbow.x - lShoulderX) - Math.PI / 2;
var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH;
var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH;
lElbow.x = lElbowX;
lElbow.y = lElbowY;
// Left lower arm
lLowerArm.x = lElbowX;
lLowerArm.y = lElbowY;
lLowerArm.rotation = lLowerArmAngle;
// Right upper arm: connect from shoulder to elbow
rUpperArm.x = rShoulderX;
rUpperArm.y = rShoulderY;
rUpperArm.rotation = Math.atan2(
// target: elbow - shoulder
rElbow.y - rShoulderY, rElbow.x - rShoulderX) - Math.PI / 2;
var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH;
var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH;
rElbow.x = rElbowX;
rElbow.y = rElbowY;
// Right lower arm
rLowerArm.x = rElbowX;
rLowerArm.y = rElbowY;
rLowerArm.rotation = rLowerArmAngle;
// --- Improved leg kinematics ---
var legY = bodyH / 2 - 10;
var legX = bodyW / 2 - 18;
// Hip positions (left and right)
var lHipX = -legX;
var lHipY = legY;
var rHipX = legX;
var rHipY = legY;
lHip.x = lHipX;
lHip.y = lHipY;
rHip.x = rHipX;
rHip.y = rHipY;
// Default leg pose (narrower stance)
var legAbduction = 0.28; // outward angle in radians (~16deg), reduced for a more closed stance
var lUpperLegAngle = legAbduction + (self.state.lUpperLegRotation || 0);
var rUpperLegAngle = -legAbduction + (self.state.rUpperLegRotation || 0);
var lLowerLegAngle = 0.25 + (self.state.lLowerLegRotation || 0);
var rLowerLegAngle = -0.25 + (self.state.rLowerLegRotation || 0);
// Pose-based leg animation
if (self.state.pose === 'sit') {
lUpperLegAngle = 1.35 + (self.state.lUpperLegRotation || 0);
rUpperLegAngle = 1.35 + (self.state.rUpperLegRotation || 0);
lLowerLegAngle = lUpperLegAngle - Math.PI / 2 + 0.15 + (self.state.lLowerLegRotation || 0);
rLowerLegAngle = rUpperLegAngle - Math.PI / 2 - 0.15 + (self.state.rLowerLegRotation || 0);
} else if (self.state.pose === 'jump') {
// In jump pose, upper legs are raised up and slightly outward
lUpperLegAngle = -0.9 - legAbduction + (self.state.lUpperLegRotation || 0); // sol üst bacak yukarı ve dışa
rUpperLegAngle = 0.9 + legAbduction + (self.state.rUpperLegRotation || 0); // sağ üst bacak yukarı ve dışa
lLowerLegAngle = lUpperLegAngle + 2.1 + (self.state.lLowerLegRotation || 0);
rLowerLegAngle = rUpperLegAngle + 2.1 + (self.state.rLowerLegRotation || 0);
} else if (self.state.pose === 'stand') {
// Gentle walk cycle if moving
var walk = Math.abs(self.state.vx) > 0.5 ? Math.sin(Date.now() * 0.008) * 0.25 : 0;
lUpperLegAngle += walk;
rUpperLegAngle -= walk;
lLowerLegAngle += walk * 0.5;
rLowerLegAngle -= walk * 0.5;
}
// Left upper leg: connect from right hip to left knee (swapped knees)
lUpperLeg.x = rHip.x;
lUpperLeg.y = rHip.y;
// Calculate left knee position (swapped)
var lKneeX = lUpperLeg.x + Math.sin(lUpperLegAngle) * upperLegH;
var lKneeY = lUpperLeg.y + Math.cos(lUpperLegAngle) * upperLegH;
lKnee.x = lKneeX;
lKnee.y = lKneeY;
lUpperLeg.rotation = Math.atan2(lKnee.y - lUpperLeg.y, lKnee.x - lUpperLeg.x) - Math.PI / 2;
// Attach left lower leg at left knee, keep it connected
lLowerLeg.x = lKneeX;
lLowerLeg.y = lKneeY;
lLowerLeg.rotation = lLowerLegAngle;
// Right upper leg: connect from left hip to right knee (swapped knees)
rUpperLeg.x = lHip.x;
rUpperLeg.y = lHip.y;
// Calculate right knee position (swapped)
var rKneeX = rUpperLeg.x + Math.sin(rUpperLegAngle) * upperLegH;
var rKneeY = rUpperLeg.y + Math.cos(rUpperLegAngle) * upperLegH;
rKnee.x = rKneeX;
rKnee.y = rKneeY;
rUpperLeg.rotation = Math.atan2(rKnee.y - rUpperLeg.y, rKnee.x - rUpperLeg.x) - Math.PI / 2;
// Attach right lower leg at right knee, keep it connected
rLowerLeg.x = rKneeX;
rLowerLeg.y = rKneeY;
rLowerLeg.rotation = rLowerLegAngle;
// Pose adjustments
if (self.state.pose === 'sit') {
// Sitting: both thighs forward, knees bent, knees together, shins down, using IK
// Both upper legs start from hips and point forward, knees together in the middle
// Calculate a common knee position between the two hips for "knees together"
var hipsMidX = (lHip.x + rHip.x) / 2;
var hipsMidY = (lHip.y + rHip.y) / 2;
// Angle for thighs: forward (down), slightly inward
var thighAngle = 1.32;
// Distance from hip to knee
var kneeOffsetX = Math.sin(thighAngle) * upperLegH;
var kneeOffsetY = Math.cos(thighAngle) * upperLegH;
// Both knees at the same position (knees together)
var kneeX = hipsMidX + kneeOffsetX;
var kneeY = hipsMidY + kneeOffsetY;
// Left upper leg: right hip to common knee
lUpperLeg.x = rHip.x;
lUpperLeg.y = rHip.y;
lUpperLeg.rotation = Math.atan2(kneeY - lUpperLeg.y, kneeX - lUpperLeg.x) - Math.PI / 2;
lKnee.x = kneeX;
lKnee.y = kneeY;
// Left lower leg: from knee, bent downward
lLowerLeg.x = kneeX;
lLowerLeg.y = kneeY;
lLowerLeg.rotation = lUpperLeg.rotation - Math.PI / 2 + 0.18;
// Right upper leg: left hip to common knee
rUpperLeg.x = lHip.x;
rUpperLeg.y = lHip.y;
rUpperLeg.rotation = Math.atan2(kneeY - rUpperLeg.y, kneeX - rUpperLeg.x) - Math.PI / 2;
rKnee.x = kneeX;
rKnee.y = kneeY;
// Right lower leg: from knee, bent downward
rLowerLeg.x = kneeX;
rLowerLeg.y = kneeY;
rLowerLeg.rotation = rUpperLeg.rotation - Math.PI / 2 - 0.18;
body.rotation = -0.18;
} else if (self.state.pose === 'jump') {
// Jump: both legs bend at the knees, knees close together, feet up, using IK
// --- Left leg (right hip to left knee) ---
lUpperLeg.x = rHip.x;
lUpperLeg.y = rHip.y;
// Both upper legs point downward but slightly inward for knees-together
lUpperLeg.rotation = -0.45 - legAbduction; // up and slightly inward
var lKneeX = lUpperLeg.x + Math.sin(lUpperLeg.rotation) * upperLegH;
var lKneeY = lUpperLeg.y + Math.cos(lUpperLeg.rotation) * upperLegH;
lKnee.x = lKneeX;
lKnee.y = lKneeY;
// Lower leg bends sharply upward, keeping connected at knee
lLowerLeg.x = lKnee.x;
lLowerLeg.y = lKnee.y;
lLowerLeg.rotation = lUpperLeg.rotation + 2.5; // sharp bend
// --- Right leg (left hip to right knee) ---
rUpperLeg.x = lHip.x;
rUpperLeg.y = lHip.y;
rUpperLeg.rotation = 0.45 + legAbduction; // up and slightly inward
var rKneeX = rUpperLeg.x + Math.sin(rUpperLeg.rotation) * upperLegH;
var rKneeY = rUpperLeg.y + Math.cos(rUpperLeg.rotation) * upperLegH;
rKnee.x = rKneeX;
rKnee.y = rKneeY;
rLowerLeg.x = rKneeX;
rLowerLeg.y = rKneeY;
rLowerLeg.rotation = rUpperLeg.rotation + 2.5; // sharp bend
// Elbows more bent in jump
lLowerArm.x = lElbow.x;
lLowerArm.y = lElbow.y;
lLowerArm.rotation = 2.0;
rLowerArm.x = rElbow.x;
rLowerArm.y = rElbow.y;
rLowerArm.rotation = -2.0;
body.rotation = 0.12;
} else {
body.rotation = 0;
}
}
// --- Public puppet actions ---
self.pullHeadLeft = function () {
// Pull head left, add leftward velocity
if (self.state.grounded) {
self.state.vx -= 12;
self.state.headAngle = -0.5;
tween(self.state, {
headAngle: 0
}, {
duration: 400,
easing: tween.easeOut
});
}
};
self.pullHeadRight = function () {
if (self.state.grounded) {
self.state.vx += 12;
self.state.headAngle = 0.5;
tween(self.state, {
headAngle: 0
}, {
duration: 400,
easing: tween.easeOut
});
}
};
self.jump = function () {
if (self.state.grounded) {
self.state.vy = -48; // Increased jump velocity for higher jump
self.state.grounded = false;
self.state.pose = 'jump';
tween(self.state, {}, {
duration: 0,
onFinish: function onFinish() {
// After 400ms, return to stand pose
LK.setTimeout(function () {
self.state.pose = 'stand';
}, 400);
}
});
}
};
self.sit = function () {
if (self.state.grounded && self.state.pose !== 'sit') {
self.state.pose = 'sit';
// After 600ms, stand up automatically
LK.setTimeout(function () {
self.stand();
}, 600);
}
};
self.stand = function () {
if (self.state.grounded && self.state.pose !== 'stand') {
self.state.pose = 'stand';
}
};
// --- Physics update ---
self.update = function () {
// Gravity
if (!self.state.grounded) {
self.state.vy += 2.2; // gravity
if (self.state.vy > 40) self.state.vy = 40;
}
// Friction
if (self.state.grounded) {
self.state.vx *= 0.82;
if (Math.abs(self.state.vx) < 0.5) self.state.vx = 0;
} else {
self.state.vx *= 0.98;
}
// Move
self.state.x += self.state.vx;
self.state.y += self.state.vy;
// Clamp to world bounds
if (self.state.x < 80) self.state.x = 80;
if (self.state.x > 2048 - 80) self.state.x = 2048 - 80;
// --- Ava: Adjust puppet Y so feet are above ground visually ---
// The puppet's feet are at y + (bodyH/2) + upperLegH + lowerLegH - 10 - 10
// ground.y = 2732 - 80, ground height = 80
// So, puppet.y + (bodyH/2) + upperLegH + lowerLegH - 20 = 2732 - 80
// puppet.y = 2732 - 80 - (bodyH/2) - upperLegH - lowerLegH + 20
var puppetFeetOffset = bodyH / 2 + upperLegH + lowerLegH - 20;
var puppetGroundY = 2732 - 80 - puppetFeetOffset;
if (self.state.y > puppetGroundY) self.state.y = puppetGroundY; // above ground
// Ground collision
if (self.state.y >= puppetGroundY) {
self.state.y = puppetGroundY;
self.state.vy = 0;
self.state.grounded = true;
if (self.state.pose === 'jump') self.state.pose = 'stand';
} else {
self.state.grounded = false;
}
// Apply to container
self.x = self.state.x;
self.y = self.state.y;
updateBodyParts();
};
// --- Start position ---
self.state.x = 600; // Moved puppet further right (was 180)
// --- Ava: Set initial Y so feet are above ground visually ---
var puppetFeetOffset = bodyH / 2 + upperLegH + lowerLegH - 20;
self.state.y = 2732 - 80 - puppetFeetOffset;
updateBodyParts();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Define and initialize the reverb object before using it
// Win/lose sound
// Drum tap sound
// Finish sign
// Ground
// Drums
// Puppet body parts (shapes)
// --- World setup ---
// Apply reverb to all drum and win/lose sounds
// Ava: background asset
var reverb = {
add: function add(sound) {
// Dummy implementation: does nothing, but prevents errors
// In a real environment, this would apply a reverb effect to the sound
}
};
reverb.add(LK.getSound('drum_tap_center'));
reverb.add(LK.getSound('drum_tap_left'));
reverb.add(LK.getSound('drum_tap_right'));
reverb.add(LK.getSound('drum_tap_sit'));
reverb.add(LK.getSound('drum_tap_stand'));
reverb.add(LK.getSound('lose'));
reverb.add(LK.getSound('win'));
// --- Background music playlist (4 tracks, play in random order) ---
var musicTracks = [{
id: 'musicId',
volume: 0.1,
start: 0,
end: 1
}, {
id: 'musicId2',
volume: 0.1,
start: 0,
end: 1
}, {
id: 'musicId3',
volume: 0.1,
start: 0,
end: 1
}, {
id: 'musicId4',
volume: 0.1,
start: 0,
end: 1
}];
// Shuffle helper (Fisher-Yates)
function shuffleArray(arr) {
for (var i = arr.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// Maintain a shuffled playlist order
var shuffledMusicOrder = [];
function reshuffleMusicOrder() {
shuffledMusicOrder = [];
for (var i = 0; i < musicTracks.length; ++i) shuffledMusicOrder.push(i);
shuffleArray(shuffledMusicOrder);
}
reshuffleMusicOrder();
var currentMusicOrderIndex = 0;
// Play the next music track in the shuffled order, and keep playing forever
function playNextMusic() {
// If we've played all, reshuffle for a new random order
if (currentMusicOrderIndex >= shuffledMusicOrder.length) {
reshuffleMusicOrder();
currentMusicOrderIndex = 0;
}
var trackIndex = shuffledMusicOrder[currentMusicOrderIndex];
var track = musicTracks[trackIndex];
// Play music and set up onFinish to play the next one
LK.playMusic(track.id, {
loop: false,
volume: track.volume,
start: track.start,
end: track.end,
onFinish: function onFinish() {
currentMusicOrderIndex++;
playNextMusic();
}
});
}
playNextMusic();
game.setBackgroundColor(0x000000);
// --- Background ---
// Ava: Add background image behind all elements
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 1,
scaleY: 1
});
game.addChild(background);
// Ground
var ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground.x = 0;
ground.y = 2732 - 80;
game.addChild(ground);
// Finish sign
var finishSign = LK.getAsset('finish_sign', {
anchorX: 0.5,
anchorY: 1,
scaleX: 3,
scaleY: 6 // 2x as tall as before
});
finishSign.x = 2048 - 120;
finishSign.y = 2732 - 80;
game.addChild(finishSign);
// Finish text removed
// --- Puppet ---
var puppet = new Puppet();
game.addChild(puppet);
// --- Drums ---
var drums = [];
// Drum positions (relative to center)
// Move drums higher: set drumCenterY above puppet's head
var drumCenterX = 2048 / 2,
drumCenterY = 900; // was 2732 / 2 + 220, now much higher (puppet head is around y=~1200)
var drumRadius = 220 * 3;
var angleList = [{
type: 'left',
angle: -Math.PI / 2 - 0.7
}, {
type: 'right',
angle: -Math.PI / 2 + 0.7
}, {
type: 'sit',
angle: Math.PI / 2 + 0.7
}, {
type: 'stand',
angle: Math.PI / 2 - 0.7
}];
// --- Drum action pool ---
// Each drum will have all actions, only their order will be shuffled
// Ava: Increase the number of right movement actions (pullHeadRight) in the action pool
var puppetActions = [function () {
puppet.pullHeadLeft();
}, function () {
puppet.pullHeadRight();
}, function () {
puppet.pullHeadRight();
}, function () {
puppet.jump();
}, function () {
puppet.sit();
}, function () {
puppet.stand();
}];
// Large center drum (fixed action sequence)
var drumJump = new Drum();
drumJump.setDrum('large');
drumJump.x = drumCenterX;
drumJump.y = drumCenterY;
// Assign a fixed sequence of all 5 actions, and cycle through them
drumJump._actionSequence = puppetActions.slice();
drumJump._actionIndex = 0;
drumJump.action = function () {
drumJump._actionSequence[drumJump._actionIndex]();
drumJump._actionIndex = (drumJump._actionIndex + 1) % drumJump._actionSequence.length;
};
game.addChild(drumJump);
drums.push(drumJump);
// Four medium drums
for (var i = 0; i < angleList.length; ++i) {
var d = new Drum();
d.setDrum(angleList[i].type);
d.x = drumCenterX + Math.cos(angleList[i].angle) * drumRadius;
d.y = drumCenterY + Math.sin(angleList[i].angle) * drumRadius;
// Each drum gets a fixed sequence of all 5 actions, and cycles through them
d._actionSequence = puppetActions.slice();
d._actionIndex = 0;
d.action = function (drum) {
return function () {
drum._actionSequence[drum._actionIndex]();
drum._actionIndex = (drum._actionIndex + 1) % drum._actionSequence.length;
};
}(d);
game.addChild(d);
drums.push(d);
}
// --- Timer ---
var timeLeft = 60;
function formatTimeDigital(secs) {
var m = Math.floor(secs / 60);
var s = secs % 60;
var mm = m < 10 ? "0" + m : "" + m;
var ss = s < 10 ? "0" + s : "" + s;
return mm + ":" + ss;
}
var timerText = new Text2(formatTimeDigital(60), {
size: 120,
fill: '#ffffff'
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
// --- Score/Win state ---
var gameEnded = false;
// --- Timer logic ---
var timerInterval = LK.setInterval(function () {
if (gameEnded) return;
timeLeft -= 1;
if (timeLeft < 0) timeLeft = 0;
timerText.setText(formatTimeDigital(timeLeft));
if (timeLeft === 0 && !gameEnded) {
gameEnded = true;
LK.getSound('lose').play();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
}, 1000);
// --- Game update ---
game.update = function () {
if (gameEnded) return;
puppet.update();
// Win condition: puppet body collides with finish sign using intersects
if (!gameEnded && puppet.intersects(finishSign)) {
gameEnded = true;
LK.setScore(timeLeft); // Set score to remaining seconds
LK.getSound('win').play();
LK.effects.flashScreen(0x44c767, 800);
LK.showYouWin();
}
};
// --- Clean up on game over ---
game.onDestroy = function () {
LK.clearInterval(timerInterval);
};
// --- Prevent accidental tap on top left (menu) ---
/* No elements are placed at (0,0)-(100,100) */
// --- UX: drums are always on top ---
for (var i = 0; i < drums.length; ++i) {
game.addChild(drums[i]);
} ===================================================================
--- original.js
+++ change.js
@@ -324,8 +324,38 @@
lUpperArmAngle += self.state.vx * 0.01;
rUpperArmAngle -= self.state.vx * 0.01;
lLowerArmAngle += Math.sin(Date.now() * 0.003) * 0.08;
rLowerArmAngle -= Math.sin(Date.now() * 0.003) * 0.08;
+ } else if (self.state.pose === 'left') {
+ // Open both arms to the left and right using IK
+ lUpperArmAngle = -Math.PI / 2; // left arm straight left
+ rUpperArmAngle = Math.PI / 2; // right arm straight right
+ lLowerArmAngle = 0;
+ rLowerArmAngle = 0;
+ // Place elbows at the end of upper arms
+ var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH;
+ var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH;
+ lElbow.x = lElbowX;
+ lElbow.y = lElbowY;
+ var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH;
+ var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH;
+ rElbow.x = rElbowX;
+ rElbow.y = rElbowY;
+ } else if (self.state.pose === 'right') {
+ // Open both arms to the left and right using IK
+ lUpperArmAngle = -Math.PI / 2; // left arm straight left
+ rUpperArmAngle = Math.PI / 2; // right arm straight right
+ lLowerArmAngle = 0;
+ rLowerArmAngle = 0;
+ // Place elbows at the end of upper arms
+ var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH;
+ var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH;
+ lElbow.x = lElbowX;
+ lElbow.y = lElbowY;
+ var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH;
+ var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH;
+ rElbow.x = rElbowX;
+ rElbow.y = rElbowY;
}
// Left upper arm: connect from shoulder to elbow
lUpperArm.x = lShoulderX;
lUpperArm.y = lShoulderY;
@@ -608,18 +638,18 @@
/****
* Game Code
****/
-// Ava: background asset
-// Apply reverb to all drum and win/lose sounds
-// --- World setup ---
-// Puppet body parts (shapes)
-// Drums
-// Ground
-// Finish sign
-// Drum tap sound
-// Win/lose sound
// Define and initialize the reverb object before using it
+// Win/lose sound
+// Drum tap sound
+// Finish sign
+// Ground
+// Drums
+// Puppet body parts (shapes)
+// --- World setup ---
+// Apply reverb to all drum and win/lose sounds
+// Ava: background asset
var reverb = {
add: function add(sound) {
// Dummy implementation: does nothing, but prevents errors
// In a real environment, this would apply a reverb effect to the sound