User prompt
Dizleri swap yap
User prompt
Dizlerin birisi sagda birisi solda olsun.
User prompt
Bacakları biraz aç
User prompt
Üst bacakları swap yap
User prompt
Üst bacakları ve dizleri swap yap
User prompt
Bacakları biraz aç
User prompt
Bacakları biraz daha aç
User prompt
Bacakları biraz aç
User prompt
Üst bacakları swap yap
User prompt
Ust bacakları ve alt bacakları dizlerle bağla ve pozları güncelle
User prompt
Jumpta dizlerin bağlantısı bağlı kalsın
User prompt
Jumpta diz bağlı kalsın
User prompt
Jumpta diz bağlı kalsın
User prompt
Jumpta alt sol bacağı ters cevir
User prompt
Jumpta üst bacakları swap yap
User prompt
Jump ve sit pozlarinda tüm ikyi resetle
User prompt
Üst bacakları swap yap
User prompt
Bacakları biraz aç
User prompt
Alt bacakları swap yap
User prompt
Dizleri swap yap
User prompt
Alt bacaklari swap yap
User prompt
Alt bacakları ekle ust bacak devamına
User prompt
Dizler dogru pozisyonda degil tam ust bacak alt kenar ortasina koy
User prompt
Dizler dogru pozisyonda degil tam ust bacak alt ucunun ortasina koy
User prompt
Şimdi dizleri ekle ust bacak alt ucuna
/****
* 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
};
// --- 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
var lUpperLegAngle = 0.18;
var rUpperLegAngle = -0.18;
var lLowerLegAngle = 0.25;
var rLowerLegAngle = -0.25;
// Pose-based leg animation
if (self.state.pose === 'sit') {
lUpperLegAngle = 1.35;
rUpperLegAngle = 1.35;
lLowerLegAngle = lUpperLegAngle - Math.PI / 2 + 0.15;
rLowerLegAngle = rUpperLegAngle - Math.PI / 2 - 0.15;
} else if (self.state.pose === 'jump') {
// In jump pose, upper legs are raised up
lUpperLegAngle = -0.9; // sol üst bacak yukarı
rUpperLegAngle = 0.9; // sağ üst bacak yukarı
lLowerLegAngle = lUpperLegAngle + 2.1;
rLowerLegAngle = rUpperLegAngle + 2.1;
} 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 left hip to left knee
lUpperLeg.x = lHip.x;
lUpperLeg.y = lHip.y;
lUpperLeg.rotation = Math.atan2(lKnee.y - lHip.y, lKnee.x - lHip.x) - Math.PI / 2;
// Calculate left knee position
var lKneeX = lUpperLeg.x + Math.sin(lUpperLegAngle) * upperLegH;
var lKneeY = lUpperLeg.y + Math.cos(lUpperLegAngle) * upperLegH;
lKnee.x = lKneeX;
lKnee.y = lKneeY;
// Left lower leg (SWAPPED: use right knee and right lower leg angle)
lLowerLeg.x = rKneeX;
lLowerLeg.y = rKneeY;
lLowerLeg.rotation = rLowerLegAngle;
// Right upper leg: connect from right hip to right knee
rUpperLeg.x = rHip.x;
rUpperLeg.y = rHip.y;
rUpperLeg.rotation = Math.atan2(rKnee.y - rHip.y, rKnee.x - rHip.x) - Math.PI / 2;
// Calculate right knee position
var rKneeX = rUpperLeg.x + Math.sin(rUpperLegAngle) * upperLegH;
var rKneeY = rUpperLeg.y + Math.cos(rUpperLegAngle) * upperLegH;
rKnee.x = rKneeX;
rKnee.y = rKneeY;
// Attach lower leg at knee, rotate for more natural foot placement
// SWAPPED: use left knee and left lower leg angle for right lower leg
rLowerLeg.x = lKneeX;
rLowerLeg.y = lKneeY;
rLowerLeg.rotation = lLowerLegAngle;
// Pose adjustments
if (self.state.pose === 'sit') {
// Sitting: thighs forward, knees bent, shins down
lUpperLeg.x = lHip.x;
lUpperLeg.y = lHip.y;
lUpperLeg.rotation = 1.35;
var lKneeX = lUpperLeg.x + Math.sin(lUpperLeg.rotation) * upperLegH;
var lKneeY = lUpperLeg.y + Math.cos(lUpperLeg.rotation) * upperLegH;
lKnee.x = lKneeX;
lKnee.y = lKneeY;
// SWAPPED: left lower leg uses right knee and right lower leg angle
lLowerLeg.x = rKneeX;
lLowerLeg.y = rKneeY;
lLowerLeg.rotation = rUpperLeg.rotation - Math.PI / 2 - 0.15;
rUpperLeg.x = rHip.x;
rUpperLeg.y = rHip.y;
rUpperLeg.rotation = 1.35;
var rKneeX = rUpperLeg.x + Math.sin(rUpperLeg.rotation) * upperLegH;
var rKneeY = rUpperLeg.y + Math.cos(rUpperLeg.rotation) * upperLegH;
rKnee.x = rKneeX;
rKnee.y = rKneeY;
// SWAPPED: right lower leg uses left knee and left lower leg angle
rLowerLeg.x = lKneeX;
rLowerLeg.y = lKneeY;
rLowerLeg.rotation = lUpperLeg.rotation - Math.PI / 2 + 0.15;
body.rotation = -0.18;
} else if (self.state.pose === 'jump') {
// Jump: knees bent, but upper legs do not change position
// --- Maintain upper leg to hip and knee connections in jump pose ---
// Left upper leg: connect from left hip to left knee
lUpperLeg.x = lHip.x;
lUpperLeg.y = lHip.y;
lUpperLeg.rotation = Math.atan2(lKnee.y - lUpperLeg.y, lKnee.x - lUpperLeg.x) - Math.PI / 2;
// Calculate left knee position based on upper leg angle
var lKneeX = lUpperLeg.x + Math.sin(lUpperLeg.rotation) * upperLegH;
var lKneeY = lUpperLeg.y + Math.cos(lUpperLeg.rotation) * upperLegH;
lKnee.x = lKneeX;
lKnee.y = lKneeY;
// Attach lower leg at knee, rotate for jump
// SWAPPED: left lower leg uses right knee and right lower leg angle
lLowerLeg.x = rKneeX;
lLowerLeg.y = rKneeY;
lLowerLeg.rotation = rUpperLeg.rotation + 2.1;
// Right upper leg: connect from right hip to right knee
rUpperLeg.x = rHip.x;
rUpperLeg.y = rHip.y;
rUpperLeg.rotation = Math.atan2(rKnee.y - rUpperLeg.y, rKnee.x - rUpperLeg.x) - Math.PI / 2;
// Calculate right knee position based on upper leg angle
var rKneeX = rUpperLeg.x + Math.sin(rUpperLeg.rotation) * upperLegH;
var rKneeY = rUpperLeg.y + Math.cos(rUpperLeg.rotation) * upperLegH;
rKnee.x = rKneeX;
rKnee.y = rKneeY;
// SWAPPED: right lower leg uses left knee and left lower leg angle
rLowerLeg.x = lKneeX;
rLowerLeg.y = lKneeY;
rLowerLeg.rotation = lUpperLeg.rotation + 2.1;
// Elbows more bent in jump
// Keep upper arms at default (down), but elbows and lower arms follow articulation
// (Shoulder-elbow already set above for jump pose)
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;
}
}
// Start with a shuffled playlist
var shuffledMusicOrder = [];
function reshuffleMusicOrder() {
shuffledMusicOrder = [];
for (var i = 0; i < musicTracks.length; ++i) shuffledMusicOrder.push(i);
shuffleArray(shuffledMusicOrder);
}
reshuffleMusicOrder();
var currentMusicOrderIndex = 0;
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];
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
@@ -202,11 +202,12 @@
anchorY: 0,
scaleX: 1.5,
scaleY: 1.5
});
- var rUpperLeg = self.attachAsset('puppet_upperleg', {
+ // Left knee
+ var lKnee = self.attachAsset('puppet_knee', {
anchorX: 0.5,
- anchorY: 0,
+ anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Left lower leg
@@ -215,8 +216,22 @@
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,
@@ -330,9 +345,9 @@
// Right lower arm
rLowerArm.x = rElbowX;
rLowerArm.y = rElbowY;
rLowerArm.rotation = rLowerArmAngle;
- // --- Improved leg kinematics (now using same structure as arms, no IK, just angles) ---
+ // --- Improved leg kinematics ---
var legY = bodyH / 2 - 10;
var legX = bodyW / 2 - 18;
// Hip positions (left and right)
var lHipX = -legX;
@@ -342,67 +357,125 @@
lHip.x = lHipX;
lHip.y = lHipY;
rHip.x = rHipX;
rHip.y = rHipY;
- // Default leg pose angles (legs down, slightly outward)
- var legAbduction = 0.18;
- var lUpperLegAngle = legAbduction;
- var rUpperLegAngle = -legAbduction;
+ // Default leg pose
+ var lUpperLegAngle = 0.18;
+ var rUpperLegAngle = -0.18;
+ var lLowerLegAngle = 0.25;
+ var rLowerLegAngle = -0.25;
// Pose-based leg animation
if (self.state.pose === 'sit') {
lUpperLegAngle = 1.35;
rUpperLegAngle = 1.35;
+ lLowerLegAngle = lUpperLegAngle - Math.PI / 2 + 0.15;
+ rLowerLegAngle = rUpperLegAngle - Math.PI / 2 - 0.15;
} else if (self.state.pose === 'jump') {
- // In jump pose, upper legs use the same angles as in stand pose (identical to each other)
- lUpperLegAngle = 0.18;
- rUpperLegAngle = -0.18;
+ // In jump pose, upper legs are raised up
+ lUpperLegAngle = -0.9; // sol üst bacak yukarı
+ rUpperLegAngle = 0.9; // sağ üst bacak yukarı
+ lLowerLegAngle = lUpperLegAngle + 2.1;
+ rLowerLegAngle = rUpperLegAngle + 2.1;
} 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 left hip, angle out
+ // Left upper leg: connect from left hip to left knee
lUpperLeg.x = lHip.x;
lUpperLeg.y = lHip.y;
- lUpperLeg.rotation = lUpperLegAngle;
- // Right upper leg: connect from right hip, angle out
- rUpperLeg.x = rHip.x;
- rUpperLeg.y = rHip.y;
- rUpperLeg.rotation = rUpperLegAngle;
- // --- Lower leg kinematics ---
- // Default lower leg angles (straight down)
- var lLowerLegAngle = 0;
- var rLowerLegAngle = 0;
- // Pose-based lower leg animation
- if (self.state.pose === 'sit') {
- lLowerLegAngle = 1.2;
- rLowerLegAngle = 1.2;
- } else if (self.state.pose === 'jump') {
- lLowerLegAngle = 0.1;
- rLowerLegAngle = -0.1;
- } 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 + Math.PI) * 0.18 : 0;
- lLowerLegAngle += walk;
- rLowerLegAngle -= walk;
- }
- // Left lower leg: connect to end of left upper leg
+ lUpperLeg.rotation = Math.atan2(lKnee.y - lHip.y, lKnee.x - lHip.x) - Math.PI / 2;
+ // Calculate left knee position
var lKneeX = lUpperLeg.x + Math.sin(lUpperLegAngle) * upperLegH;
var lKneeY = lUpperLeg.y + Math.cos(lUpperLegAngle) * upperLegH;
- lLowerLeg.x = lKneeX;
- lLowerLeg.y = lKneeY;
- lLowerLeg.rotation = lUpperLegAngle + lLowerLegAngle;
- // Right lower leg: connect to end of right upper leg
+ lKnee.x = lKneeX;
+ lKnee.y = lKneeY;
+ // Left lower leg (SWAPPED: use right knee and right lower leg angle)
+ lLowerLeg.x = rKneeX;
+ lLowerLeg.y = rKneeY;
+ lLowerLeg.rotation = rLowerLegAngle;
+ // Right upper leg: connect from right hip to right knee
+ rUpperLeg.x = rHip.x;
+ rUpperLeg.y = rHip.y;
+ rUpperLeg.rotation = Math.atan2(rKnee.y - rHip.y, rKnee.x - rHip.x) - Math.PI / 2;
+ // Calculate right knee position
var rKneeX = rUpperLeg.x + Math.sin(rUpperLegAngle) * upperLegH;
var rKneeY = rUpperLeg.y + Math.cos(rUpperLegAngle) * upperLegH;
- rLowerLeg.x = rKneeX;
- rLowerLeg.y = rKneeY;
- rLowerLeg.rotation = rUpperLegAngle + rLowerLegAngle;
- // Pose adjustments for body rotation
+ rKnee.x = rKneeX;
+ rKnee.y = rKneeY;
+ // Attach lower leg at knee, rotate for more natural foot placement
+ // SWAPPED: use left knee and left lower leg angle for right lower leg
+ rLowerLeg.x = lKneeX;
+ rLowerLeg.y = lKneeY;
+ rLowerLeg.rotation = lLowerLegAngle;
+ // Pose adjustments
if (self.state.pose === 'sit') {
+ // Sitting: thighs forward, knees bent, shins down
+ lUpperLeg.x = lHip.x;
+ lUpperLeg.y = lHip.y;
+ lUpperLeg.rotation = 1.35;
+ var lKneeX = lUpperLeg.x + Math.sin(lUpperLeg.rotation) * upperLegH;
+ var lKneeY = lUpperLeg.y + Math.cos(lUpperLeg.rotation) * upperLegH;
+ lKnee.x = lKneeX;
+ lKnee.y = lKneeY;
+ // SWAPPED: left lower leg uses right knee and right lower leg angle
+ lLowerLeg.x = rKneeX;
+ lLowerLeg.y = rKneeY;
+ lLowerLeg.rotation = rUpperLeg.rotation - Math.PI / 2 - 0.15;
+ rUpperLeg.x = rHip.x;
+ rUpperLeg.y = rHip.y;
+ rUpperLeg.rotation = 1.35;
+ var rKneeX = rUpperLeg.x + Math.sin(rUpperLeg.rotation) * upperLegH;
+ var rKneeY = rUpperLeg.y + Math.cos(rUpperLeg.rotation) * upperLegH;
+ rKnee.x = rKneeX;
+ rKnee.y = rKneeY;
+ // SWAPPED: right lower leg uses left knee and left lower leg angle
+ rLowerLeg.x = lKneeX;
+ rLowerLeg.y = lKneeY;
+ rLowerLeg.rotation = lUpperLeg.rotation - Math.PI / 2 + 0.15;
body.rotation = -0.18;
} else if (self.state.pose === 'jump') {
+ // Jump: knees bent, but upper legs do not change position
+ // --- Maintain upper leg to hip and knee connections in jump pose ---
+ // Left upper leg: connect from left hip to left knee
+ lUpperLeg.x = lHip.x;
+ lUpperLeg.y = lHip.y;
+ lUpperLeg.rotation = Math.atan2(lKnee.y - lUpperLeg.y, lKnee.x - lUpperLeg.x) - Math.PI / 2;
+ // Calculate left knee position based on upper leg angle
+ var lKneeX = lUpperLeg.x + Math.sin(lUpperLeg.rotation) * upperLegH;
+ var lKneeY = lUpperLeg.y + Math.cos(lUpperLeg.rotation) * upperLegH;
+ lKnee.x = lKneeX;
+ lKnee.y = lKneeY;
+ // Attach lower leg at knee, rotate for jump
+ // SWAPPED: left lower leg uses right knee and right lower leg angle
+ lLowerLeg.x = rKneeX;
+ lLowerLeg.y = rKneeY;
+ lLowerLeg.rotation = rUpperLeg.rotation + 2.1;
+ // Right upper leg: connect from right hip to right knee
+ rUpperLeg.x = rHip.x;
+ rUpperLeg.y = rHip.y;
+ rUpperLeg.rotation = Math.atan2(rKnee.y - rUpperLeg.y, rKnee.x - rUpperLeg.x) - Math.PI / 2;
+ // Calculate right knee position based on upper leg angle
+ var rKneeX = rUpperLeg.x + Math.sin(rUpperLeg.rotation) * upperLegH;
+ var rKneeY = rUpperLeg.y + Math.cos(rUpperLeg.rotation) * upperLegH;
+ rKnee.x = rKneeX;
+ rKnee.y = rKneeY;
+ // SWAPPED: right lower leg uses left knee and left lower leg angle
+ rLowerLeg.x = lKneeX;
+ rLowerLeg.y = lKneeY;
+ rLowerLeg.rotation = lUpperLeg.rotation + 2.1;
+ // Elbows more bent in jump
+ // Keep upper arms at default (down), but elbows and lower arms follow articulation
+ // (Shoulder-elbow already set above for jump pose)
+ 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;
}
@@ -483,13 +556,13 @@
// 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 - 10
+ // 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 - 10 = 2732 - 80
- // puppet.y = 2732 - 80 - (bodyH/2) - upperLegH + 10
- var puppetFeetOffset = bodyH / 2 + upperLegH - 10;
+ // 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) {
@@ -507,9 +580,9 @@
};
// --- 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 - 10;
+ var puppetFeetOffset = bodyH / 2 + upperLegH + lowerLegH - 20;
self.state.y = 2732 - 80 - puppetFeetOffset;
updateBodyParts();
return self;
});
@@ -523,18 +596,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