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 ****/ // Sounds and music. // Other assets (you may use enemy01 for normal enemies) // Note: Use a unique key ("bigbob") so that it doesn’t conflict with enemy01. // NEW: Bigbob enemy asset. // Background // Ready screen // Standard shapes, images, and sounds. // Show the "Ready" screen at the beginning. 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 15 seconds LK.setTimeout(function () { spawnSchmart(); }, 15000); // 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); // Push back all current enemies for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Skip enemies that are already being hit or processed if (enemy.hit) { continue; } // Calculate knockback direction based on player position var knockbackDistance = 400; // Increased from 150px to 400px for more dramatic effect var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance; // Temporarily mark enemy as hit to prevent other interactions enemy.hit = true; // Store original speed to restore after effect var originalSpeed = enemy.speedX; // Apply knockback tween with slightly longer duration // Capture the reference to the specific enemy for this iteration (function (currentEnemy, originalX, direction, originalSpeed) { tween(currentEnemy, { x: newX, rotation: direction ? -Math.PI / 4 : Math.PI / 4, tint: 0xFFFFFF // Flash white }, { duration: 400, // Slightly longer for dramatic effect easing: tween.easeOut, onFinish: function onFinish() { // Reset rotation and tint tween(currentEnemy, { rotation: 0, tint: 0xFFFFFF }, { duration: 200, onFinish: function onFinish() { // Reset hit flag and restore speed currentEnemy.hit = false; currentEnemy.speedX = originalSpeed; } }); } }); })(enemy, enemy.x, enemy.x < player.x, originalSpeed); } 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); // Push back all current enemies again after transformation ends for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; // Skip enemies that are already being hit or processed if (enemy.hit) { continue; } // Calculate knockback direction based on player position var knockbackDistance = 400; // Increased from 150px to 400px for more dramatic effect var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance; // Temporarily mark enemy as hit to prevent other interactions enemy.hit = true; // Store original speed to restore after effect var originalSpeed = enemy.speedX; // Apply knockback tween with slightly longer duration // Capture the reference to the specific enemy for this iteration (function (currentEnemy, originalX, direction, originalSpeed) { tween(currentEnemy, { x: newX, rotation: direction ? -Math.PI / 4 : Math.PI / 4, tint: 0xFFFFFF // Flash white }, { duration: 400, // Slightly longer for dramatic effect easing: tween.easeOut, onFinish: function onFinish() { // Reset rotation and tint tween(currentEnemy, { rotation: 0, tint: 0xFFFFFF }, { duration: 200, onFinish: function onFinish() { // Reset hit flag and restore speed currentEnemy.hit = false; currentEnemy.speedX = originalSpeed; } }); } }); })(enemy, enemy.x, enemy.x < player.x, originalSpeed); } 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; }, 30000); // Force spawn a Schmart after 30 seconds if none exist } // Roll dice for which enemy type to spawn var randomValue = Math.random(); // Spawn Schmart with 5% chance if no Schmarts are active if (randomValue < 0.05 && 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 - 50, scaleX: 0.95, // Less squash/stretch - more subtle effect for upward movement scaleY: 1.05 // Less squash/stretch - more subtle effect for upward movement }, { duration: 500, easing: tween.bounceInOut, onFinish: function onFinish() { tween(enemy, { y: baseY, scaleX: 1.05, // Less squash/stretch - more subtle effect for downward movement scaleY: 0.95 // Less squash/stretch - more subtle effect for downward movement }, { 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 = false; enemy.isSchmarts = true; enemy.health = 8; // Schmarts now takes 8 hits to die 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.5 + 1 : -(Math.random() * 1.5 + 1); 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 var knockbackDistance = 150; // Same knockback distance for both Schmart and BigBob 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; // 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.isSchmarts ? 0 : 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; }, 20000); // Force spawn another Schmart after 20 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
@@ -485,9 +485,9 @@
if (enemy.hit) {
continue;
}
// Calculate knockback direction based on player position
- var knockbackDistance = 150; // 150px knockback distance
+ var knockbackDistance = 400; // Increased from 150px to 400px for more dramatic effect
var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance;
// Temporarily mark enemy as hit to prevent other interactions
enemy.hit = true;
// Store original speed to restore after effect
@@ -563,9 +563,9 @@
if (enemy.hit) {
continue;
}
// Calculate knockback direction based on player position
- var knockbackDistance = 150; // 150px knockback distance
+ var knockbackDistance = 400; // Increased from 150px to 400px for more dramatic effect
var newX = enemy.x < player.x ? enemy.x - knockbackDistance : enemy.x + knockbackDistance;
// Temporarily mark enemy as hit to prevent other interactions
enemy.hit = true;
// Store original speed to restore after effect
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