User prompt
Sorunlu ve gereksiz kodları temizle
User prompt
Testten çık
User prompt
Testten çık
User prompt
Kuklayı zemine kadar indir
User prompt
Tüm ik bağlantılarını beyaz renkte ve noktalı çizgilerle en önde gòzukecek şekilde çiz.
User prompt
Tüm ik bağlantılarını beyaz renkte ve noktalı çizgilerle en önde gòzukecek şekilde çiz.
User prompt
Bağlantı çizgileri beyaz olsun
User prompt
Please fix the bug: 'TypeError: LK.getLine is not a function' in or related to this line: 'var line = LK.getLine({' Line Number: 647
User prompt
Tüm ik bağlantılarını beyaz noktalı çizgilerle en önde gòzukecek şekilde çiz.
User prompt
Kalçayı aşağıya çek
User prompt
Üst bacakları sol sağ yer değiştir
User prompt
Üst bacakları aç
User prompt
Bacakların bağdaş durmasın
User prompt
Alt bacaklar zemine deysin
User prompt
Alt bacakların alt kenarları zeminde olsun.
User prompt
Dizler aynı hizada olsun
User prompt
Dizlerin tüm ik bağlantılarını yap
User prompt
Dizlerin tüm ik bağlantılarını resetle
User prompt
Dizler merkezi üst bacakların alt kenarının tam orta noktasında olmalı
User prompt
Dizler bacakların önünde görünmeli
User prompt
Dirsekler bacakların önünde gözüksün
User prompt
Üst bacaklari aç.
User prompt
Üst bacaklar çapraz durmasin
User prompt
Zemine indir
User prompt
Zemine sıfır yap
/**** * 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 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; head.y = -bodyH / 2 - headH / 2 - 30; head.rotation = self.state.headAngle; // Neck var hipH = 44 * 1.5; var neckH = hipH; neck.x = 0; neck.y = -bodyH / 2 - neckH / 2 + 38; neck.rotation = 0; // Body body.x = 0; body.y = -bodyH / 2; // --- Symmetric Arms --- var armY = -bodyH / 2 + 30; var armX = bodyW / 2 + upperArmW / 2 - 10; // Shoulders var lShoulderX = -armX; var lShoulderY = armY; var rShoulderX = armX; var rShoulderY = armY; lShoulder.x = lShoulderX; lShoulder.y = lShoulderY; rShoulder.x = rShoulderX; rShoulder.y = rShoulderY; // Default symmetric arm pose var armAbduction = 0.32; var baseUpperArmAngle = 0.0; var baseLowerArmAngle = 0.0; var lUpperArmAngle = -armAbduction + baseUpperArmAngle; var rUpperArmAngle = armAbduction + baseUpperArmAngle; var lLowerArmAngle = baseLowerArmAngle; var rLowerArmAngle = baseLowerArmAngle; // Symmetric 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') { lUpperArmAngle = -1.6 - armAbduction; rUpperArmAngle = 1.6 + armAbduction; lLowerArmAngle = 2.0; rLowerArmAngle = -2.0; } else if (self.state.pose === 'stand') { 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 arm lUpperArm.x = lShoulderX; lUpperArm.y = lShoulderY; var lElbowX = lUpperArm.x + Math.sin(lUpperArmAngle) * upperArmH; var lElbowY = lUpperArm.y + Math.cos(lUpperArmAngle) * upperArmH; lElbow.x = lElbowX; lElbow.y = lElbowY; lUpperArm.rotation = Math.atan2(lElbow.y - lUpperArm.y, lElbow.x - lUpperArm.x) - Math.PI / 2; lLowerArm.x = lElbowX; lLowerArm.y = lElbowY; lLowerArm.rotation = lLowerArmAngle; // Right arm (mirror of left) rUpperArm.x = rShoulderX; rUpperArm.y = rShoulderY; var rElbowX = rUpperArm.x + Math.sin(rUpperArmAngle) * upperArmH; var rElbowY = rUpperArm.y + Math.cos(rUpperArmAngle) * upperArmH; rElbow.x = rElbowX; rElbow.y = rElbowY; rUpperArm.rotation = Math.atan2(rElbow.y - rUpperArm.y, rElbow.x - rUpperArm.x) - Math.PI / 2; rLowerArm.x = rElbowX; rLowerArm.y = rElbowY; rLowerArm.rotation = rLowerArmAngle; // --- Symmetric Legs --- var legY = bodyH / 2 - 10; var legX = bodyW / 2 - 18; // Hips 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 symmetric leg pose var legAbduction = 0.28; var lowerLegOutAngle = 0.38; 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); // Symmetric pose-based leg animation if (self.state.pose === 'sit') { // Cross-legged (bağdaş) pose // Hips // Move hips slightly closer for a more natural cross-legged look var hipsMidX = (lHip.x + rHip.x) / 2; var hipsMidY = (lHip.y + rHip.y) / 2 + 18; // Cross-legged: knees cross in front of body, ankles under opposite knee var crossKneeSpread = 60; // horizontal distance from center for knees var crossKneeForward = 80; // forward (down) distance for knees var crossAnkleSpread = 90; // horizontal distance from center for ankles var crossAnkleForward = 170; // forward (down) distance for ankles // Upper legs: hips to knees (open thighs outward for cross-legged look) var thighSpreadAngle = 0.55; // radians, how much to open thighs outward // Calculate upper leg bottom (knee) positions lUpperLeg.x = lHip.x; lUpperLeg.y = lHip.y; lUpperLeg.rotation = Math.atan2(Math.sin(thighSpreadAngle), Math.cos(thighSpreadAngle)) + Math.PI / 2; rUpperLeg.x = rHip.x; rUpperLeg.y = rHip.y; rUpperLeg.rotation = -Math.atan2(Math.sin(thighSpreadAngle), Math.cos(thighSpreadAngle)) - Math.PI / 2; // Find the bottom center of each upper leg (where knee should be) var lKneeAttachX = lUpperLeg.x + Math.sin(lUpperLeg.rotation + Math.PI / 2) * upperLegH; var lKneeAttachY = lUpperLeg.y + Math.cos(lUpperLeg.rotation + Math.PI / 2) * upperLegH; var rKneeAttachX = rUpperLeg.x + Math.sin(rUpperLeg.rotation + Math.PI / 2) * upperLegH; var rKneeAttachY = rUpperLeg.y + Math.cos(rUpperLeg.rotation + Math.PI / 2) * upperLegH; // Place knees at the exact midpoint of the bottom edge of the upper legs // --- Ava: Make knees at the same y position --- var avgKneeY = (lKneeAttachY + rKneeAttachY) / 2; var lKneeX = lKneeAttachX; var lKneeY = avgKneeY; var rKneeX = rKneeAttachX; var rKneeY = avgKneeY; // Knees (bring knees visually in front of upper/lower legs by setting z-order) // To ensure knees are drawn in front, remove and re-add them after legs if (lKnee.parent) lKnee.parent.removeChild(lKnee); if (rKnee.parent) rKnee.parent.removeChild(rKnee); // --- Connect knees to both upper and lower legs --- // Left knee: connect to left upper leg (top) and left lower leg (bottom) lKnee.x = lKneeX; lKnee.y = lKneeY; // Right knee: connect to right upper leg (top) and right lower leg (bottom) rKnee.x = rKneeX; rKnee.y = rKneeY; // Lower legs: knees to opposite ankles (crossed under) // --- Ava: Place lower leg bottom edges exactly on the ground --- // The lower leg is anchored at (0.5, 0), so its bottom is at y + Math.cos(rotation + PI/2) * lowerLegH_px var groundY = 2732 - 80; var lowerLegH_px = 110 * 1.5; // For each lower leg, solve for rotation so that the bottom edge is at groundY // Left lower leg lLowerLeg.x = lKnee.x; lLowerLeg.y = lKnee.y; // Find angle so that lLowerLeg.y + Math.cos(rotation + Math.PI/2) * lowerLegH_px = groundY // Solve for rotation: var lDeltaY = groundY - lLowerLeg.y; var lAngle = Math.acos(Math.max(-1, Math.min(1, lDeltaY / lowerLegH_px))) - Math.PI / 2; // If the knee is to the right of the hip center, flip the sign if (lKnee.x < (lHip.x + rHip.x) / 2) lAngle = -lAngle; lLowerLeg.rotation = lAngle; // Right lower leg rLowerLeg.x = rKnee.x; rLowerLeg.y = rKnee.y; var rDeltaY = groundY - rLowerLeg.y; var rAngle = Math.acos(Math.max(-1, Math.min(1, rDeltaY / lowerLegH_px))) - Math.PI / 2; if (rKnee.x > (lHip.x + rHip.x) / 2) rAngle = -rAngle; rLowerLeg.rotation = rAngle; // Now set knee positions and re-add to ensure they are on top self.addChild(lKnee); self.addChild(rKnee); body.rotation = 0; } else if (self.state.pose === 'jump') { // Both upper legs up and slightly inward, knees together, feet up, using IK // --- Keep knees and upper legs connected in jump pose --- // --- Make both legs perfectly horizontally aligned in jump pose --- var jumpThighAngle = 0.45; var jumpKneeBend = 1.25; // radians, how much the knee is bent (smaller = straighter, larger = more bent) // Set both hips at same y, and both knees at same y, for perfect horizontal alignment // Calculate the average x between hips for knee position, and set a fixed y offset for knees var avgHipY = (lHip.y + rHip.y) / 2; var avgHipX = (lHip.x + rHip.x) / 2; var kneeYOffset = -upperLegH * Math.cos(jumpThighAngle); // vertical offset from hips to knees var kneeY = avgHipY + kneeYOffset; var kneeXLeft = lHip.x + Math.sin(-jumpThighAngle - legAbduction) * upperLegH; var kneeXRight = rHip.x + Math.sin(jumpThighAngle + legAbduction) * upperLegH; // Both knees at same y lKnee.x = kneeXLeft; lKnee.y = kneeY; rKnee.x = kneeXRight; rKnee.y = kneeY; // Upper legs: hips to knees lUpperLeg.x = lHip.x; lUpperLeg.y = lHip.y; lUpperLeg.rotation = Math.atan2(lKnee.y - lUpperLeg.y, lKnee.x - lUpperLeg.x) - Math.PI / 2; rUpperLeg.x = rHip.x; rUpperLeg.y = rHip.y; rUpperLeg.rotation = Math.atan2(rKnee.y - rUpperLeg.y, rKnee.x - rUpperLeg.x) - Math.PI / 2; // Lower legs: knees to ankles, both at same y // Left lLowerLeg.x = lKnee.x; lLowerLeg.y = lKnee.y; var lJumpShinLen = lowerLegH; var lJumpAnkleX = lKnee.x + Math.sin(lUpperLeg.rotation + Math.PI / 2 + jumpKneeBend) * lJumpShinLen; var lJumpAnkleY = lKnee.y + Math.cos(lUpperLeg.rotation + Math.PI / 2 + jumpKneeBend) * lJumpShinLen; lLowerLeg.rotation = Math.atan2(lJumpAnkleY - lKnee.y, lJumpAnkleX - lKnee.x) - Math.PI / 2; // Right rLowerLeg.x = rKnee.x; rLowerLeg.y = rKnee.y; var rJumpShinLen = lowerLegH; var rJumpAnkleX = rKnee.x + Math.sin(rUpperLeg.rotation + Math.PI / 2 + jumpKneeBend) * rJumpShinLen; var rJumpAnkleY = rKnee.y + Math.cos(rUpperLeg.rotation + Math.PI / 2 + jumpKneeBend) * rJumpShinLen; rLowerLeg.rotation = Math.atan2(rJumpAnkleY - rKnee.y, rJumpAnkleX - rKnee.x) - Math.PI / 2; // 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; } 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 leg lUpperLeg.x = lHip.x; lUpperLeg.y = lHip.y; 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 to left knee lLowerLeg.x = lKneeX; lLowerLeg.y = lKneeY; // Calculate ankle position for left leg var lStandShinLen = lowerLegH; var lStandAnkleX = lKneeX + Math.sin(lLowerLegAngle) * lStandShinLen; var lStandAnkleY = lKneeY + Math.cos(lLowerLegAngle) * lStandShinLen; lLowerLeg.rotation = Math.atan2(lStandAnkleY - lKneeY, lStandAnkleX - lKneeX) - Math.PI / 2; // Right leg (mirror) rUpperLeg.x = rHip.x; rUpperLeg.y = rHip.y; 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 to right knee rLowerLeg.x = rKneeX; rLowerLeg.y = rKneeY; // Calculate ankle position for right leg var rStandShinLen = lowerLegH; var rStandAnkleX = rKneeX + Math.sin(rLowerLegAngle) * rStandShinLen; var rStandAnkleY = rKneeY + Math.cos(rLowerLegAngle) * rStandShinLen; rLowerLeg.rotation = Math.atan2(rStandAnkleY - rKneeY, rStandAnkleX - rKneeX) - Math.PI / 2; 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 () { // --- Physics update --- // TEST: Force puppet to always stay in sit pose for testing self.state.pose = 'sit'; self.state.vy += 3.2; // gravity self.state.x += self.state.vx; self.state.y += self.state.vy; // Friction if (self.state.grounded) { self.state.vx *= 0.82; } else { self.state.vx *= 0.98; } // Clamp to world bounds if (self.state.x < 0) self.state.x = 0; if (self.state.x > 2048) self.state.x = 2048; // Ground collision var groundY = 2732 - 80; var puppetFeetOffset = bodyH / 2 + upperLegH + lowerLegH - 20; var feetY = self.state.y + puppetFeetOffset; if (feetY >= groundY) { self.state.y = groundY - puppetFeetOffset; 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 (keep puppet at current position) 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
@@ -399,38 +399,29 @@
rKnee.x = rKneeX;
rKnee.y = rKneeY;
// Lower legs: knees to opposite ankles (crossed under)
// --- Ava: Place lower leg bottom edges exactly on the ground ---
+ // The lower leg is anchored at (0.5, 0), so its bottom is at y + Math.cos(rotation + PI/2) * lowerLegH_px
var groundY = 2732 - 80;
var lowerLegH_px = 110 * 1.5;
- var lLowerLegBottomY = groundY;
- var rLowerLegBottomY = groundY;
- // For each lower leg, solve for ankle position so that the bottom edge of the lower leg is at groundY
- // The lower leg is anchored at (0.5, 0), so its bottom is at y + Math.cos(rotation + PI/2) * lowerLegH_px
- // We'll solve for the ankle position so that this is true
+ // For each lower leg, solve for rotation so that the bottom edge is at groundY
// Left lower leg
- var lKneeToAnkleLen = lowerLegH_px;
- var lKneeX_to_ankle = hipsMidX - crossAnkleSpread;
- var lKneeY_to_ankle = groundY - lKnee.y;
- var lLowerLegAngle = Math.atan2(lKneeY_to_ankle, lKneeX_to_ankle - lKnee.x);
- var lAnkleX = lKnee.x + Math.sin(lLowerLegAngle) * lKneeToAnkleLen;
- var lAnkleY = lKnee.y + Math.cos(lLowerLegAngle) * lKneeToAnkleLen;
- // But we want the bottom of the lower leg to be at groundY, so adjust
- lAnkleY = groundY;
lLowerLeg.x = lKnee.x;
lLowerLeg.y = lKnee.y;
- lLowerLeg.rotation = Math.atan2(lAnkleY - lKnee.y, lAnkleX - lKnee.x) - Math.PI / 2;
+ // Find angle so that lLowerLeg.y + Math.cos(rotation + Math.PI/2) * lowerLegH_px = groundY
+ // Solve for rotation:
+ var lDeltaY = groundY - lLowerLeg.y;
+ var lAngle = Math.acos(Math.max(-1, Math.min(1, lDeltaY / lowerLegH_px))) - Math.PI / 2;
+ // If the knee is to the right of the hip center, flip the sign
+ if (lKnee.x < (lHip.x + rHip.x) / 2) lAngle = -lAngle;
+ lLowerLeg.rotation = lAngle;
// Right lower leg
- var rKneeToAnkleLen = lowerLegH_px;
- var rKneeX_to_ankle = hipsMidX + crossAnkleSpread;
- var rKneeY_to_ankle = groundY - rKnee.y;
- var rLowerLegAngle = Math.atan2(rKneeY_to_ankle, rKneeX_to_ankle - rKnee.x);
- var rAnkleX = rKnee.x + Math.sin(rLowerLegAngle) * rKneeToAnkleLen;
- var rAnkleY = rKnee.y + Math.cos(rLowerLegAngle) * rKneeToAnkleLen;
- rAnkleY = groundY;
rLowerLeg.x = rKnee.x;
rLowerLeg.y = rKnee.y;
- rLowerLeg.rotation = Math.atan2(rAnkleY - rKnee.y, rAnkleX - rKnee.x) - Math.PI / 2;
+ var rDeltaY = groundY - rLowerLeg.y;
+ var rAngle = Math.acos(Math.max(-1, Math.min(1, rDeltaY / lowerLegH_px))) - Math.PI / 2;
+ if (rKnee.x > (lHip.x + rHip.x) / 2) rAngle = -rAngle;
+ rLowerLeg.rotation = rAngle;
// Now set knee positions and re-add to ensure they are on top
self.addChild(lKnee);
self.addChild(rKnee);
body.rotation = 0;