User prompt
Bacakları bağdaş yap
User prompt
Sadece sit pozda sabit kal test için
User prompt
Sadece zıplama pozda sabit kalmayı kaldır test bitti.
User prompt
Bacaklar aynı hizada olsun
User prompt
Jum pozda alt bacaklar simetrik olsun
User prompt
Jump pozda üst bacakları swap yap
User prompt
Jump pozda diz bağlı kalsın
User prompt
Alt bacaklar jump pozda ust bacaklara bağlı değil
User prompt
Sadece zıplama pozda sabit kal test için
User prompt
Dizler ve alt bacakları düzgün bağla
User prompt
Dizler ve üst bacakları düzgün bağla
User prompt
Üst bacakları swap yap
User prompt
Alt bacakları swap yap
User prompt
Sol ve sağ vücut parçaları simetrik pozisyonda dursun ve tüm pozlarda simetrik hareket etsin
User prompt
Omuzlar vücudun sol üst ve sağ üst köşede olmalı
User prompt
Ayaklar en altta zemine deysin diğer uzuvlar njnun üstünde yükselsin.
User prompt
Sol dirsek sol omuza sag dirsek sağ omuza. Sag omuz sag kalçaya sol omuz sol kalçaya. Sol ayak bileği sol dize sol diz sol kalçaya. Sağ ayak bilegi sağ dize sağ diz sağ kalçaya bağlansın ik
User prompt
Bileklerin pozisyonunu alt bacakların alt kenarina bitişik yap.
User prompt
Ayaklar zeminde bilekler üstünde ve alt bacaklar ve kukla aynı hizada olsun
User prompt
Alt ayakların tam uçlarına koy bilekleri
User prompt
Sol sağ ayak bileği ve ayak assetleri ekle. Alt bacaklarla ayakları bileklerle birbirine bağla ik.
User prompt
Üst bacaklar alt bacaklardan önde gözüksün
User prompt
Alt bacakları swap yap.
User prompt
Alt bacakları yer değiştir.
User prompt
Alt bacakları biraz daha dışa aç
/**** * 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 lower leg var lLowerLeg = self.attachAsset('puppet_lowerleg', { anchorX: 0.5, anchorY: 0, 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 }); // Left ankle var lAnkle = self.attachAsset('puppet_ankle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); // Right ankle var rAnkle = self.attachAsset('puppet_ankle', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); // Left foot var lFoot = self.attachAsset('puppet_foot', { anchorX: 0.5, anchorY: 0.2, scaleX: 1.5, scaleY: 1.5 }); // Right foot var rFoot = self.attachAsset('puppet_foot', { anchorX: 0.5, anchorY: 0.2, 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 }); // 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 }); // --- 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; } // 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 // --- Ava: Make lower legs angle outward more --- var lowerLegOutAngle = 0.38; // outward angle for lower legs (was 0.25, now more open) var lUpperLegAngle = legAbduction + (self.state.lUpperLegRotation || 0); var rUpperLegAngle = -legAbduction + (self.state.rUpperLegRotation || 0); var lLowerLegAngle = lowerLegOutAngle + (self.state.lLowerLegRotation || 0); var rLowerLegAngle = -lowerLegOutAngle + (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.32 + (self.state.lLowerLegRotation || 0); // was 0.15, now more outward rLowerLegAngle = rUpperLegAngle - Math.PI / 2 - 0.32 + (self.state.rLowerLegRotation || 0); // was 0.15, now more outward } 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.35 + (self.state.lLowerLegRotation || 0); // was 2.1, now more outward rLowerLegAngle = rUpperLegAngle + 2.35 + (self.state.rLowerLegRotation || 0); // was 2.1, now more outward } 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 right lower leg at left knee (swap lower legs) rLowerLeg.x = lKneeX; rLowerLeg.y = lKneeY; rLowerLeg.rotation = lLowerLegAngle; // --- Ankles and feet (default pose) --- // Right lower leg (attached at left knee) → right ankle // Place ankle so its top edge is flush with the bottom of the lower leg var rAnkleRadius = 28 * 1.5 / 2; // puppet_ankle height * scale / 2 var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius); var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius); rAnkle.x = rAnkleX; rAnkle.y = rAnkleY; // Right foot at right ankle, pointing forward rFoot.x = rAnkleX; rFoot.y = rAnkleY; rFoot.rotation = rLowerLeg.rotation; // 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 left lower leg at right knee (swap lower legs) lLowerLeg.x = rKneeX; lLowerLeg.y = rKneeY; lLowerLeg.rotation = rLowerLegAngle; // Left lower leg (attached at right knee) → left ankle // Place ankle so its top edge is flush with the bottom of the lower leg var lAnkleRadius = 28 * 1.5 / 2; // puppet_ankle height * scale / 2 var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius); var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius); lAnkle.x = lAnkleX; lAnkle.y = lAnkleY; // Left foot at left ankle, pointing forward lFoot.x = lAnkleX; lFoot.y = lAnkleY; lFoot.rotation = lLowerLeg.rotation; // 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; // Right lower leg: from knee, bent downward (swap lower legs) rLowerLeg.x = kneeX; rLowerLeg.y = kneeY; rLowerLeg.rotation = lUpperLeg.rotation - Math.PI / 2 + 0.18; // Right ankle and foot (sit) // Place ankle so its top edge is flush with the bottom of the lower leg var rAnkleRadius = 28 * 1.5 / 2; var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius); var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius); rAnkle.x = rAnkleX; rAnkle.y = rAnkleY; rFoot.x = rAnkleX; rFoot.y = rAnkleY; rFoot.rotation = rLowerLeg.rotation; // 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; // Left lower leg: from knee, bent downward (swap lower legs) lLowerLeg.x = kneeX; lLowerLeg.y = kneeY; lLowerLeg.rotation = rUpperLeg.rotation - Math.PI / 2 - 0.18; // Left ankle and foot (sit) // Place ankle so its top edge is flush with the bottom of the lower leg var lAnkleRadius = 28 * 1.5 / 2; var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius); var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius); lAnkle.x = lAnkleX; lAnkle.y = lAnkleY; lFoot.x = lAnkleX; lFoot.y = lAnkleY; lFoot.rotation = lLowerLeg.rotation; 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; // Right lower leg bends sharply upward, keeping connected at left knee (swap lower legs) rLowerLeg.x = lKnee.x; rLowerLeg.y = lKnee.y; rLowerLeg.rotation = lUpperLeg.rotation + 2.5; // sharp bend // Right ankle and foot (jump) // Place ankle so its top edge is flush with the bottom of the lower leg var rAnkleRadius = 28 * 1.5 / 2; var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius); var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius); rAnkle.x = rAnkleX; rAnkle.y = rAnkleY; rFoot.x = rAnkleX; rFoot.y = rAnkleY; rFoot.rotation = rLowerLeg.rotation; // --- 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; // Left lower leg bends sharply upward, keeping connected at right knee (swap lower legs) lLowerLeg.x = rKneeX; lLowerLeg.y = rKneeY; lLowerLeg.rotation = rUpperLeg.rotation + 2.5; // sharp bend // Left ankle and foot (jump) // Place ankle so its top edge is flush with the bottom of the lower leg var lAnkleRadius = 28 * 1.5 / 2; var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius); var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius); lAnkle.x = lAnkleX; lAnkle.y = lAnkleY; lFoot.x = lAnkleX; lFoot.y = lAnkleY; lFoot.rotation = lLowerLeg.rotation; // 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 ****/ // 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 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
@@ -382,101 +382,96 @@
rLowerArm.x = rElbowX;
rLowerArm.y = rElbowY;
rLowerArm.rotation = rLowerArmAngle;
// --- Improved leg kinematics ---
- // All legs/feet/ankles in a straight vertical line, feet on ground, ankles above, puppet centered
- // We'll compute the feet position first, then build up the chain above
- // 1. Compute the world Y for the ground (where feet should be)
- var groundY = 2732 - 80; // ground.y + ground.height = 2732 - 80
- // 2. Get foot asset height (scaled)
- var footH = 32 * 1.5;
- // 3. Place feet so their bottom touches the ground
- var footY = groundY - footH * (1 - 0.2); // anchorY=0.2, so bottom is at ground
- // 4. Ankles are above feet, at the top center of the foot asset
- var ankleH = 28 * 1.5;
- var ankleY = footY - ankleH / 2;
- // 5. Lower legs: connect from ankle upward, in a straight line
- var lowerLegH = 110 * 1.5;
- var lowerLegY = ankleY - lowerLegH / 2;
- // 6. Knees: above lower legs
- var kneeH = 32 * 1.5;
- var kneeY = lowerLegY - lowerLegH / 2 - kneeH / 2;
- // 7. Upper legs: connect from knee upward, in a straight line
- var upperLegH = 120 * 1.5;
- var upperLegY = kneeY - upperLegH / 2;
- // 8. Hips: above upper legs
- var hipH = 44 * 1.5;
- var hipY = upperLegY - upperLegH / 2 - hipH / 2;
- // 9. Puppet body: above hips
- var bodyH = 200 * 1.5;
- var bodyY = hipY - hipH / 2 - bodyH / 2;
- // 10. Puppet x: center
- var puppetX = 0;
- // 11. All X positions are aligned
- var puppetLineX = 0;
- // --- Place hips ---
- lHip.x = puppetLineX;
- lHip.y = hipY;
- rHip.x = puppetLineX;
- rHip.y = hipY;
- // --- Place upper legs ---
- lUpperLeg.x = puppetLineX;
- lUpperLeg.y = hipY + hipH / 2 + upperLegH / 2;
- lUpperLeg.rotation = 0;
- rUpperLeg.x = puppetLineX;
- rUpperLeg.y = hipY + hipH / 2 + upperLegH / 2;
- rUpperLeg.rotation = 0;
- // --- Place knees ---
- lKnee.x = puppetLineX;
- lKnee.y = kneeY;
- rKnee.x = puppetLineX;
- rKnee.y = kneeY;
- // --- Place lower legs ---
- lLowerLeg.x = puppetLineX;
- lLowerLeg.y = lowerLegY;
- lLowerLeg.rotation = 0;
- rLowerLeg.x = puppetLineX;
- rLowerLeg.y = lowerLegY;
- rLowerLeg.rotation = 0;
- // --- Place ankles ---
- lAnkle.x = puppetLineX;
- lAnkle.y = ankleY;
- rAnkle.x = puppetLineX;
- rAnkle.y = ankleY;
- // --- Place feet ---
- lFoot.x = puppetLineX;
- lFoot.y = footY;
- lFoot.rotation = 0;
- rFoot.x = puppetLineX;
- rFoot.y = footY;
- rFoot.rotation = 0;
- // --- Place body ---
- body.x = puppetLineX;
- body.y = bodyY;
- // --- Place head and neck above body as before ---
- var headH = 120 * 1.5;
- var neckH = 44 * 1.5;
- head.x = puppetLineX;
- head.y = bodyY - bodyH / 2 - headH / 2 - 30;
- head.rotation = self.state.headAngle;
- neck.x = puppetLineX;
- neck.y = bodyY - bodyH / 2 - neckH / 2 + 38;
- neck.rotation = 0;
- // --- Place shoulders and arms as before ---
- var bodyW = 80 * 1.5;
- var upperArmH = 100 * 1.5;
- var upperArmW = 40 * 1.5;
- var armY = bodyY - bodyH / 2 + 30;
- var armX = bodyW / 2 + upperArmW / 2 - 10;
- var lShoulderX = puppetLineX - armX;
- var lShoulderY = armY;
- var rShoulderX = puppetLineX + armX;
- var rShoulderY = armY;
- lShoulder.x = lShoulderX;
- lShoulder.y = lShoulderY;
- rShoulder.x = rShoulderX;
- rShoulder.y = rShoulderY;
- // (Arms, elbows, lower arms, etc. can be placed as before, or in a straight pose if desired)
+ 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
+ // --- Ava: Make lower legs angle outward more ---
+ var lowerLegOutAngle = 0.38; // outward angle for lower legs (was 0.25, now more open)
+ var lUpperLegAngle = legAbduction + (self.state.lUpperLegRotation || 0);
+ var rUpperLegAngle = -legAbduction + (self.state.rUpperLegRotation || 0);
+ var lLowerLegAngle = lowerLegOutAngle + (self.state.lLowerLegRotation || 0);
+ var rLowerLegAngle = -lowerLegOutAngle + (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.32 + (self.state.lLowerLegRotation || 0); // was 0.15, now more outward
+ rLowerLegAngle = rUpperLegAngle - Math.PI / 2 - 0.32 + (self.state.rLowerLegRotation || 0); // was 0.15, now more outward
+ } 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.35 + (self.state.lLowerLegRotation || 0); // was 2.1, now more outward
+ rLowerLegAngle = rUpperLegAngle + 2.35 + (self.state.rLowerLegRotation || 0); // was 2.1, now more outward
+ } 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 right lower leg at left knee (swap lower legs)
+ rLowerLeg.x = lKneeX;
+ rLowerLeg.y = lKneeY;
+ rLowerLeg.rotation = lLowerLegAngle;
+ // --- Ankles and feet (default pose) ---
+ // Right lower leg (attached at left knee) → right ankle
+ // Place ankle so its top edge is flush with the bottom of the lower leg
+ var rAnkleRadius = 28 * 1.5 / 2; // puppet_ankle height * scale / 2
+ var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius);
+ var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius);
+ rAnkle.x = rAnkleX;
+ rAnkle.y = rAnkleY;
+ // Right foot at right ankle, pointing forward
+ rFoot.x = rAnkleX;
+ rFoot.y = rAnkleY;
+ rFoot.rotation = rLowerLeg.rotation;
+ // 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 left lower leg at right knee (swap lower legs)
+ lLowerLeg.x = rKneeX;
+ lLowerLeg.y = rKneeY;
+ lLowerLeg.rotation = rLowerLegAngle;
+ // Left lower leg (attached at right knee) → left ankle
+ // Place ankle so its top edge is flush with the bottom of the lower leg
+ var lAnkleRadius = 28 * 1.5 / 2; // puppet_ankle height * scale / 2
+ var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius);
+ var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius);
+ lAnkle.x = lAnkleX;
+ lAnkle.y = lAnkleY;
+ // Left foot at left ankle, pointing forward
+ lFoot.x = lAnkleX;
+ lFoot.y = lAnkleY;
+ lFoot.rotation = lLowerLeg.rotation;
// 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
@@ -500,24 +495,19 @@
// Right lower leg: from knee, bent downward (swap lower legs)
rLowerLeg.x = kneeX;
rLowerLeg.y = kneeY;
rLowerLeg.rotation = lUpperLeg.rotation - Math.PI / 2 + 0.18;
- // Right ankle and foot (sit) at very tip of lower leg
- var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * lowerLegH;
- var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * lowerLegH;
+ // Right ankle and foot (sit)
+ // Place ankle so its top edge is flush with the bottom of the lower leg
+ var rAnkleRadius = 28 * 1.5 / 2;
+ var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius);
+ var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius);
rAnkle.x = rAnkleX;
rAnkle.y = rAnkleY;
rFoot.x = rAnkleX;
rFoot.y = rAnkleY;
rFoot.rotation = rLowerLeg.rotation;
- // Left ankle and foot (sit) at very tip of lower leg
- var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * lowerLegH;
- var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * lowerLegH;
- lAnkle.x = lAnkleX;
- lAnkle.y = lAnkleY;
- lFoot.x = lAnkleX;
- lFoot.y = lAnkleY;
- lFoot.rotation = lLowerLeg.rotation;
+ // 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;
@@ -526,8 +516,17 @@
lLowerLeg.x = kneeX;
lLowerLeg.y = kneeY;
lLowerLeg.rotation = rUpperLeg.rotation - Math.PI / 2 - 0.18;
// Left ankle and foot (sit)
+ // Place ankle so its top edge is flush with the bottom of the lower leg
+ var lAnkleRadius = 28 * 1.5 / 2;
+ var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius);
+ var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius);
+ lAnkle.x = lAnkleX;
+ lAnkle.y = lAnkleY;
+ lFoot.x = lAnkleX;
+ lFoot.y = lAnkleY;
+ lFoot.rotation = lLowerLeg.rotation;
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) ---
@@ -542,24 +541,19 @@
// Right lower leg bends sharply upward, keeping connected at left knee (swap lower legs)
rLowerLeg.x = lKnee.x;
rLowerLeg.y = lKnee.y;
rLowerLeg.rotation = lUpperLeg.rotation + 2.5; // sharp bend
- // Right ankle and foot (jump) at very tip of lower leg
- var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * lowerLegH;
- var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * lowerLegH;
+ // Right ankle and foot (jump)
+ // Place ankle so its top edge is flush with the bottom of the lower leg
+ var rAnkleRadius = 28 * 1.5 / 2;
+ var rAnkleX = rLowerLeg.x + Math.sin(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius);
+ var rAnkleY = rLowerLeg.y + Math.cos(rLowerLeg.rotation) * (lowerLegH - rAnkleRadius);
rAnkle.x = rAnkleX;
rAnkle.y = rAnkleY;
rFoot.x = rAnkleX;
rFoot.y = rAnkleY;
rFoot.rotation = rLowerLeg.rotation;
- // Left ankle and foot (jump) at very tip of lower leg
- var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * lowerLegH;
- var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * lowerLegH;
- lAnkle.x = lAnkleX;
- lAnkle.y = lAnkleY;
- lFoot.x = lAnkleX;
- lFoot.y = lAnkleY;
- lFoot.rotation = lLowerLeg.rotation;
+ // --- 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;
@@ -570,8 +564,17 @@
lLowerLeg.x = rKneeX;
lLowerLeg.y = rKneeY;
lLowerLeg.rotation = rUpperLeg.rotation + 2.5; // sharp bend
// Left ankle and foot (jump)
+ // Place ankle so its top edge is flush with the bottom of the lower leg
+ var lAnkleRadius = 28 * 1.5 / 2;
+ var lAnkleX = lLowerLeg.x + Math.sin(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius);
+ var lAnkleY = lLowerLeg.y + Math.cos(lLowerLeg.rotation) * (lowerLegH - lAnkleRadius);
+ lAnkle.x = lAnkleX;
+ lAnkle.y = lAnkleY;
+ lFoot.x = lAnkleX;
+ lFoot.y = lAnkleY;
+ lFoot.rotation = lLowerLeg.rotation;
// Elbows more bent in jump
lLowerArm.x = lElbow.x;
lLowerArm.y = lElbow.y;
lLowerArm.rotation = 2.0;
@@ -699,18 +702,18 @@
/****
* 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
+// 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
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