User prompt
Remove the guy who throws bombs and add a vibrant animated background ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the background a guy who throws bombs at you ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make a animated background ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make items move faster based on their rarity
User prompt
Add a animation for when you click a good item ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Remove new animations
User prompt
Add some animations and polish everything ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Get rid of the holdable item
User prompt
Add a good item which you hold down
User prompt
Make the spikes light grey
User prompt
Make the spikes look like grey balls with spikes around them
User prompt
Add some sound effects
User prompt
Space the orbs out a bit more when the score gets higher
User prompt
Add one more difficulty named insane which has more spawning and it is faster
User prompt
Make the good items a bit smaller
User prompt
Give the good items bigger hitboxes
User prompt
Make the good items look like magical orbs and the better they are the better aura they have
User prompt
Make the items look better
User prompt
Add a difficulty menu
User prompt
Remove everything about pop
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var pop = LK.getAsset('pop', {' Line Number: 60
User prompt
Make popping objects work
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var pop = LK.getAsset('pop', {' Line Number: 60
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var pop = LK.getAsset('pop', {' Line Number: 60
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var pop = LK.getAsset('pop', {' Line Number: 60
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // GuyBackground class: draws a guy at the top, animates his arm, and throws bombs var GuyBackground = Container.expand(function () { var self = Container.call(this); // Body var body = LK.getAsset('item_basic', { anchorX: 0.5, anchorY: 1.0 }); body.width = 320; body.height = 420; body.x = 2048 / 2; body.y = 320; body.alpha = 0.93; body.tint = 0x8d5524; self.addChild(body); // Head var head = LK.getAsset('item_basic', { anchorX: 0.5, anchorY: 0.5 }); head.width = 210; head.height = 210; head.x = body.x; head.y = body.y - body.height + 90; head.alpha = 1; head.tint = 0xf1c27d; self.addChild(head); // Eyes var eyeL = LK.getAsset('item_rare', { anchorX: 0.5, anchorY: 0.5 }); eyeL.width = 28; eyeL.height = 28; eyeL.x = head.x - 38; eyeL.y = head.y - 18; eyeL.tint = 0x222222; self.addChild(eyeL); var eyeR = LK.getAsset('item_rare', { anchorX: 0.5, anchorY: 0.5 }); eyeR.width = 28; eyeR.height = 28; eyeR.x = head.x + 38; eyeR.y = head.y - 18; eyeR.tint = 0x222222; self.addChild(eyeR); // Smile var smile = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); smile.width = 60; smile.height = 22; smile.x = head.x; smile.y = head.y + 38; smile.tint = 0x6d4c41; smile.alpha = 0.7; self.addChild(smile); // Left arm (static, for balance) var armL = LK.getAsset('item_basic', { anchorX: 0.5, anchorY: 0.1 }); armL.width = 60; armL.height = 170; armL.x = body.x - 110; armL.y = body.y - 220; armL.rotation = -Math.PI / 4.5; armL.tint = 0xf1c27d; armL.alpha = 0.93; self.addChild(armL); // Right arm (throws bombs) var armR = LK.getAsset('item_basic', { anchorX: 0.5, anchorY: 0.1 }); armR.width = 60; armR.height = 170; armR.x = body.x + 110; armR.y = body.y - 220; armR.tint = 0xf1c27d; armR.alpha = 0.93; self.addChild(armR); // Hand (right) var handR = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); handR.width = 54; handR.height = 54; handR.x = armR.x; handR.y = armR.y + armR.height - 18; handR.tint = 0xf1c27d; handR.alpha = 0.98; self.addChild(handR); // Bomb in hand (only visible when about to throw) var bomb = LK.getAsset('item_bomb', { anchorX: 0.5, anchorY: 0.5 }); bomb.width = 60; bomb.height = 60; bomb.x = handR.x; bomb.y = handR.y - 10; bomb.visible = false; self.addChild(bomb); // Animation state self.armThrowing = false; self.armThrowTimer = 0; self.armThrowDuration = 32; // frames self.lastThrowTick = 0; // For bomb throw event self.onBombThrow = null; // Animate arm and bomb self.update = function () { // Arm idle: gentle up/down var idleAngle = Math.PI / 4.5 + Math.sin(LK.ticks / 40) * 0.08; var throwAngle = -Math.PI / 1.2; if (!self.armThrowing) { armR.rotation = idleAngle; bomb.visible = false; } else { // Animate throw: swing up, then down var t = self.armThrowTimer / self.armThrowDuration; if (t < 0.45) { // Wind up armR.rotation = idleAngle + (throwAngle - idleAngle) * (t / 0.45); } else { // Snap down armR.rotation = throwAngle + (idleAngle - throwAngle) * ((t - 0.45) / 0.55); } bomb.visible = self.armThrowTimer < self.armThrowDuration * 0.7; // Bomb follows hand bomb.x = handR.x + Math.sin(armR.rotation) * (armR.height - 18); bomb.y = handR.y + Math.cos(armR.rotation) * (armR.height - 18) - 10; if (self.armThrowTimer === Math.floor(self.armThrowDuration * 0.7) && typeof self.onBombThrow === "function") { // Throw bomb now! self.onBombThrow(bomb.x, bomb.y); } self.armThrowTimer++; if (self.armThrowTimer >= self.armThrowDuration) { self.armThrowing = false; self.armThrowTimer = 0; } } }; // Call to trigger a throw self.throwBomb = function () { if (!self.armThrowing) { self.armThrowing = true; self.armThrowTimer = 0; } }; return self; }); // Item class for all falling items var Item = Container.expand(function () { var self = Container.call(this); // Asset id and score are set on creation self.assetId = 'item_basic'; self.scoreValue = 1; self.isBad = false; // true for bomb/spike self.isTapped = false; // Attach asset var itemGfx = self.attachAsset(self.assetId, { anchorX: 0.5, anchorY: 0.5 }); // Set up item visuals self.setType = function (type) { // type: {assetId, scoreValue, isBad} self.assetId = type.assetId; self.scoreValue = type.scoreValue; self.isBad = type.isBad; // Remove old asset if any if (itemGfx && itemGfx.parent) itemGfx.parent.removeChild(itemGfx); itemGfx = self.attachAsset(self.assetId, { anchorX: 0.5, anchorY: 0.5 }); // Add magical aura/glow for good items if (!self.isBad) { // Basic: faint green glow if (self.assetId === 'item_basic') { var aura = LK.getAsset('item_basic', { anchorX: 0.5, anchorY: 0.5 }); aura.width = itemGfx.width * 1.5; aura.height = itemGfx.height * 1.5; aura.alpha = 0.22; aura.tint = 0x7fffbe; self.addChild(aura); aura.zIndex = -1; } // Rare: blue aura, more intense, with a second layer if (self.assetId === 'item_rare') { var aura1 = LK.getAsset('item_rare', { anchorX: 0.5, anchorY: 0.5 }); aura1.width = itemGfx.width * 1.7; aura1.height = itemGfx.height * 1.7; aura1.alpha = 0.18; aura1.tint = 0x7ecbff; self.addChild(aura1); aura1.zIndex = -2; var aura2 = LK.getAsset('item_rare', { anchorX: 0.5, anchorY: 0.5 }); aura2.width = itemGfx.width * 1.25; aura2.height = itemGfx.height * 1.25; aura2.alpha = 0.32; aura2.tint = 0x42a5f5; self.addChild(aura2); aura2.zIndex = -1; } // Legend: golden aura, multi-layer if (self.assetId === 'item_legend') { var aura1 = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); aura1.width = itemGfx.width * 2.1; aura1.height = itemGfx.height * 2.1; aura1.alpha = 0.13; aura1.tint = 0xfff7b2; self.addChild(aura1); aura1.zIndex = -3; var aura2 = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); aura2.width = itemGfx.width * 1.5; aura2.height = itemGfx.height * 1.5; aura2.alpha = 0.22; aura2.tint = 0xffe082; self.addChild(aura2); aura2.zIndex = -2; var aura3 = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); aura3.width = itemGfx.width * 1.1; aura3.height = itemGfx.height * 1.1; aura3.alpha = 0.32; aura3.tint = 0xffc107; self.addChild(aura3); aura3.zIndex = -1; } } // For bomb, add a fuse and a little rotation if (self.assetId === 'item_bomb') { itemGfx.rotation = Math.PI / 8 * (Math.random() > 0.5 ? 1 : -1); // Add a fuse (small rectangle at top) var fuse = LK.getAsset('item_rare', { anchorX: 0.5, anchorY: 1.0 }); fuse.width = 18; fuse.height = 48; fuse.x = 0; fuse.y = -itemGfx.height / 2 + 10; fuse.alpha = 0.7; self.addChild(fuse); // Add a spark (small yellow ellipse) var spark = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); spark.width = 28; spark.height = 18; spark.x = 0; spark.y = fuse.y - 20; spark.alpha = 0.8; self.addChild(spark); } // For spike, make it a grey ball with spikes around it if (self.assetId === 'item_spike') { // Remove the box and use a light grey ellipse as the main body if (itemGfx && itemGfx.parent) itemGfx.parent.removeChild(itemGfx); itemGfx = self.attachAsset('item_bomb', { anchorX: 0.5, anchorY: 0.5 }); // Make it a light grey itemGfx.tint = 0xdddddd; // Add spikes around the ball var spikeCount = 8; var radius = itemGfx.width * 0.52; for (var s = 0; s < spikeCount; s++) { var angle = Math.PI * 2 / spikeCount * s; var spike = LK.getAsset('item_rare', { anchorX: 0.5, anchorY: 1.0 }); spike.width = itemGfx.width * 0.13; spike.height = itemGfx.height * 0.32; spike.x = Math.cos(angle) * radius; spike.y = Math.sin(angle) * radius; spike.rotation = angle; spike.alpha = 0.92; spike.tint = 0x888888; self.addChild(spike); } // Optionally, add a faint shadow for depth var shadow = LK.getAsset('item_bomb', { anchorX: 0.5, anchorY: 0.5 }); shadow.width = itemGfx.width * 1.12; shadow.height = itemGfx.height * 1.12; shadow.alpha = 0.13; shadow.tint = 0x222222; self.addChild(shadow); shadow.zIndex = -2; } }; // Called when tapped self.onTap = function () { if (self.isTapped) return; self.isTapped = true; // Animate: if bad, just remove immediately if (self.isBad) { if (self.parent) self.parent.removeChild(self); } else { // Good item: pop scale up, then shrink and fade out var origScaleX = self.scaleX; var origScaleY = self.scaleY; tween(self, { scaleX: origScaleX * 1.25, scaleY: origScaleY * 1.25 }, { duration: 90, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { scaleX: 0.2, scaleY: 0.2, alpha: 0 }, { duration: 180, easing: tween.cubicIn, onFinish: function onFinish() { if (self.parent) self.parent.removeChild(self); } }); } }); } }; // Called every tick self.update = function () { // Movement handled in game loop }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Add GuyBackground behind everything var guyBg = new GuyBackground(); game.addChild(guyBg); game.setChildIndex(guyBg, 0); // Ensure it's at the back // Helper: find the next bomb item to spawn, or null if none function findNextBombItemIndex() { for (var i = 0; i < items.length; i++) { if (items[i].assetId === 'item_bomb' && !items[i].isTapped && items[i].y < 0) { return i; } } return -1; } // Set up bomb throw callback guyBg.onBombThrow = function (bx, by) { // Find the next bomb item that hasn't appeared yet (y < 0) var idx = findNextBombItemIndex(); if (idx >= 0) { var bombItem = items[idx]; // Animate bombItem from guy's hand to its spawn X,Y bombItem.x = bx; bombItem.y = by; // Animate bomb flying down to its normal spawn Y var targetY = -100; var targetX = bombItem.x; tween(bombItem, { y: targetY }, { duration: 180, easing: tween.cubicIn }); } }; // spike: keep as box, but will add visual in class // rare: blue, slightly smaller // legend: larger, gold // bomb: dark ellipse // Item types // Good items // Bad items // Pop effect // Sounds // Music var ITEM_TYPES = [{ assetId: 'item_basic', scoreValue: 1, isBad: false, weight: 55 }, { assetId: 'item_rare', scoreValue: 3, isBad: false, weight: 18 }, { assetId: 'item_legend', scoreValue: 7, isBad: false, weight: 5 }, { assetId: 'item_bomb', scoreValue: 0, isBad: true, weight: 10 }, { assetId: 'item_spike', scoreValue: 0, isBad: true, weight: 5 }]; // Weighted random selection function pickItemType() { var total = 0; for (var i = 0; i < ITEM_TYPES.length; i++) total += ITEM_TYPES[i].weight; var r = Math.random() * total; var acc = 0; for (var i = 0; i < ITEM_TYPES.length; i++) { acc += ITEM_TYPES[i].weight; if (r < acc) return ITEM_TYPES[i]; } return ITEM_TYPES[0]; } // Game state var items = []; var lives = 3; var score = 0; var spawnInterval = 1000; // ms var minSpawnInterval = 350; var spawnTimer = null; var itemFallSpeed = 7; // px per frame var itemSpeedInc = 0.15; var itemSpawnDec = 30; var lastTapTime = 0; // Difficulty menu var difficultyMenu = null; var difficultySettings = { Easy: { lives: 5, spawnInterval: 1200, minSpawnInterval: 500, itemFallSpeed: 5, itemSpeedInc: 0.10, itemSpawnDec: 18 }, Normal: { lives: 3, spawnInterval: 1000, minSpawnInterval: 350, itemFallSpeed: 7, itemSpeedInc: 0.15, itemSpawnDec: 30 }, Hard: { lives: 2, spawnInterval: 800, minSpawnInterval: 200, itemFallSpeed: 10, itemSpeedInc: 0.22, itemSpawnDec: 45 }, Insane: { lives: 1, spawnInterval: 500, minSpawnInterval: 100, itemFallSpeed: 16, itemSpeedInc: 0.38, itemSpawnDec: 80 } }; var selectedDifficulty = "Normal"; // Show difficulty menu at game start function showDifficultyMenu() { if (difficultyMenu && difficultyMenu.parent) difficultyMenu.parent.removeChild(difficultyMenu); difficultyMenu = new Container(); // Background overlay var bg = LK.getAsset('item_basic', { anchorX: 0.5, anchorY: 0.5 }); bg.width = 900; bg.height = 900; bg.alpha = 0.92; bg.x = 2048 / 2; bg.y = 2732 / 2; difficultyMenu.addChild(bg); // Title var title = new Text2("Select Difficulty", { size: 120, fill: "#fff" }); title.anchor.set(0.5, 0); title.x = 2048 / 2; title.y = 2732 / 2 - 320; difficultyMenu.addChild(title); // Buttons var btnY = 2732 / 2 - 80; var btns = ["Easy", "Normal", "Hard", "Insane"]; for (var i = 0; i < btns.length; i++) { (function (idx) { var diff = btns[idx]; var btn = LK.getAsset('item_legend', { anchorX: 0.5, anchorY: 0.5 }); btn.width = 520; btn.height = 160; btn.x = 2048 / 2; btn.y = btnY + idx * 200; difficultyMenu.addChild(btn); var label = new Text2(diff, { size: 90, fill: diff === "Insane" ? "#b71c1c" : "#222" }); label.anchor.set(0.5, 0.5); label.x = btn.x; label.y = btn.y; difficultyMenu.addChild(label); btn.interactive = true; btn.down = function (x, y, obj) { selectDifficulty(diff); }; })(i); } // Add to game game.addChild(difficultyMenu); // Pause spawn if (spawnTimer) LK.clearInterval(spawnTimer); } // Set difficulty and start game function selectDifficulty(diff) { selectedDifficulty = diff; var s = difficultySettings[diff]; lives = s.lives; spawnInterval = s.spawnInterval; minSpawnInterval = s.minSpawnInterval; itemFallSpeed = s.itemFallSpeed; itemSpeedInc = s.itemSpeedInc; itemSpawnDec = s.itemSpawnDec; updateLives(); score = 0; scoreTxt.setText(score); if (difficultyMenu && difficultyMenu.parent) difficultyMenu.parent.removeChild(difficultyMenu); startSpawnTimer(); } // Show menu at game start showDifficultyMenu(); // GUI var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var livesTxt = new Text2('♥♥♥', { size: 90, fill: 0xFF5252 }); livesTxt.anchor.set(1, 0); livesTxt.x = -40; // right padding LK.gui.topRight.addChild(livesTxt); // Prevent elements in top left 100x100 // (No elements added to gui.topLeft or at (0,0)) // Music LK.playMusic('bgmusic'); // Spawn a new item function spawnItem() { var type = pickItemType(); var item; item = new Item(); item.setType(type); // Assign per-item fall speed based on rarity/type // Default: base on global itemFallSpeed, then scale by rarity var speedMultiplier = 1; if (type.assetId === 'item_basic') speedMultiplier = 1;else if (type.assetId === 'item_rare') speedMultiplier = 1.18;else if (type.assetId === 'item_legend') speedMultiplier = 1.35;else if (type.assetId === 'item_bomb') speedMultiplier = 1.10;else if (type.assetId === 'item_spike') speedMultiplier = 1.22; item.fallSpeed = itemFallSpeed * speedMultiplier; // Random X, avoid edges, space out more as score increases var baseMargin = 120; var extraMargin = Math.min(260, Math.floor(score / 15) * 40); // +40px margin every 15 points, max +260 var margin = baseMargin + extraMargin; var x = margin + Math.random() * (2048 - 2 * margin); item.x = x; item.y = -100; // For touch detection item.width = LK.getAsset(type.assetId, { anchorX: 0.5, anchorY: 0.5 }).width; item.height = LK.getAsset(type.assetId, { anchorX: 0.5, anchorY: 0.5 }).height; // Make good items have a slightly larger hitbox (but smaller than before) if (!type.isBad) { item.width *= 1.15; item.height *= 1.15; } // Add to game game.addChild(item); items.push(item); // No pop-in animation item.scaleX = 1; item.scaleY = 1; // If this is a bomb, trigger the guy to throw if (type.assetId === 'item_bomb' && typeof guyBg !== "undefined" && guyBg.throwBomb) { guyBg.throwBomb(); } } // Update lives display function updateLives() { var s = ''; for (var i = 0; i < lives; i++) s += '♥'; livesTxt.setText(s); } // Handle tap function handleTap(x, y, obj) { // Find topmost item under tap for (var i = items.length - 1; i >= 0; i--) { var item = items[i]; // Simple bounding box check var dx = x - item.x; var dy = y - item.y; var w = item.width / 2; var h = item.height / 2; if (dx * dx / (w * w) + dy * dy / (h * h) <= 1.1) { // Tapped this item if (item.isTapped) continue; item.onTap(); if (item.isBad) { // Lose a life lives--; updateLives(); LK.getSound('bad').play(); LK.effects.flashScreen(0xff0000, 350); if (lives <= 0) { LK.getSound('lose').play(); LK.showGameOver(); return; } } else { // Score! score += item.scoreValue; LK.setScore(score); scoreTxt.setText(score); LK.getSound('score').play(); if (item.parent) item.parent.removeChild(item); } // Remove item from array items.splice(i, 1); break; } } } // Game move/tap handler game.down = function (x, y, obj) { handleTap(x, y, obj); // End hold on all hold items when released game.up = function (x, y, obj) {}; // Main update loop game.update = function () { // Animate GuyBackground if (guyBg && guyBg.update) guyBg.update(); // Move items for (var i = items.length - 1; i >= 0; i--) { var item = items[i]; item.y += typeof item.fallSpeed === "number" ? item.fallSpeed : itemFallSpeed; // If not tapped and off screen if (!item.isTapped && item.y > 2732 + 100) { // If good item missed, lose a life if (!item.isBad) { lives--; updateLives(); LK.getSound('life').play(); LK.effects.flashScreen(0xff9800, 250); if (lives <= 0) { LK.getSound('lose').play(); LK.showGameOver(); return; } } // Remove from game if (!item.isBad && !item.isTapped) { if (item.parent) item.parent.removeChild(item); } items.splice(i, 1); continue; } } }; // Difficulty ramp: every 10 points, increase speed and spawn rate var level = Math.floor(score / 10); var targetSpeed = 7 + level * itemSpeedInc; if (itemFallSpeed < targetSpeed) itemFallSpeed += 0.02; var targetInterval = Math.max(minSpawnInterval, 1000 - level * itemSpawnDec); if (spawnInterval > targetInterval) spawnInterval -= 1.5; }; // Spawn timer function startSpawnTimer() { if (spawnTimer) LK.clearInterval(spawnTimer); spawnTimer = LK.setInterval(function () { spawnItem(); // Adjust interval LK.clearInterval(spawnTimer); startSpawnTimer(); }, spawnInterval); } startSpawnTimer(); // Reset on game over LK.on('gameover', function () { // Clean up for (var i = 0; i < items.length; i++) { if (items[i].parent) items[i].parent.removeChild(items[i]); } items = []; // Show difficulty menu again showDifficultyMenu(); LK.playMusic('bgmusic'); }); // Reset on win (not used, but for completeness) LK.on('youwin', function () { for (var i = 0; i < items.length; i++) { if (items[i].parent) items[i].parent.removeChild(items[i]); } items = []; showDifficultyMenu(); LK.playMusic('bgmusic'); });
===================================================================
--- original.js
+++ change.js
@@ -5,45 +5,163 @@
/****
* Classes
****/
-// Animated background class
-var AnimatedBackground = Container.expand(function () {
+// GuyBackground class: draws a guy at the top, animates his arm, and throws bombs
+var GuyBackground = Container.expand(function () {
var self = Container.call(this);
- // Create several large, faint, colored ellipses for a soft animated effect
- var bgEllipses = [];
- var ellipseColors = [0x2e7d32, 0x1565c0, 0xffb300, 0x6d4c41, 0x8e24aa];
- var ellipseCount = 5;
- for (var i = 0; i < ellipseCount; i++) {
- var color = ellipseColors[i % ellipseColors.length];
- var ellipse = LK.getAsset('item_basic', {
- anchorX: 0.5,
- anchorY: 0.5
- });
- ellipse.width = 1200 + Math.random() * 700;
- ellipse.height = 700 + Math.random() * 600;
- ellipse.alpha = 0.10 + Math.random() * 0.10;
- ellipse.tint = color;
- ellipse.x = 2048 / 2 + Math.cos(i * 2 * Math.PI / ellipseCount) * 600;
- ellipse.y = 2732 / 2 + Math.sin(i * 2 * Math.PI / ellipseCount) * 700;
- self.addChild(ellipse);
- bgEllipses.push(ellipse);
- }
- // Animate ellipses with slow drifting, scaling, and rotation
+ // Body
+ var body = LK.getAsset('item_basic', {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ body.width = 320;
+ body.height = 420;
+ body.x = 2048 / 2;
+ body.y = 320;
+ body.alpha = 0.93;
+ body.tint = 0x8d5524;
+ self.addChild(body);
+ // Head
+ var head = LK.getAsset('item_basic', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ head.width = 210;
+ head.height = 210;
+ head.x = body.x;
+ head.y = body.y - body.height + 90;
+ head.alpha = 1;
+ head.tint = 0xf1c27d;
+ self.addChild(head);
+ // Eyes
+ var eyeL = LK.getAsset('item_rare', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ eyeL.width = 28;
+ eyeL.height = 28;
+ eyeL.x = head.x - 38;
+ eyeL.y = head.y - 18;
+ eyeL.tint = 0x222222;
+ self.addChild(eyeL);
+ var eyeR = LK.getAsset('item_rare', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ eyeR.width = 28;
+ eyeR.height = 28;
+ eyeR.x = head.x + 38;
+ eyeR.y = head.y - 18;
+ eyeR.tint = 0x222222;
+ self.addChild(eyeR);
+ // Smile
+ var smile = LK.getAsset('item_legend', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ smile.width = 60;
+ smile.height = 22;
+ smile.x = head.x;
+ smile.y = head.y + 38;
+ smile.tint = 0x6d4c41;
+ smile.alpha = 0.7;
+ self.addChild(smile);
+ // Left arm (static, for balance)
+ var armL = LK.getAsset('item_basic', {
+ anchorX: 0.5,
+ anchorY: 0.1
+ });
+ armL.width = 60;
+ armL.height = 170;
+ armL.x = body.x - 110;
+ armL.y = body.y - 220;
+ armL.rotation = -Math.PI / 4.5;
+ armL.tint = 0xf1c27d;
+ armL.alpha = 0.93;
+ self.addChild(armL);
+ // Right arm (throws bombs)
+ var armR = LK.getAsset('item_basic', {
+ anchorX: 0.5,
+ anchorY: 0.1
+ });
+ armR.width = 60;
+ armR.height = 170;
+ armR.x = body.x + 110;
+ armR.y = body.y - 220;
+ armR.tint = 0xf1c27d;
+ armR.alpha = 0.93;
+ self.addChild(armR);
+ // Hand (right)
+ var handR = LK.getAsset('item_legend', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ handR.width = 54;
+ handR.height = 54;
+ handR.x = armR.x;
+ handR.y = armR.y + armR.height - 18;
+ handR.tint = 0xf1c27d;
+ handR.alpha = 0.98;
+ self.addChild(handR);
+ // Bomb in hand (only visible when about to throw)
+ var bomb = LK.getAsset('item_bomb', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ bomb.width = 60;
+ bomb.height = 60;
+ bomb.x = handR.x;
+ bomb.y = handR.y - 10;
+ bomb.visible = false;
+ self.addChild(bomb);
+ // Animation state
+ self.armThrowing = false;
+ self.armThrowTimer = 0;
+ self.armThrowDuration = 32; // frames
+ self.lastThrowTick = 0;
+ // For bomb throw event
+ self.onBombThrow = null;
+ // Animate arm and bomb
self.update = function () {
- for (var i = 0; i < bgEllipses.length; i++) {
- var e = bgEllipses[i];
- // Gentle drifting
- e.x += Math.sin(LK.ticks / (400 + i * 80)) * 0.3;
- e.y += Math.cos(LK.ticks / (350 + i * 60)) * 0.2;
- // Gentle scale pulse
- var baseScale = 1 + 0.04 * Math.sin(LK.ticks / (180 + i * 40));
- e.scaleX = baseScale;
- e.scaleY = baseScale;
- // Gentle rotation
- e.rotation = Math.sin(LK.ticks / (600 + i * 100)) * 0.08;
+ // Arm idle: gentle up/down
+ var idleAngle = Math.PI / 4.5 + Math.sin(LK.ticks / 40) * 0.08;
+ var throwAngle = -Math.PI / 1.2;
+ if (!self.armThrowing) {
+ armR.rotation = idleAngle;
+ bomb.visible = false;
+ } else {
+ // Animate throw: swing up, then down
+ var t = self.armThrowTimer / self.armThrowDuration;
+ if (t < 0.45) {
+ // Wind up
+ armR.rotation = idleAngle + (throwAngle - idleAngle) * (t / 0.45);
+ } else {
+ // Snap down
+ armR.rotation = throwAngle + (idleAngle - throwAngle) * ((t - 0.45) / 0.55);
+ }
+ bomb.visible = self.armThrowTimer < self.armThrowDuration * 0.7;
+ // Bomb follows hand
+ bomb.x = handR.x + Math.sin(armR.rotation) * (armR.height - 18);
+ bomb.y = handR.y + Math.cos(armR.rotation) * (armR.height - 18) - 10;
+ if (self.armThrowTimer === Math.floor(self.armThrowDuration * 0.7) && typeof self.onBombThrow === "function") {
+ // Throw bomb now!
+ self.onBombThrow(bomb.x, bomb.y);
+ }
+ self.armThrowTimer++;
+ if (self.armThrowTimer >= self.armThrowDuration) {
+ self.armThrowing = false;
+ self.armThrowTimer = 0;
+ }
}
};
+ // Call to trigger a throw
+ self.throwBomb = function () {
+ if (!self.armThrowing) {
+ self.armThrowing = true;
+ self.armThrowTimer = 0;
+ }
+ };
return self;
});
// Item class for all falling items
var Item = Container.expand(function () {
@@ -258,12 +376,41 @@
/****
* Game Code
****/
-// Add animated background behind everything
-var animatedBg = new AnimatedBackground();
-game.addChild(animatedBg);
-game.setChildIndex(animatedBg, 0); // Ensure it's at the back
+// Add GuyBackground behind everything
+var guyBg = new GuyBackground();
+game.addChild(guyBg);
+game.setChildIndex(guyBg, 0); // Ensure it's at the back
+// Helper: find the next bomb item to spawn, or null if none
+function findNextBombItemIndex() {
+ for (var i = 0; i < items.length; i++) {
+ if (items[i].assetId === 'item_bomb' && !items[i].isTapped && items[i].y < 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+// Set up bomb throw callback
+guyBg.onBombThrow = function (bx, by) {
+ // Find the next bomb item that hasn't appeared yet (y < 0)
+ var idx = findNextBombItemIndex();
+ if (idx >= 0) {
+ var bombItem = items[idx];
+ // Animate bombItem from guy's hand to its spawn X,Y
+ bombItem.x = bx;
+ bombItem.y = by;
+ // Animate bomb flying down to its normal spawn Y
+ var targetY = -100;
+ var targetX = bombItem.x;
+ tween(bombItem, {
+ y: targetY
+ }, {
+ duration: 180,
+ easing: tween.cubicIn
+ });
+ }
+};
// spike: keep as box, but will add visual in class
// rare: blue, slightly smaller
// legend: larger, gold
// bomb: dark ellipse
@@ -490,8 +637,12 @@
items.push(item);
// No pop-in animation
item.scaleX = 1;
item.scaleY = 1;
+ // If this is a bomb, trigger the guy to throw
+ if (type.assetId === 'item_bomb' && typeof guyBg !== "undefined" && guyBg.throwBomb) {
+ guyBg.throwBomb();
+ }
}
// Update lives display
function updateLives() {
var s = '';
@@ -543,10 +694,10 @@
// End hold on all hold items when released
game.up = function (x, y, obj) {};
// Main update loop
game.update = function () {
- // Animate background
- if (animatedBg && animatedBg.update) animatedBg.update();
+ // Animate GuyBackground
+ if (guyBg && guyBg.update) guyBg.update();
// Move items
for (var i = items.length - 1; i >= 0; i--) {
var item = items[i];
item.y += typeof item.fallSpeed === "number" ? item.fallSpeed : itemFallSpeed;