User prompt
knockthem back much further away
User prompt
somethings wrong with the knockback ennemies, they are all slanted
User prompt
use the same knockback effect as big bob
User prompt
do it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
reduce it to 150 pixels
User prompt
reduce the squash and stretch effect on schmart ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
schmart spawns too frequently
User prompt
i don't like it when schmarts gets knockbacked that the asset rotates
User prompt
reduce the exagerate effect of the knockback on schmart
User prompt
add some weight to schmart, he feels too light
User prompt
schmart is twice the size of bigbob, it should be reflected in its animation and knockback NOT IN ITS DEATH ANIMATION
User prompt
there are sometimes multiple schmarts spawned at the same time, this is a big, it should be limited to only one
User prompt
don't flash the screen when schmart spawns
User prompt
reduce schmarts health to 8
User prompt
shchmart moves too quickly, reduce his speed
User prompt
schmarts knockback rotation animation is too exagerated, reduce it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
the jump attack should not work on schmart
User prompt
schmart should knockback it doesn't, fix it
User prompt
fix it
User prompt
add a failsafe to spawn schmart because it doesn't spawn
Code edit (1 edits merged)
Please save this source code
User prompt
Remove the duplicate lines at the bottom of your file (the second var enemies = []; and the extra LK.setInterval(...)) so you have a single, clear spawn loop with a single enemy pool.
User prompt
schmart spawning logic should be seperated from bigbobs,
User prompt
fix it
User prompt
reduce the knockback effect on schmart
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Shape = Container.expand(function (options) { var self = Container.call(this); self.attachAsset('shape', { width: options.width, height: options.height, anchorX: options.anchorX || 0, anchorY: options.anchorY || 0, color: options.color || 0x66ff00, alpha: typeof options.alpha === 'number' ? options.alpha : 0 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Show the "Ready" screen at the beginning. // Standard shapes, images, and sounds. // Ready screen // Background // NEW: Bigbob enemy asset. // Note: Use a unique key ("bigbob") so that it doesn’t conflict with enemy01. // Other assets (you may use enemy01 for normal enemies) // Sounds and music. function showReadyScreen() { var ready = LK.getAsset('Ready', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); ready.zIndex = 10000; game.addChild(ready); ready.alpha = 0.9; ready.scaleX = 1; ready.scaleY = 1; LK.setTimeout(function () { tween(ready, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { ready.destroy(); } }); }, 2000); } // Begin Game Setup var bg01 = LK.getAsset('bg01', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); game.addChild(bg01); showReadyScreen(); // Guaranteed spawn of first Schmart after 5 seconds LK.setTimeout(function () { spawnSchmart(); }, 5000); // Guard variable for game over. var gameOverTriggered = false; // Helper to create shadowed text. function createShadowedText(message, size, mainColor) { var shadow = new Text2(message, { size: size, fill: 0x000000, fontFamily: "Arial", align: "center" }); shadow.anchor.set(0.5); shadow.x = 4; shadow.y = 4; var main = new Text2(message, { size: size, fill: mainColor, fontFamily: "Arial", align: "center" }); main.anchor.set(0.5); var container = new Container(); container.addChild(shadow); container.addChild(main); return container; } function showCustomGameOver() { var gameOverContainer = new Container(); gameOverContainer.name = "gameOverContainer"; gameOverContainer.sortableChildren = true; var finalScoreContainer = createShadowedText("You Lost\nFinal Score: " + score, 150, 0xFFFFFF); finalScoreContainer.x = 1024; finalScoreContainer.y = 2066; finalScoreContainer.anchorX = 0.5; finalScoreContainer.anchorY = 0.5; gameOverContainer.addChild(finalScoreContainer); scoreTxt.visible = false; LK.getSound('awww').play(); game.down = function () {}; game.up = function () {}; game.addChild(gameOverContainer); LK.setTimeout(function () { LK.showGameOver(); }, 5000); } // HELP MENU setup. var helpButtonShadow = new Container(); helpButtonShadow.attachAsset('helpbutton', { anchorX: 0.0, anchorY: 0.0, x: 50, y: 260, tint: 0x000000, alpha: 0.8 }); LK.gui.topLeft.addChild(helpButtonShadow); var helpButton = LK.getAsset('helpbutton', { anchorX: 0.0, anchorY: 0.0, x: 40, y: 250, tint: 0xFFFFFF }); LK.gui.topLeft.addChild(helpButton); helpButton.down = function () { var menuPage = new Container(); menuPage.name = "menuPageContainer"; menuPage.sortableChildren = true; var menupageImage = menuPage.attachAsset('menupage', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); menuPage.x = 1024; menuPage.y = 1300; game.addChild(menuPage); var controlsText = new Text2("Controls:\n\nMelee [Left/Right] Tap\nRange [Hold Press]\nJump [Up] Tap \n Tap to Collect Coins", { size: 100, fill: 0x000000, fontFamily: "Garamond", align: "center" }); controlsText.name = "controlsText"; controlsText.anchor.set(0.5, 0.5); controlsText.x = 0; controlsText.y = -(menupageImage.height / 2) + 500; controlsText.zIndex = 9999; menuPage.addChild(controlsText); game.paused = true; menuPage.down = function () { game.paused = false; game.removeChild(menuPage); }; }; function findChildByName(container, name) { for (var i = 0; i < container.children.length; i++) { if (container.children[i].name === name) { return container.children[i]; } } return null; } /**** * Global Variables ****/ var helmetMeter = 0; var helmetMeterMax = 125; var jumpColGlobal = null; var isPressHeld = false; var pressHoldStartTime = 0; var pressDownX = 0; var pressDownY = 0; var mouseX = 0; var mouseY = 0; var schmartSpawnTimer = null; game.move = function (x, y) { mouseX = x; mouseY = y; }; var projectiles = []; var score = 0; var scoreTxt; function updateScoreDisplay() { if (gameOverTriggered) { if (scoreTxt) { scoreTxt.visible = false; } return; } if (score > highScore) { highScore = score; storage.highScore = highScore; highScoreTxt.setText('High Score: ' + highScore); } game.removeChild(scoreTxt); scoreTxt = createScoreText(score); scoreTxt.scaleX = 1.0; scoreTxt.scaleY = 1.0; game.addChild(scoreTxt); tween(scoreTxt, { scaleX: 1.5, scaleY: 1.5 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(scoreTxt, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, easing: tween.easeIn }); } }); } function createScoreText(value) { var shadow = new Text2(String(value), { size: 600, fill: 0x000000, fontFamily: "Arial" }); shadow.name = "shadow"; shadow.anchor.set(0.5, 0); shadow.x = 4; shadow.y = 4; var main = new Text2(String(value), { size: 600, fill: 0xFF69B4, fontFamily: "Arial" }); main.name = "main"; main.anchor.set(0.5, 0); var container = new Container(); container.name = "scoreTxt"; container.x = 1024; container.y = 50; container.addChild(shadow); container.addChild(main); return container; } scoreTxt = createScoreText(score); scoreTxt.scaleX = 1.0; scoreTxt.scaleY = 1.0; LK.playMusic('bgm', { loop: true }); var highScore = storage.highScore || 0; var highScoreTxt = new Text2('High Score: ' + highScore, { size: 50, fill: 0xFFFFFF }); highScoreTxt.name = 'highScoreTxt'; highScoreTxt.anchor.set(1, 1); highScoreTxt.x = 1900; highScoreTxt.y = 2720; game.addChild(highScoreTxt); /**** * HUD: Helmet and Valkbar ****/ var hudContainer = new Container(); hudContainer.name = "hudContainer"; hudContainer.sortableChildren = true; game.addChild(hudContainer); var valkbar = LK.getAsset('valkbar', { anchorX: 1.0, anchorY: 0.5, x: 2235 - 205, y: 305 }); valkbar.zIndex = 0; hudContainer.addChild(valkbar); var powerHelmet = new Container(); powerHelmet.name = "powerHelmet"; var helmetSprite = powerHelmet.attachAsset('helmet', { anchorX: 0.5, anchorY: 0.5 }); powerHelmet.x = 2048 - helmetSprite.width / 2 - 20; powerHelmet.y = 170; powerHelmet.zIndex = 10; var helmetFillContainer = new Container(); helmetFillContainer.name = "helmetFillContainer"; var fillBar = new Shape({ width: helmetSprite.width * 0.05, height: 40, color: 0xFFFFFF, alpha: 1 }); fillBar.anchorX = 0; fillBar.anchorY = 0.5; fillBar.x = -helmetSprite.width / 2; fillBar.y = helmetSprite.height / 2 - 5; helmetFillContainer.addChild(fillBar); powerHelmet.addChild(helmetFillContainer); hudContainer.addChild(powerHelmet); function updateHelmetDisplay() { var fraction = helmetMeter / helmetMeterMax; if (helmetMeter <= 0) { fillBar.visible = false; } else { fillBar.visible = true; if (fraction > 1) { fraction = 1; } fillBar.width = fraction * helmetSprite.width; } } /**** * Petals ****/ var petals = []; for (var i = 0; i < 50; i++) { var petal = new Container(); petal.attachAsset('petals', { anchorX: 0.5, anchorY: 0.5, rotation: Math.random() * Math.PI * 2 }); petal.x = Math.random() * 2048; petal.y = Math.random() * 2732; petal.speedY = Math.random() * 2 + 1; petal.speedX = Math.random() * 2 - 1; petal.update = function () { this.y += this.speedY; this.x += this.speedX; if (this.y > 2732) { this.y = -50; this.x = Math.random() * 2048; } }; petals.push(petal); game.addChild(petal); } /**** * Player Setup with Custom Collision ****/ var player = new Container(); var visualContainer = new Container(); visualContainer.name = 'visual'; var playerSprite = visualContainer.attachAsset('player_idle', { anchorX: 0.5, anchorY: 0.5 }); player.addChild(visualContainer); player.x = 1024; player.y = 2732 - 250; game.addChild(player); var idleCollision = player.attachAsset('shape', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 120, alpha: 0 }); idleCollision.name = 'idleCollision'; /**** * Idle Animations ****/ function startBreathingAnimation() { tween(player, { scaleX: 1.05, scaleY: 1.05 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(player, { scaleX: 1.0, scaleY: 1.0 }, { duration: 1000, easing: tween.easeInOut, onFinish: startBreathingAnimation }); } }); } function startTiltAnimation() { tween(player, { rotation: Math.PI / 32 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(player, { rotation: -Math.PI / 32 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(player, { rotation: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: startTiltAnimation }); } }); } }); } startBreathingAnimation(); startTiltAnimation(); /**** * Attack Collider ****/ var attackCol = LK.getAsset('attackcol', { anchorX: 0.5, anchorY: 0.5, alpha: 0.75 }); game.addChild(attackCol); attackCol.visible = false; attackCol.alpha = 0; /**** * Power-Up: Helmet HUD & Special ****/ var featherEffects = []; function spawnFeatherMove() { if (!specialIdleActive) { return; } for (var i = -2; i <= 2; i++) { var feather = new Container(); feather.attachAsset('feather', { anchorX: 0.5, anchorY: 0.5 }); feather.x = player.x + i * 50; feather.y = player.y; game.addChild(feather); featherEffects.push(feather); tween(feather, { x: feather.x + i * 500, y: feather.y + (Math.random() * 200 - 100), alpha: 0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { feather.destroy(); } }); } } var helmetActive = false; var specialIdleActive = false; /* NEW: In activateHelmetPowerUp() the warcry sound is played once. */ function activateHelmetPowerUp() { if (helmetActive) { return; } helmetActive = true; swapPlayerVisual('special_idle', player.x, player.y, visualContainer.scaleX); specialIdleActive = true; LK.getSound('warcry').play(); LK.effects.flashScreen(0xFFFFFF, 100); var shakeIntensity = 10, shakeDuration = 500; var shakeStartTime = Date.now(); var originalPosition = { x: game.x, y: game.y }; function shakeScreen() { var elapsed = Date.now() - shakeStartTime; if (elapsed < shakeDuration) { var offsetX = (Math.random() - 0.5) * shakeIntensity; var offsetY = (Math.random() - 0.5) * shakeIntensity; game.x = originalPosition.x + offsetX; game.y = originalPosition.y + offsetY; LK.setTimeout(shakeScreen, 16); } else { game.x = originalPosition.x; game.y = originalPosition.y; } } shakeScreen(); spawnFeatherMove(); LK.setTimeout(spawnFeatherMove, 1500); LK.setTimeout(spawnFeatherMove, 3000); LK.setTimeout(function () { while (featherEffects.length) { featherEffects.pop().destroy(); } specialIdleActive = false; if (!isJumping) { swapPlayerVisual('player_idle', player.x, player.y, visualContainer.scaleX, function () { startBreathingAnimation(); startTiltAnimation(); }); } LK.effects.flashScreen(0xFFFFFF, 100); helmetActive = false; helmetMeter = 0; updateHelmetDisplay(); }, 4000); } /**** * Spawning Enemies * Now, sometimes spawn a “bigbob” enemy. ****/ function spawnEnemy() { if (game.paused) { return; } // Count how many BigBobs and Schmarts are currently active var activeBigBobs = 0; var activeSchmarts = 0; for (var i = 0; i < enemies.length; i++) { if (enemies[i].isSchmarts === true) { activeSchmarts++; } else if (enemies[i].isBigBob) { activeBigBobs++; } } console.log("Active Schmarts:", activeSchmarts); // Set or reset Schmart spawn timer if no Schmarts are active if (activeSchmarts === 0 && !schmartSpawnTimer) { schmartSpawnTimer = LK.setTimeout(function () { spawnSchmart(); schmartSpawnTimer = null; }, 15000); // Force spawn a Schmart after 15 seconds if none exist } // Roll dice for which enemy type to spawn var randomValue = Math.random(); // Spawn Schmart with 10% chance if no Schmarts are active if (randomValue < 0.10 && activeSchmarts < 1) { spawnSchmart(); } // Separate roll for Bigbob spawning else if (Math.random() < 0.20 && activeBigBobs < 2) { spawnBigBob(); } else { spawnRegularEnemy(); } } // Separate function for spawning Schmart enemies function spawnSchmart() { // First check if a Schmart enemy already exists var schmartExists = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i].isSchmarts === true) { schmartExists = true; break; } } // Don't spawn if one already exists if (schmartExists) { console.log("Attempted to spawn Schmart but one already exists"); return; } // Clear the Schmart spawn timer if it exists if (schmartSpawnTimer) { LK.clearTimeout(schmartSpawnTimer); schmartSpawnTimer = null; } var _bounce = function bounce() { tween(enemy, { y: baseY - 30, // Reduced bounce height to simulate heaviness scaleX: 0.92, // Less squash when stretching upward - feels heavier scaleY: 1.08 // Less stretch upward - feels heavier }, { duration: 700, // Slower animation for heavier feel easing: tween.easeInOut, // Changed from bounceInOut to easeInOut for heavier feel onFinish: function onFinish() { tween(enemy, { y: baseY, scaleX: 1.08, // Slightly wider when squashing at bottom scaleY: 0.92 // Slightly shorter when squashing at bottom }, { duration: 700, // Slower animation for heavier feel easing: tween.easeInOut, // Changed from bounceInOut to easeInOut for heavier feel onFinish: function onFinish() { // Return to normal scale before starting next bounce cycle tween(enemy, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200, // Slightly longer pause before next bounce cycle onFinish: _bounce }); } }); } }); }; var enemy = new Container(); enemy.isBigBob = false; enemy.isSchmarts = true; enemy.health = 8; // Schmarts now takes 8 hits to die // Add more mass/weight to Schmart enemy.mass = 3; // Higher mass makes it feel heavier var gfx = enemy.attachAsset('shmarts', { anchorX: 0.5, anchorY: 0.5, alpha: 1 // Set fully opaque alpha }); var fromLeft = Math.random() < 0.5; // Start Schmart closer to the visible area of the screen enemy.x = fromLeft ? -gfx.width / 4 : 2048 + gfx.width / 4; enemy.y = 2732 - 400; // Move Schmart spawning position higher on screen // Reduce Schmart speed to make it move more slowly enemy.speedX = fromLeft ? Math.random() * 1.2 + 0.8 : -(Math.random() * 1.2 + 0.8); // Even slower to feel heavier enemy.originalSpeedX = enemy.speedX; // Save original speed. gfx.scaleX = fromLeft ? 1 : -1; // Flip Schmarts asset if coming from the right var baseY = enemy.y; // Debug message to confirm Schmart spawning without flashing the screen console.log("Schmart spawned at:", enemy.x, enemy.y); _bounce(); enemies.push(enemy); game.addChild(enemy); } // Separate function for spawning BigBob enemies function spawnBigBob() { var _bounce = function bounce() { tween(enemy, { y: baseY - 50, scaleX: 0.9, // Slightly thinner when stretching upward scaleY: 1.1 // Slightly taller when stretching upward }, { duration: 500, easing: tween.bounceInOut, onFinish: function onFinish() { tween(enemy, { y: baseY, scaleX: 1.1, // Slightly wider when squashing at bottom scaleY: 0.9 // Slightly shorter when squashing at bottom }, { duration: 500, easing: tween.bounceInOut, onFinish: function onFinish() { // Return to normal scale before starting next bounce cycle tween(enemy, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: _bounce }); } }); } }); }; var enemy = new Container(); enemy.isBigBob = true; enemy.isSchmarts = false; enemy.health = 3; // Takes three hits to die. Always set to 3. var gfx = enemy.attachAsset('bigbob', { anchorX: 0.5, anchorY: 0.5, alpha: 1 // Set fully opaque alpha }); var fromLeft = Math.random() < 0.5; enemy.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2; enemy.y = 2732 - 250; // Move spawning position lower on screen // Bigbob is slower: speed between 1 and 3. enemy.speedX = fromLeft ? Math.random() * 2 + 1 : -(Math.random() * 2 + 1); enemy.originalSpeedX = enemy.speedX; // Save original speed. gfx.scaleX = fromLeft ? 1 : -1; // Flip Bigbob's asset if coming from the right var baseY = enemy.y; _bounce(); enemies.push(enemy); game.addChild(enemy); } // Separate function for spawning regular enemies function spawnRegularEnemy() { var _bounce2 = function bounce() { tween(enemy, { y: baseY - 50, scaleX: 0.9, // Slightly thinner when stretching upward scaleY: 1.1 // Slightly taller when stretching upward }, { duration: 500, easing: tween.bounceInOut, onFinish: function onFinish() { tween(enemy, { y: baseY, scaleX: 1.1, // Slightly wider when squashing at bottom scaleY: 0.9 // Slightly shorter when squashing at bottom }, { duration: 500, easing: tween.bounceInOut, onFinish: function onFinish() { // Return to normal scale before starting next bounce cycle tween(enemy, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: _bounce2 }); } }); } }); }; // Spawn regular enemy. var enemy = new Container(); enemy.isBigBob = false; enemy.isSchmarts = false; var hitbox = new Shape({ width: 200, height: 209, anchorX: 0.5, anchorY: 0.5, color: 0x00FF00, alpha: 0 }); hitbox.x = 0; hitbox.y = 0; enemy.addChild(hitbox); var gfx = enemy.attachAsset('enemy01', { anchorX: 0.5, anchorY: 0.5 }); var fromLeft = Math.random() < 0.5; enemy.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2; enemy.y = 2732 - 205; // Move spawning position lower enemy.speedX = fromLeft ? Math.random() * 6 + 2 : -(Math.random() * 6 + 2); if (Math.abs(enemy.speedX) >= 6) { gfx.tint = 0xFF0000; gfx.scaleX *= 0.85; gfx.scaleY *= 0.85; } else if (Math.abs(enemy.speedX) <= 3) { gfx.tint = 0x0000FF; } gfx.scaleX = fromLeft ? 1 : -1; var baseY = enemy.y; _bounce2(); enemies.push(enemy); game.addChild(enemy); } function spawnShield() { // (Spawn shield enemy code remains unchanged) if (game.paused) { return; } var shield = new Container(); var hitbox = new Shape({ width: 200, height: 209, anchorX: 0.5, anchorY: 0.5, color: 0x00FF00, alpha: 0 }); hitbox.x = 0; hitbox.y = 0; shield.addChild(hitbox); var gfx = shield.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5 }); var fromLeft = Math.random() < 0.5; shield.x = fromLeft ? -gfx.width / 2 : 2048 + gfx.width / 2; shield.y = 2732 - 205; shield.speedX = fromLeft ? Math.random() * 6 + 2 : -(Math.random() * 6 + 2); shield.isShield = true; gfx.tint = 0xFFD700; gfx.scaleX = fromLeft ? 1 : -1; var baseY = shield.y; function bounce() { tween(shield, { y: baseY - 50, scaleX: 0.9, // Slightly thinner when stretching upward scaleY: 1.1 // Slightly taller when stretching upward }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(shield, { y: baseY, scaleX: 1.1, // Slightly wider when squashing at bottom scaleY: 0.9 // Slightly shorter when squashing at bottom }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { // Return to normal scale before starting next bounce cycle tween(shield, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100, onFinish: bounce }); } }); } }); } bounce(); enemies.push(shield); game.addChild(shield); } var enemySpawnInterval = Math.random() * 3000 + 2000; var shieldSpawnInterval = 20000; LK.setInterval(spawnEnemy, enemySpawnInterval); LK.setInterval(spawnShield, shieldSpawnInterval); /**** * Swap Player Sprite Function ****/ function swapPlayerVisual(newVisualId, x, y, flip, onDone) { if (specialIdleActive && newVisualId !== 'special_idle') { return; } var visualContainer = player.findChildByName('visual'); if (!visualContainer) { visualContainer = new Container(); visualContainer.name = 'visual'; player.addChild(visualContainer); } else { visualContainer.removeChildAt(0); } playerSprite = visualContainer.attachAsset(newVisualId, { anchorX: 0.5, anchorY: 0.5, y: newVisualId === 'special_idle' ? -100 : 0, scaleX: newVisualId === 'special_idle' ? 1.25 : 1, scaleY: newVisualId === 'special_idle' ? 1.25 : 1 }); visualContainer.scaleX = flip; player.x = x; player.y = y; if (newVisualId === 'player_jump') { flip = Math.random() < 0.5 ? -1 : 1; visualContainer.scaleX = flip; jumpColGlobal = LK.getAsset('jumpcol', { anchorX: 0.5, anchorY: 0.5, x: x, y: y + player.height / 2, alpha: 0 }); game.addChild(jumpColGlobal); tween(jumpColGlobal, { y: jumpColGlobal.y - 600 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(jumpColGlobal, { y: 2732 - 250 + player.height / 2 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { jumpColGlobal.destroy(); jumpColGlobal = null; } }); } }); } if (typeof onDone === 'function') { if (newVisualId === 'player_idle') { startBreathingAnimation(); startTiltAnimation(); } onDone(); } } /**** * Input Logic ****/ var isSequenceRunning = false; var isJumping = false; var playerState = 'idle'; game.down = function (x, y) { if (game.paused) { return; } if (isSequenceRunning || specialIdleActive) { return; } isPressHeld = true; pressHoldStartTime = Date.now(); pressDownX = x; pressDownY = y; if (y < 2732 * 2.2 / 3 && !isJumping) { isJumping = true; LK.getSound('hup').play(); swapPlayerVisual('player_jump', player.x, player.y); for (var i = 0; i < 10; i++) { var p = LK.getAsset('dust', { anchorX: 0.5, anchorY: 0.5, x: player.x + (Math.random() * 100 - 50), y: player.y + (Math.random() * 100 - 50) }); game.addChild(p); tween(p, { alpha: 0, x: p.x + (Math.random() * 200 - 100), y: p.y - Math.random() * 200 }, { duration: 500, onFinish: function onFinish() { p.destroy(); } }); } tween(player, { y: player.y - 600 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(player, { y: 2732 - 250 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { for (var j = 0; j < 10; j++) { var pp = LK.getAsset('dust', { anchorX: 0.5, anchorY: 0.5, x: player.x + (Math.random() * 100 - 50), y: player.y + (Math.random() * 100 - 50) }); game.addChild(pp); tween(pp, { alpha: 0, x: pp.x + (Math.random() * 200 - 100), y: pp.y + Math.random() * 200 }, { duration: 500, onFinish: function onFinish() { pp.destroy(); } }); } isJumping = false; var landingFlip = Math.random() < 0.5 ? -1 : 1; if (specialIdleActive) { swapPlayerVisual('special_idle', 1024, 2732 - 250, landingFlip); } else { swapPlayerVisual('player_idle', 1024, 2732 - 250, landingFlip, function () { startBreathingAnimation(); startTiltAnimation(); }); } var v = player.findChildByName('visual'); if (v) { var dir = v.scaleX < 0 ? -1 : 1; tween(v, { scaleX: dir * 1.3, scaleY: 1.3 }, { duration: 30, onFinish: function onFinish() { tween(v, { scaleX: dir * 1.0, scaleY: 1.0 }, { duration: 60 }); } }); } } }); } }); return; } isSequenceRunning = true; var flip = x < 1024 ? -1 : 1; swapPlayerVisual('player_attackf01', 1024, 2732 - 250, flip); LK.getSound('retroslash').play(); var vis = player.findChildByName('visual'); if (vis) { tween(vis, { scaleX: flip * 1.3, scaleY: 1.3 }, { duration: 30, onFinish: function onFinish() { tween(vis, { scaleX: flip * 1.0, scaleY: 1.0 }, { duration: 60 }); } }); } LK.setTimeout(function () { swapPlayerVisual('player_attackf02', 1024, 2732 - 250, flip); attackCol.width = 180; attackCol.height = 180; attackCol.x = flip === -1 ? 874 : 1174; attackCol.y = 2732 - 250; attackCol.scaleX = flip; attackCol.visible = true; LK.setTimeout(function () { if (attackCol) { attackCol.visible = false; } if (!specialIdleActive) { swapPlayerVisual('player_idle', 1024, 2732 - 250, flip, function () { startBreathingAnimation(); startTiltAnimation(); }); } isSequenceRunning = false; playerState = 'idle'; }, 150); }, 150); }; /**** * Spawning Enemies & Shields ****/ var enemies = []; LK.setInterval(spawnEnemy, enemySpawnInterval); LK.setInterval(spawnShield, shieldSpawnInterval); /**** * Projectile Logic (Throw Attack) ****/ function spawnProjectile(targetX, targetY) { var flip = targetX < player.x ? -1 : 1; swapPlayerVisual('player_attackf01', player.x, player.y, flip); var proj = new Container(); proj.attachAsset('player_throw', { anchorX: 0.5, anchorY: 0.5 }); LK.getSound('throwsnd').play(); proj.x = player.x; proj.y = player.y; var cloudSmoke = LK.getAsset('cloudsmoke', { anchorX: 0.5, anchorY: 0.5, x: proj.x, y: proj.y, alpha: 0.75 }); game.addChild(cloudSmoke); tween(cloudSmoke, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { cloudSmoke.destroy(); } }); var dx = targetX - player.x, dy = targetY - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist !== 0) { dx /= dist; dy /= dist; } var speed = 40; proj.vx = dx * speed; proj.vy = dy * speed; proj.scaleX = targetX < player.x ? -1 : 1; proj.distanceTraveled = 0; proj.maxDistance = 1000; projectiles.push(proj); game.addChild(proj); LK.setTimeout(function () { swapPlayerVisual('player_idle', player.x, player.y, flip, function () { startBreathingAnimation(); startTiltAnimation(); }); }, 300); } /**** * Coins ****/ var coins = []; function dropCoin(x, y) { var rand = Math.random(); if (rand < 0.5) { var coin = new Container(); coin.type = 'silver'; coin.attachAsset('silver_coin', { anchorX: 0.5, anchorY: 0.5 }); coin.x = x; coin.y = y; game.addChild(coin); coins.push(coin); loopCoinTween(coin, y); } else if (rand < 0.6) { var coin = new Container(); coin.type = 'gold'; coin.attachAsset('gold_coin', { anchorX: 0.5, anchorY: 0.5 }); coin.x = x; coin.y = y; game.addChild(coin); coins.push(coin); loopCoinTween(coin, y); } } /**** * Looping Tween Functions ****/ function loopCoinTween(coin, baseY) { tween(coin, { y: baseY - 20 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(coin, { y: baseY + 20 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { loopCoinTween(coin, baseY); } }); } }); } /**** * Enemy Hit Logic – Also fills the helmet meter * NEW: For bigbob enemies, subtract health each hit. If health > 0, perform a knockback tween; * if health reaches 0, perform a death tween. ****/ function handleEnemyHit(enemy, index, attackType) { if (!enemies.includes(enemy) || enemy.hit) { return; } if (enemy.isShield) { if (attackType === 'throw') { return; } if (attackType === 'melee') { // Shield is hit by melee, knock it back enemy.hit = true; // Prevent multiple hits // Calculate knockback direction based on player position var knockbackDistance = 300; var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance; // Play sound effect LK.getSound('boing').play(); // Knock shield back with tween tween(enemy, { x: newX, rotation: enemy.x < player.x ? -Math.PI / 4 : Math.PI / 4, tint: 0xFFFFFF // Flash }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Reset after knockback tween(enemy, { rotation: 0, tint: 0xFFD700 // Reset to gold tint }, { duration: 200, onFinish: function onFinish() { enemy.hit = false; // Allow hitting again } }); } }); return; // Exit the function after handling shield knockback } } // If this enemy is Bigbob or Schmart, handle multi-hit and knockback. if (enemy.isBigBob || enemy.isSchmarts) { // Always log Schmart hit for debugging if (enemy.isSchmarts) { console.log("Hit Schmart! Health before:", enemy.health); } enemy.health -= 1; // Temporary mark as hit so multiple rapid hits are prevented. enemy.hit = true; if (enemy.health > 0) { // Knockback: move enemy away from the player. // Make knockback distance appropriate for each enemy type // Account for enemy mass if defined - heavier enemies get less knockback var mass = enemy.mass || 1; var knockbackDistance = enemy.isSchmarts ? Math.floor(200 / mass) : 150; var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance; // Temporarily store original speed to restore after knockback var originalSpeed = enemy.speedX; // Reverse direction briefly for knockback effect - reduced by mass enemy.speedX = enemy.speedX * (-0.5 / mass); // Play boing sound for knockback LK.getSound('boing').play(); // Flash the enemy with LK.effects LK.effects.flashObject(enemy, 0xFF0000, 300); tween(enemy, { x: newX, rotation: enemy.x < player.x ? -Math.PI / 4 : Math.PI / 4, tint: 0xFFFFFF // Flash to white }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Reset rotation and tint with a smooth tween // Restore original speed direction after knockback enemy.speedX = originalSpeed; tween(enemy, { rotation: 0, tint: 0xFFFFFF // Reset to default white (no tint) }, { duration: 200, onFinish: function onFinish() { enemy.hit = false; } }); } }); return; // Do not run the death animation. } else { // On third hit (health <= 0), kill bigbob. LK.getSound('slimedeath').play(); tween(enemy, { tint: 0xFF0000 }, { duration: 0, onFinish: function onFinish() { tween(enemy, { scaleX: 0.3, scaleY: 0.3, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { var idx = enemies.indexOf(enemy); if (idx !== -1) { enemies.splice(idx, 1); } enemy.destroy(); // Reset Schmart spawn timer if a Schmart is killed if (enemy.isSchmarts && !schmartSpawnTimer) { schmartSpawnTimer = LK.setTimeout(function () { spawnSchmart(); schmartSpawnTimer = null; }, 10000); // Force spawn another Schmart after 10 seconds } if (!enemy.coinsDropped) { if (enemy.isSchmarts) { // Drop three gold coins when Schmart dies for (var i = 0; i < 3; i++) { var coin = new Container(); coin.type = 'gold'; coin.attachAsset('gold_coin', { anchorX: 0.5, anchorY: 0.5 }); // Position coins slightly apart from each other coin.x = enemy.x + (i - 1) * 50; coin.y = enemy.y; game.addChild(coin); coins.push(coin); loopCoinTween(coin, enemy.y); } } else if (enemy.isBigBob) { // Always drop a gold coin when BigBob dies var coin = new Container(); coin.type = 'gold'; coin.attachAsset('gold_coin', { anchorX: 0.5, anchorY: 0.5 }); coin.x = enemy.x; coin.y = enemy.y; game.addChild(coin); coins.push(coin); loopCoinTween(coin, enemy.y); } else { dropCoin(enemy.x, enemy.y); } enemy.coinsDropped = true; } // Add bonus score for BigBob and Schmarts if (!enemy.scoreCounted) { if (enemy.isSchmarts) { score += 25; } else { score += 10; } updateScoreDisplay(); enemy.scoreCounted = true; } } }); } }); return; } } // Regular enemy: instant kill on hit. enemy.hit = true; LK.getSound('slimedeath').play(); if (enemy.bounceTween && typeof enemy.bounceTween.cancel === 'function') { enemy.bounceTween.cancel(); } tween(enemy, { tint: 0xFF0000 }, { duration: 0, onFinish: function onFinish() { tween(enemy, { scaleX: 1.3, scaleY: 1.3 }, { duration: 50, onFinish: function onFinish() { tween(enemy, { scaleX: 0.5, scaleY: 0.5, alpha: 0 }, { duration: 100, onFinish: function onFinish() { var idx = enemies.indexOf(enemy); if (idx !== -1) { enemies.splice(idx, 1); } enemy.hit = false; enemy.destroy(); if (!enemy.coinsDropped) { dropCoin(enemy.x, enemy.y); enemy.coinsDropped = true; } helmetMeter += attackType === 'melee' || attackType === 'throw' ? 5 : 1; if (helmetMeter >= helmetMeterMax) { helmetMeter = helmetMeterMax; activateHelmetPowerUp(); helmetMeter = 0; } updateHelmetDisplay(); if (!enemy.scoreCounted) { score += attackType === 'melee' ? 2 : attackType === 'throw' ? 1 : 1; updateScoreDisplay(); enemy.scoreCounted = true; } } }); } }); } }); } function handleEnemyJumpHit(enemy, index) { if (!enemies.includes(enemy)) { return; } // Prevent jump attack from working on Schmart enemies if (enemy.isSchmarts === true) { LK.getSound('boing').play(); return; // Early return for Schmart enemies } LK.getSound('boing').play(); if (enemy.bounceTween && typeof enemy.bounceTween.cancel === 'function') { enemy.bounceTween.cancel(); } tween(enemy, { tint: 0xFF0000 }, { duration: 0, onFinish: function onFinish() { var targetX = enemy.x < 1024 ? -300 : 2048 + 300; var targetY = enemy.y - 600; tween(enemy, { x: targetX, y: targetY, alpha: 0 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { var idx = enemies.indexOf(enemy); if (idx !== -1) { enemies.splice(idx, 1); } enemy.destroy(); if (!enemy.coinsDropped) { dropCoin(enemy.x, enemy.y); enemy.coinsDropped = true; } helmetMeter += 7; if (helmetMeter >= helmetMeterMax) { helmetMeter = helmetMeterMax; activateHelmetPowerUp(); helmetMeter = 0; } updateHelmetDisplay(); if (!enemy.scoreCounted) { score += 3; updateScoreDisplay(); enemy.scoreCounted = true; } } }); } }); } /**** * findChildByName Helper ****/ Container.prototype.findChildByName = function (name) { for (var i = 0; i < this.children.length; i++) { if (this.children[i].name === name) { return this.children[i]; } } return null; }; /**** * game.up to Reset Press ****/ game.up = function (x, y) { isPressHeld = false; pressHoldStartTime = 0; }; /**** * Main Update ****/ game.update = function () { if (game.paused) { return; } if (isPressHeld) { var holdDuration = Date.now() - pressHoldStartTime; if (holdDuration > 500) { console.log("Long press detected, spawn projectile!"); isPressHeld = false; spawnProjectile(pressDownX, pressDownY); } } for (var p = projectiles.length - 1; p >= 0; p--) { var proj = projectiles[p]; proj.x += proj.vx; proj.y += proj.vy; var stepDist = Math.sqrt(proj.vx * proj.vx + proj.vy * proj.vy); proj.distanceTraveled += stepDist; if (proj.distanceTraveled > proj.maxDistance) { projectiles.splice(p, 1); proj.destroy(); continue; } if (proj.x < -100 || proj.x > 2148 || proj.y < -100 || proj.y > 2832) { projectiles.splice(p, 1); proj.destroy(); continue; } for (var ei = enemies.length - 1; ei >= 0; ei--) { var enemy = enemies[ei]; if (proj.intersects(enemy)) { handleEnemyHit(enemy, ei, 'throw'); projectiles.splice(p, 1); proj.destroy(); break; } } } for (var f = featherEffects.length - 1; f >= 0; f--) { var feather = featherEffects[f]; for (var ei = enemies.length - 1; ei >= 0; ei--) { var enemy = enemies[ei]; if (feather.intersects(enemy)) { handleEnemyHit(enemy, ei, 'feather'); featherEffects.splice(f, 1); feather.destroy(); break; } } } for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.x += e.speedX; if (e.x < -300 || e.x > 2048 + 300) { var index = enemies.indexOf(e); if (index !== -1) { enemies.splice(index, 1); } e.destroy(); continue; } if (jumpColGlobal && jumpColGlobal.visible && e.intersects(jumpColGlobal)) { handleEnemyJumpHit(e, i); continue; } if (attackCol.visible && e.intersects(attackCol)) { handleEnemyHit(e, i, 'melee'); } var idleCollision = player.findChildByName('idleCollision'); if (!isJumping && !attackCol.visible && idleCollision && e.intersects(idleCollision)) { if (specialIdleActive) { handleEnemyHit(e, i, 'special_idle'); continue; } else { if (!gameOverTriggered) { gameOverTriggered = true; storage.lastScore = score; showCustomGameOver(); } } } } for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; if (!gameOverTriggered && !coin.collecting && Math.abs(coin.x - mouseX) < 32.5 && Math.abs(coin.y - mouseY) < 32.5) { coin.collecting = true; tween(coin, { x: scoreTxt.x, y: scoreTxt.y, alpha: 0 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { var index = coins.indexOf(coin); if (index !== -1) { coins.splice(index, 1); } if (coin.type === 'silver') { LK.getSound('silversnd').play(); score += 5; } else if (coin.type === 'gold') { LK.getSound('goldsnd').play(); score += 10; } updateScoreDisplay(); coin.destroy(); } }); } } // Helmet HUD: No collision logic. };
===================================================================
--- original.js
+++ change.js
@@ -579,31 +579,37 @@
schmartSpawnTimer = null;
}
var _bounce = function bounce() {
tween(enemy, {
- y: baseY - 100,
- scaleX: 1.8,
- // Twice as wide with slight thinning when stretching upward
- scaleY: 2.2 // Twice as tall with slight stretch when going upward
+ y: baseY - 30,
+ // Reduced bounce height to simulate heaviness
+ scaleX: 0.92,
+ // Less squash when stretching upward - feels heavier
+ scaleY: 1.08 // Less stretch upward - feels heavier
}, {
- duration: 500,
- easing: tween.bounceInOut,
+ duration: 700,
+ // Slower animation for heavier feel
+ easing: tween.easeInOut,
+ // Changed from bounceInOut to easeInOut for heavier feel
onFinish: function onFinish() {
tween(enemy, {
y: baseY,
- scaleX: 2.2,
- // Twice as wide with slight widening when squashing at bottom
- scaleY: 1.8 // Twice as tall with slight squashing at bottom
+ scaleX: 1.08,
+ // Slightly wider when squashing at bottom
+ scaleY: 0.92 // Slightly shorter when squashing at bottom
}, {
- duration: 500,
- easing: tween.bounceInOut,
+ duration: 700,
+ // Slower animation for heavier feel
+ easing: tween.easeInOut,
+ // Changed from bounceInOut to easeInOut for heavier feel
onFinish: function onFinish() {
// Return to normal scale before starting next bounce cycle
tween(enemy, {
- scaleX: 2.0,
- scaleY: 2.0
+ scaleX: 1.0,
+ scaleY: 1.0
}, {
- duration: 100,
+ duration: 200,
+ // Slightly longer pause before next bounce cycle
onFinish: _bounce
});
}
});
@@ -613,8 +619,10 @@
var enemy = new Container();
enemy.isBigBob = false;
enemy.isSchmarts = true;
enemy.health = 8; // Schmarts now takes 8 hits to die
+ // Add more mass/weight to Schmart
+ enemy.mass = 3; // Higher mass makes it feel heavier
var gfx = enemy.attachAsset('shmarts', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1 // Set fully opaque alpha
@@ -623,9 +631,9 @@
// Start Schmart closer to the visible area of the screen
enemy.x = fromLeft ? -gfx.width / 4 : 2048 + gfx.width / 4;
enemy.y = 2732 - 400; // Move Schmart spawning position higher on screen
// Reduce Schmart speed to make it move more slowly
- enemy.speedX = fromLeft ? Math.random() * 1.5 + 1 : -(Math.random() * 1.5 + 1);
+ enemy.speedX = fromLeft ? Math.random() * 1.2 + 0.8 : -(Math.random() * 1.2 + 0.8); // Even slower to feel heavier
enemy.originalSpeedX = enemy.speedX; // Save original speed.
gfx.scaleX = fromLeft ? 1 : -1; // Flip Schmarts asset if coming from the right
var baseY = enemy.y;
// Debug message to confirm Schmart spawning without flashing the screen
@@ -1211,14 +1219,16 @@
enemy.hit = true;
if (enemy.health > 0) {
// Knockback: move enemy away from the player.
// Make knockback distance appropriate for each enemy type
- var knockbackDistance = enemy.isSchmarts ? 400 : 150;
+ // Account for enemy mass if defined - heavier enemies get less knockback
+ var mass = enemy.mass || 1;
+ var knockbackDistance = enemy.isSchmarts ? Math.floor(200 / mass) : 150;
var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance;
// Temporarily store original speed to restore after knockback
var originalSpeed = enemy.speedX;
- // Reverse direction briefly for knockback effect
- enemy.speedX = enemy.speedX * -0.5;
+ // Reverse direction briefly for knockback effect - reduced by mass
+ enemy.speedX = enemy.speedX * (-0.5 / mass);
// Play boing sound for knockback
LK.getSound('boing').play();
// Flash the enemy with LK.effects
LK.effects.flashObject(enemy, 0xFF0000, 300);
@@ -1253,11 +1263,10 @@
}, {
duration: 0,
onFinish: function onFinish() {
tween(enemy, {
- // Set death animation scale to consistently small size regardless of enemy type
- scaleX: enemy.isSchmarts ? 0.15 : 0.3,
- scaleY: enemy.isSchmarts ? 0.15 : 0.3,
+ scaleX: 0.3,
+ scaleY: 0.3,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
high definition super nintendo background of a japanese sakura tree forest Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
2d snes dust particle. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
silver coin, $ sign on it, snes art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
gold coin, $ sign on it, snes art. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
snes white feather. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
white 3d questionmark with a shadow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
caligraphy paper front facing flat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
the letters 'Ready' in 3d with a japanese cartoon cherry blossom flair. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
picture of a cute enemy slime monster inspired by dragon quest and ragnarok online. In-Game asset. 2d. High contrast. No shadows
picture of a cute fat and large enemy slime monster inspired by dragon quest and ragnarok online. In-Game asset. 2d. High contrast. No shadows
picture of a cute enemy slime monster wearing a shield infront of its face inspired by dragon quest and ragnarok online. In-Game asset. 2d. High contrast. No shadows
picture of a cute massive enemy king metal slime monster inspired by dragon quest and ragnarok online.. In-Game asset. 2d. High contrast. No shadows