User prompt
make it so when the game is started it gives the player a choice between the hammer or the sword
User prompt
make it so if a enemy is parried by a sword they get stunned for 5 seconds and if a parry is landed by a sword it gives 5 seconds of i frames ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the parry window longer around 3 seconds and if it is missed give it a 2 second cooldown
User prompt
make it so the enemys do not go for melee attacks instead when they are in shooting range they stay in place and back up when the player gets closer
User prompt
make it so when a enemy is parried it gets stunned and if the player is using a hammer why the parry happens the enemy gets killed
User prompt
make the parry button bigger
User prompt
add a parry button
User prompt
make enemys feeze on level up screen and make the enemys have a hitpoints system where every weapon does a set amount of damage the pistol does 5 the rifle does 2 and the shotgun goes 10 and the enemys have 10 hp and give the rifle and pistol large range before there bullets disapeer and give the shotgun short range
User prompt
make a xp system when ever you level up it gives you three options one to increese damage one to give you more hp and one to increese range and make the shotgun deal more damage
User prompt
make it so you can aim the rifle while shooting and make it take three hits to kill a normal enemy
User prompt
remove the old movement and keep the double click movement
User prompt
make the rifle a starting weapon
User prompt
make the hp regen when you go in a new room
User prompt
Please fix the bug: 'Uncaught TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 839
User prompt
make it so when right click is held it will use full auto and shoot automatically if the rifle is equiped ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make so when i click on a weapon in the hotbar the trashcan icon lights up and if i click on it the weapon gets trashed and make the shotgun ammo not a pickup that goes into the hotbar but one that when is picked up it gets turned into shotgun ammo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'toGlobal')' in or related to this line: 'var localPos = hotbar.toLocal(obj.parent.toGlobal(obj.position));' Line Number: 581
User prompt
make a trash icon by the hotbar and if you drag a weapon into it it gets rid of it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
the shotgun feels overpowered add a ammo system for the gunshot and have it start with 5 ammo and once you run out you have to kill things for more ammo make it a 10% chance for a things you kill to drop shotgun ammo and make the ammo counter to the left of the hotbar and make the hp a bar and not a counter ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add a hotbar at the bottom of the screen that the player can click on to switch weapons and add a shotgun that can be found on the floor and when the player goes over it it goes into the hotbar
User prompt
Please fix the bug: 'TypeError: easing is not a function' in or related to this line: 'lastClickTime = 0; // Reset to prevent triple click' Line Number: 585
User prompt
please fix error
User prompt
make the parry right click and add a double click movement system
User prompt
redo the whole game
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function (isPlayer, gunType) { var self = Container.call(this); self.isPlayer = isPlayer || false; self.gunType = gunType || 'pistol'; var bulletGraphics = self.attachAsset(self.isPlayer ? 'bullet' : 'enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); // Different bullet properties based on gun type if (self.isPlayer) { switch (self.gunType) { case 'pistol': self.speed = 12; self.damage = 5 + damageBonus; self.maxRange = 800 * rangeBonus; // Large range break; case 'rifle': self.speed = 18; self.damage = 2 + damageBonus; self.maxRange = 1000 * rangeBonus; // Large range break; case 'shotgun': self.speed = 10; self.damage = 10 + damageBonus; self.maxRange = 300; // Short range break; } } else { self.speed = 8; self.damage = 1; self.maxRange = 400; } self.direction = 0; self.active = true; self.startX = 0; self.startY = 0; self.distanceTraveled = 0; self.update = function () { if (!self.active) return; self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; // Track distance traveled var dx = self.x - self.startX; var dy = self.y - self.startY; self.distanceTraveled = Math.sqrt(dx * dx + dy * dy); // Check range limit if (self.maxRange && self.distanceTraveled > self.maxRange) { self.active = false; } // Check bounds if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) { self.active = false; } }; return self; }); var Enemy = Container.expand(function (roomLevel) { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); // Set enemy health to 10 HP self.health = 10; self.speed = Math.min(1 + roomLevel * 0.2, 3); self.shootTimer = 0; self.shootCooldown = Math.max(120 - roomLevel * 5, 60); self.active = true; self.lastPlayerX = 0; self.lastPlayerY = 0; self.stunned = false; self.stunTimer = 0; self.update = function () { if (!self.active || !player || isLevelingUp) return; // Handle stunning if (self.stunned) { self.stunTimer--; if (self.stunTimer <= 0) { self.stunned = false; } return; // Don't move or shoot while stunned } // Track last position for intersection detection self.lastPlayerX = player.x; self.lastPlayerY = player.y; // Move to maintain optimal shooting distance var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); var optimalDistance = 250; // Preferred shooting distance var minDistance = 150; // Minimum distance to maintain if (distance < minDistance) { // Too close - back away from player self.x -= dx / distance * self.speed; self.y -= dy / distance * self.speed; } else if (distance > optimalDistance + 100) { // Too far - move closer but stop at optimal distance self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } // If between minDistance and optimalDistance+100, stay in place // Shooting logic self.shootTimer++; if (self.shootTimer >= self.shootCooldown && distance < 500) { self.shoot(); self.shootTimer = 0; } }; self.shoot = function () { var bullet = new Bullet(false); var angle = Math.atan2(player.y - self.y, player.x - self.x); bullet.direction = angle; bullet.x = self.x; bullet.y = self.y; bullet.startX = self.x; bullet.startY = self.y; enemyBullets.push(bullet); game.addChild(bullet); }; self.stun = function (duration) { self.stunned = true; self.stunTimer = duration; // Visual feedback for stunned enemy LK.effects.flashObject(self, 0xfff700, duration * 16.67); }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xFFFFFF, 200); if (self.health <= 0) { self.active = false; LK.setScore(LK.getScore() + 10); gainXP(25); // Gain 25 XP per enemy killed LK.getSound('enemyHit').play(); // 20% chance to drop weapon pickup if (Math.random() < 0.2) { spawnPickup(self.x, self.y); } // 10% chance to drop shotgun ammo if (Math.random() < 0.1) { var ammoPickup = new ShotgunAmmo(self.x, self.y); shotgunAmmoPickups.push(ammoPickup); game.addChild(ammoPickup); } } }; return self; }); var Pickup = Container.expand(function (type, x, y) { var self = Container.call(this); self.type = type; // 'gun' or 'melee' self.x = x; self.y = y; self.active = true; self.bobOffset = Math.random() * Math.PI * 2; self.startY = y; var pickupGraphics = self.attachAsset(type === 'gun' ? 'gunPickup' : 'meleePickup', { anchorX: 0.5, anchorY: 0.5 }); // Determine what weapon this pickup contains if (type === 'gun') { var guns = ['pistol', 'rifle', 'shotgun']; self.weapon = guns[Math.floor(Math.random() * guns.length)]; } else { var melees = ['sword', 'hammer']; self.weapon = melees[Math.floor(Math.random() * melees.length)]; } self.update = function () { if (!self.active) return; // Bobbing animation self.y = self.startY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 5; // Check pickup collision with player if (self.intersects(player)) { self.active = false; if (self.type === 'gun') { if (addWeaponToHotbar(self.weapon, 'gun')) { // Successfully added to hotbar LK.getSound('pickup').play(); LK.setScore(LK.getScore() + 5); } } else { if (addWeaponToHotbar(self.weapon, 'melee')) { // Successfully added to hotbar LK.getSound('pickup').play(); LK.setScore(LK.getScore() + 5); } } self.destroy(); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Gun display var gunGraphics = self.attachAsset('pistol', { anchorX: 0, anchorY: 0.5, x: 20, y: 0 }); // Melee weapon display var meleeGraphics = self.attachAsset('sword', { anchorX: 0.5, anchorY: 1, x: -15, y: -10 }); self.health = 3; self.maxHealth = 3; self.speed = 5; self.shootCooldown = 0; self.parryCooldown = 0; self.parryWindow = 0; self.invincibilityFrames = 0; // Weapon systems self.currentGun = 'pistol'; self.currentMelee = 'sword'; // Ammo system self.shotgunAmmo = 5; // Gun properties self.gunStats = { pistol: { cooldown: 12, spread: 0 }, rifle: { cooldown: 8, spread: 0.1 }, shotgun: { cooldown: 30, spread: 0.3, pellets: 3 } }; // Melee properties self.meleeStats = { sword: { parryWindow: 8, cooldown: 25, effect: 'reflect', color: 0x1abc9c }, hammer: { parryWindow: 15, cooldown: 45, effect: 'shockwave', color: 0xe74c3c } }; self.shoot = function (targetX, targetY) { if (self.shootCooldown > 0) return; // Check ammo for shotgun if (self.currentGun === 'shotgun' && self.shotgunAmmo <= 0) return; var gunStat = self.gunStats[self.currentGun]; var baseAngle = Math.atan2(targetY - self.y, targetX - self.x); if (self.currentGun === 'shotgun') { // Shotgun fires multiple pellets and consumes ammo self.shotgunAmmo--; for (var i = 0; i < gunStat.pellets; i++) { var bullet = new Bullet(true, self.currentGun); bullet.direction = baseAngle + (Math.random() - 0.5) * gunStat.spread; bullet.x = self.x; bullet.y = self.y; bullet.startX = self.x; bullet.startY = self.y; playerBullets.push(bullet); game.addChild(bullet); } } else { var bullet = new Bullet(true, self.currentGun); bullet.direction = baseAngle + (Math.random() - 0.5) * gunStat.spread; bullet.x = self.x; bullet.y = self.y; bullet.startX = self.x; bullet.startY = self.y; playerBullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot').play(); self.shootCooldown = gunStat.cooldown; }; self.parry = function () { if (self.parryCooldown > 0) return; var meleeStat = self.meleeStats[self.currentMelee]; self.parryWindow = 180; // 3 seconds at 60fps self.parryCooldown = meleeStat.cooldown; // Visual feedback var parryFX = game.attachAsset('parryEffect', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y, alpha: 0.8, tint: meleeStat.color }); tween(parryFX, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 3000, // 3 seconds onFinish: function onFinish() { parryFX.destroy(); } }); LK.getSound('parry').play(); }; self.switchGun = function (newGun) { if (newGun && self.gunStats[newGun]) { self.currentGun = newGun; gunGraphics.destroy(); gunGraphics = self.attachAsset(newGun, { anchorX: 0, anchorY: 0.5, x: 20, y: 0 }); } }; self.switchMelee = function (newMelee) { if (newMelee && self.meleeStats[newMelee]) { self.currentMelee = newMelee; meleeGraphics.destroy(); meleeGraphics = self.attachAsset(newMelee, { anchorX: 0.5, anchorY: 1, x: -15, y: -10 }); } }; self.takeDamage = function () { self.health--; LK.effects.flashObject(self, 0xFF0000, 500); LK.getSound('playerHit').play(); if (self.health <= 0) { LK.showGameOver(); } }; self.heal = function (amount) { self.health = Math.min(self.health + amount, self.maxHealth); }; self.update = function () { if (self.shootCooldown > 0) self.shootCooldown--; if (self.parryCooldown > 0) self.parryCooldown--; if (self.invincibilityFrames > 0) self.invincibilityFrames--; if (self.parryWindow > 0) { self.parryWindow--; // Check if parry window just expired without being used if (self.parryWindow === 0) { // Parry was missed, add 2 second cooldown self.parryCooldown = 120; // 2 seconds at 60fps } } }; return self; }); var Room = Container.expand(function (level) { var self = Container.call(this); self.level = level || 1; self.enemies = []; self.pickups = []; self.cleared = false; self.door = null; self.generateRoom = function () { // Create border walls var wallSize = 60; var roomWidth = 2048; var roomHeight = 2732; var wallsX = Math.floor(roomWidth / wallSize); var wallsY = Math.floor(roomHeight / wallSize); // Top and bottom walls for (var i = 0; i < wallsX; i++) { var topWall = self.attachAsset('wall', { x: i * wallSize, y: 0 }); var bottomWall = self.attachAsset('wall', { x: i * wallSize, y: roomHeight - wallSize }); } // Left and right walls for (var j = 1; j < wallsY - 1; j++) { var leftWall = self.attachAsset('wall', { x: 0, y: j * wallSize }); var rightWall = self.attachAsset('wall', { x: roomWidth - wallSize, y: j * wallSize }); } // Generate enemies var enemyCount = Math.min(2 + self.level, 8); for (var k = 0; k < enemyCount; k++) { var enemy = new Enemy(self.level); enemy.x = 200 + Math.random() * (roomWidth - 400); enemy.y = 200 + Math.random() * (roomHeight - 400); self.enemies.push(enemy); self.addChild(enemy); } // Create exit door (initially locked) self.door = self.attachAsset('door', { anchorX: 0.5, anchorY: 0.5, x: roomWidth / 2, y: wallSize / 2, tint: 0xc0392b }); // Spawn shotgun pickup in room spawnShotgunPickup(); }; self.checkCleared = function () { var activeEnemies = 0; for (var i = 0; i < self.enemies.length; i++) { if (self.enemies[i].active) { activeEnemies++; } } if (activeEnemies === 0 && !self.cleared) { self.cleared = true; // Unlock door if (self.door) { tween(self.door, { tint: 0x27ae60 }, { duration: 500 }); } } return self.cleared; }; return self; }); var ShotgunAmmo = Container.expand(function (x, y) { var self = Container.call(this); self.x = x; self.y = y; self.active = true; self.bobOffset = Math.random() * Math.PI * 2; self.startY = y; var ammoGraphics = self.attachAsset('shotgunAmmo', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { if (!self.active) return; // Bobbing animation self.y = self.startY + Math.sin(LK.ticks * 0.1 + self.bobOffset) * 5; // Check pickup collision with player if (self.intersects(player)) { self.active = false; player.shotgunAmmo += 3; // Give 3 ammo directly LK.getSound('pickup').play(); LK.setScore(LK.getScore() + 2); updateUI(); // Update ammo display self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ var player; var currentRoom; var playerBullets = []; var enemyBullets = []; var pickups = []; var shotgunAmmoPickups = []; var roomLevel = 1; var dragStartX = 0; var dragStartY = 0; var isDragging = false; var draggedWeapon = null; var draggedSlot = null; var trashIcon = null; var selectedWeapon = null; var selectedSlot = null; // XP System var playerXP = 0; var playerLevel = 1; var xpToNextLevel = 100; var isLevelingUp = false; var levelUpChoices = null; var damageBonus = 0; var rangeBonus = 1; // UI Elements var scoreText = new Text2('Score: 0', { size: 40, fill: '#ffffff' }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Health bar instead of text var healthBarBg = LK.gui.topRight.attachAsset('wall', { width: 150, height: 20, anchorX: 1, anchorY: 0, tint: 0x7f8c8d }); var healthBar = LK.gui.topRight.attachAsset('wall', { width: 150, height: 20, anchorX: 1, anchorY: 0, tint: 0xe74c3c }); var roomText = new Text2('Room: 1', { size: 30, fill: '#3498db' }); roomText.anchor.set(0, 0); roomText.x = 120; LK.gui.topLeft.addChild(roomText); var gunText = new Text2('Gun: Pistol', { size: 28, fill: '#f39c12' }); gunText.anchor.set(0, 1); LK.gui.bottomLeft.addChild(gunText); var meleeText = new Text2('Melee: Sword', { size: 28, fill: '#9b59b6' }); meleeText.anchor.set(1, 1); LK.gui.bottomRight.addChild(meleeText); // Hotbar system var hotbar = new Container(); hotbar.x = 1024; // Center of screen hotbar.y = 2600; // Bottom of screen game.addChild(hotbar); // Ammo counter to the left of hotbar var ammoText = new Text2('Shotgun: 5', { size: 32, fill: '#f39c12' }); ammoText.anchor.set(1, 0.5); ammoText.x = -300; // Position to the left of hotbar ammoText.y = 0; hotbar.addChild(ammoText); // XP and Level display var xpText = new Text2('Level 1 - XP: 0/100', { size: 30, fill: '#e67e22' }); xpText.anchor.set(0.5, 0); xpText.x = 120; xpText.y = 40; LK.gui.topLeft.addChild(xpText); var hotbarSlots = []; var slotWidth = 80; var slotHeight = 80; var slotSpacing = 100; // Create 5 hotbar slots for (var h = 0; h < 5; h++) { var slot = hotbar.attachAsset('wall', { width: slotWidth, height: slotHeight, anchorX: 0.5, anchorY: 0.5, x: (h - 2) * slotSpacing, y: 0, tint: 0x2c3e50 }); slot.slotIndex = h; slot.weapon = null; slot.weaponType = null; // 'gun' or 'melee' // Visual weapon display slot.weaponGraphics = null; slot.down = function (x, y, obj) { if (this.weapon) { // Select weapon and light up trash selectedWeapon = this.weapon; selectedSlot = this; // Highlight the selected slot tween(this, { tint: 0x3498db }, { duration: 100 }); // Light up trash icon tween(trashIcon, { tint: 0xff6b6b }, { duration: 100 }); } }; slot.up = function (x, y, obj) { // Switch to this weapon if it's selected but not the same as current selection if (selectedWeapon && selectedSlot === this) { if (this.weaponType === 'gun') { player.switchGun(this.weapon); } else if (this.weaponType === 'melee') { player.switchMelee(this.weapon); } updateUI(); } }; hotbarSlots.push(slot); } // Create trash icon next to hotbar trashIcon = hotbar.attachAsset('trashIcon', { width: 60, height: 60, anchorX: 0.5, anchorY: 0.5, x: 350, // Position to the right of hotbar y: 0, tint: 0xc0392b }); // Add click handler to trash icon trashIcon.down = function (x, y, obj) { if (selectedWeapon && selectedSlot) { // Delete weapon from selected slot selectedSlot.weapon = null; selectedSlot.weaponType = null; if (selectedSlot.weaponGraphics) { selectedSlot.weaponGraphics.destroy(); selectedSlot.weaponGraphics = null; } // Reset slot color tween(selectedSlot, { tint: 0x2c3e50 }, { duration: 100 }); // Flash trash icon to show deletion tween(trashIcon, { tint: 0xff0000 }, { duration: 200, onFinish: function onFinish() { tween(trashIcon, { tint: 0xc0392b }, { duration: 200 }); } }); // Clear selection selectedWeapon = null; selectedSlot = null; } }; // Add visual indicator for trash (X symbol) var trashX1 = hotbar.attachAsset('wall', { width: 30, height: 4, anchorX: 0.5, anchorY: 0.5, x: 350, y: 0, rotation: Math.PI / 4, tint: 0xffffff }); var trashX2 = hotbar.attachAsset('wall', { width: 30, height: 4, anchorX: 0.5, anchorY: 0.5, x: 350, y: 0, rotation: -Math.PI / 4, tint: 0xffffff }); // Create parry button var parryButton = game.attachAsset('parryButton', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 2500 }); // Add parry button text var parryButtonText = new Text2('PARRY', { size: 24, fill: '#ffffff' }); parryButtonText.anchor.set(0.5, 0.5); parryButtonText.x = 200; parryButtonText.y = 2500; game.addChild(parryButtonText); // Add parry button click handler parryButton.down = function (x, y, obj) { player.parry(); // Visual feedback on button press tween(parryButton, { scaleX: 0.9, scaleY: 0.9, tint: 0x16a085 }, { duration: 100, onFinish: function onFinish() { tween(parryButton, { scaleX: 1, scaleY: 1, tint: 0x1abc9c }, { duration: 100 }); } }); }; // Set initial weapons in hotbar hotbarSlots[0].weapon = 'pistol'; hotbarSlots[0].weaponType = 'gun'; hotbarSlots[0].weaponGraphics = hotbarSlots[0].attachAsset('pistol', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); hotbarSlots[1].weapon = 'sword'; hotbarSlots[1].weaponType = 'melee'; hotbarSlots[1].weaponGraphics = hotbarSlots[1].attachAsset('sword', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); hotbarSlots[2].weapon = 'rifle'; hotbarSlots[2].weaponType = 'gun'; hotbarSlots[2].weaponGraphics = hotbarSlots[2].attachAsset('rifle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); function updateUI() { scoreText.setText('Score: ' + LK.getScore()); // Update health bar var healthPercent = player.health / player.maxHealth; healthBar.width = 150 * healthPercent; roomText.setText('Room: ' + roomLevel); gunText.setText('Gun: ' + player.currentGun.charAt(0).toUpperCase() + player.currentGun.slice(1)); meleeText.setText('Melee: ' + player.currentMelee.charAt(0).toUpperCase() + player.currentMelee.slice(1)); // Update ammo counter ammoText.setText('Shotgun: ' + player.shotgunAmmo); // Update XP display xpText.setText('Level ' + playerLevel + ' - XP: ' + playerXP + '/' + xpToNextLevel); } function gainXP(amount) { playerXP += amount; if (playerXP >= xpToNextLevel && !isLevelingUp) { levelUp(); } } function levelUp() { isLevelingUp = true; playerLevel++; playerXP -= xpToNextLevel; xpToNextLevel = Math.floor(xpToNextLevel * 1.5); // Create level up choices overlay showLevelUpChoices(); } function showLevelUpChoices() { // Create overlay background var overlay = game.attachAsset('wall', { width: 2048, height: 2732, anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.8, tint: 0x000000 }); // Create choice buttons var choiceY = 1366; // Center Y var choiceSpacing = 400; // Damage choice var damageChoice = game.attachAsset('wall', { width: 300, height: 100, anchorX: 0.5, anchorY: 0.5, x: 1024 - choiceSpacing, y: choiceY, tint: 0xe74c3c }); var damageText = new Text2('+1 Damage', { size: 36, fill: '#ffffff' }); damageText.anchor.set(0.5, 0.5); damageText.x = 1024 - choiceSpacing; damageText.y = choiceY; game.addChild(damageText); // HP choice var hpChoice = game.attachAsset('wall', { width: 300, height: 100, anchorX: 0.5, anchorY: 0.5, x: 1024, y: choiceY, tint: 0x27ae60 }); var hpText = new Text2('+1 Max HP', { size: 36, fill: '#ffffff' }); hpText.anchor.set(0.5, 0.5); hpText.x = 1024; hpText.y = choiceY; game.addChild(hpText); // Range choice var rangeChoice = game.attachAsset('wall', { width: 300, height: 100, anchorX: 0.5, anchorY: 0.5, x: 1024 + choiceSpacing, y: choiceY, tint: 0x3498db }); var rangeText = new Text2('+Range', { size: 36, fill: '#ffffff' }); rangeText.anchor.set(0.5, 0.5); rangeText.x = 1024 + choiceSpacing; rangeText.y = choiceY; game.addChild(rangeText); // Store references for cleanup levelUpChoices = { overlay: overlay, damageChoice: damageChoice, hpChoice: hpChoice, rangeChoice: rangeChoice, damageText: damageText, hpText: hpText, rangeText: rangeText }; // Add click handlers damageChoice.down = function () { chooseLevelUpOption('damage'); }; hpChoice.down = function () { chooseLevelUpOption('hp'); }; rangeChoice.down = function () { chooseLevelUpOption('range'); }; } function chooseLevelUpOption(choice) { if (!isLevelingUp || !levelUpChoices) return; // Apply the chosen upgrade switch (choice) { case 'damage': damageBonus++; break; case 'hp': player.maxHealth++; player.health++; break; case 'range': rangeBonus += 0.2; break; } // Clean up level up UI levelUpChoices.overlay.destroy(); levelUpChoices.damageChoice.destroy(); levelUpChoices.hpChoice.destroy(); levelUpChoices.rangeChoice.destroy(); levelUpChoices.damageText.destroy(); levelUpChoices.hpText.destroy(); levelUpChoices.rangeText.destroy(); levelUpChoices = null; isLevelingUp = false; updateUI(); } function spawnPickup(x, y) { var pickupType = Math.random() < 0.6 ? 'gun' : 'melee'; var pickup = new Pickup(pickupType, x, y); pickups.push(pickup); game.addChild(pickup); } function addWeaponToHotbar(weapon, weaponType) { // Find first empty slot for (var i = 0; i < hotbarSlots.length; i++) { var slot = hotbarSlots[i]; if (!slot.weapon) { slot.weapon = weapon; slot.weaponType = weaponType; // Remove old graphics if any if (slot.weaponGraphics) { slot.weaponGraphics.destroy(); } // Add new weapon graphics slot.weaponGraphics = slot.attachAsset(weapon, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); return true; } } return false; // No empty slots } // Spawn shotgun pickup in each room function spawnShotgunPickup() { var shotgunPickup = new Pickup('gun', 300 + Math.random() * 1400, 400 + Math.random() * 1800); shotgunPickup.weapon = 'shotgun'; // Force it to be shotgun pickups.push(shotgunPickup); game.addChild(shotgunPickup); } function generateNewRoom() { // Clear current room if (currentRoom) { currentRoom.destroy(); } // Clear bullets and pickups for (var i = 0; i < playerBullets.length; i++) { playerBullets[i].destroy(); } for (var j = 0; j < enemyBullets.length; j++) { enemyBullets[j].destroy(); } for (var k = 0; k < pickups.length; k++) { pickups[k].destroy(); } for (var l = 0; l < shotgunAmmoPickups.length; l++) { shotgunAmmoPickups[l].destroy(); } playerBullets = []; enemyBullets = []; pickups = []; shotgunAmmoPickups = []; // Create new room roomLevel++; currentRoom = new Room(roomLevel); currentRoom.generateRoom(); game.addChild(currentRoom); // Reset player position player.x = 1024; player.y = 2400; game.addChild(player); // Regenerate HP when entering new room player.heal(1); // Heal 1 HP when entering a new room updateUI(); } // Game state management var gameStarted = false; var weaponSelectionUI = null; // Show weapon selection screen function showWeaponSelection() { // Create overlay background var overlay = game.attachAsset('wall', { width: 2048, height: 2732, anchorX: 0, anchorY: 0, x: 0, y: 0, alpha: 0.9, tint: 0x2c3e50 }); // Title text var titleText = new Text2('Choose Your Weapon', { size: 60, fill: '#ffffff' }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 800; game.addChild(titleText); // Create weapon choice buttons var choiceY = 1366; // Center Y var choiceSpacing = 400; // Hammer choice var hammerChoice = game.attachAsset('wall', { width: 300, height: 200, anchorX: 0.5, anchorY: 0.5, x: 1024 - choiceSpacing, y: choiceY, tint: 0x8e44ad }); var hammerIcon = game.attachAsset('hammer', { anchorX: 0.5, anchorY: 0.5, x: 1024 - choiceSpacing, y: choiceY - 20, scaleX: 3, scaleY: 3 }); var hammerText = new Text2('HAMMER', { size: 32, fill: '#ffffff' }); hammerText.anchor.set(0.5, 0.5); hammerText.x = 1024 - choiceSpacing; hammerText.y = choiceY + 50; game.addChild(hammerText); var hammerDesc = new Text2('Kills enemies\nwhen parrying', { size: 24, fill: '#ecf0f1' }); hammerDesc.anchor.set(0.5, 0.5); hammerDesc.x = 1024 - choiceSpacing; hammerDesc.y = choiceY + 80; game.addChild(hammerDesc); // Sword choice var swordChoice = game.attachAsset('wall', { width: 300, height: 200, anchorX: 0.5, anchorY: 0.5, x: 1024 + choiceSpacing, y: choiceY, tint: 0xe67e22 }); var swordIcon = game.attachAsset('sword', { anchorX: 0.5, anchorY: 0.5, x: 1024 + choiceSpacing, y: choiceY - 20, scaleX: 3, scaleY: 3 }); var swordText = new Text2('SWORD', { size: 32, fill: '#ffffff' }); swordText.anchor.set(0.5, 0.5); swordText.x = 1024 + choiceSpacing; swordText.y = choiceY + 50; game.addChild(swordText); var swordDesc = new Text2('Gives invincibility\nframes when parrying', { size: 24, fill: '#ecf0f1' }); swordDesc.anchor.set(0.5, 0.5); swordDesc.x = 1024 + choiceSpacing; swordDesc.y = choiceY + 80; game.addChild(swordDesc); // Store references for cleanup weaponSelectionUI = { overlay: overlay, titleText: titleText, hammerChoice: hammerChoice, hammerIcon: hammerIcon, hammerText: hammerText, hammerDesc: hammerDesc, swordChoice: swordChoice, swordIcon: swordIcon, swordText: swordText, swordDesc: swordDesc }; // Add click handlers hammerChoice.down = function () { chooseWeapon('hammer'); }; swordChoice.down = function () { chooseWeapon('sword'); }; } // Handle weapon selection function chooseWeapon(weaponType) { if (!weaponSelectionUI) return; // Clean up weapon selection UI weaponSelectionUI.overlay.destroy(); weaponSelectionUI.titleText.destroy(); weaponSelectionUI.hammerChoice.destroy(); weaponSelectionUI.hammerIcon.destroy(); weaponSelectionUI.hammerText.destroy(); weaponSelectionUI.hammerDesc.destroy(); weaponSelectionUI.swordChoice.destroy(); weaponSelectionUI.swordIcon.destroy(); weaponSelectionUI.swordText.destroy(); weaponSelectionUI.swordDesc.destroy(); weaponSelectionUI = null; // Start the game with chosen weapon startGameWithWeapon(weaponType); } // Initialize game with chosen weapon function startGameWithWeapon(startingWeapon) { gameStarted = true; // Initialize game currentRoom = new Room(roomLevel); currentRoom.generateRoom(); game.addChild(currentRoom); player = new Player(); player.x = 1024; player.y = 2400; game.addChild(player); // Set the chosen starting weapon player.switchMelee(startingWeapon); // Update hotbar to reflect chosen weapon hotbarSlots[1].weapon = startingWeapon; hotbarSlots[1].weaponType = 'melee'; if (hotbarSlots[1].weaponGraphics) { hotbarSlots[1].weaponGraphics.destroy(); } hotbarSlots[1].weaponGraphics = hotbarSlots[1].attachAsset(startingWeapon, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); updateUI(); } // Show weapon selection at start showWeaponSelection(); // Touch controls game.down = function (x, y, obj) { isDragging = true; dragStartX = x; dragStartY = y; }; game.move = function (x, y, obj) { // Update aim position for rifle full auto if (isRightClickHeld && player.currentGun === 'rifle') { dragStartX = x; dragStartY = y; } }; game.up = function (x, y, obj) { if (isDragging && !isRightClickHeld) { var dx = x - dragStartX; var dy = y - dragStartY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 30) { // Check if this is a potential parry (tap in bottom area of screen or near parry button) var parryButtonDistance = Math.sqrt((x - 200) * (x - 200) + (y - 2500) * (y - 2500)); if (y > 2200 || parryButtonDistance < 120) { // Tap in bottom area or near parry button - parry player.parry(); } else { // Tap elsewhere - shoot player.shoot(x, y); } } } isDragging = false; isRightClickHeld = false; rightClickDetected = false; }; // Double click variables for movement system var lastClickTime = 0; var doubleClickThreshold = 300; // milliseconds var rightClickDetected = false; var isRightClickHeld = false; var fullAutoTimer = 0; var fullAutoInterval = 8; // Fire every 8 ticks for rifle full auto // Function to handle double click movement function handleDoubleClick(x, y) { // Move player to clicked position with smooth movement var targetX = Math.max(80, Math.min(1968, x)); var targetY = Math.max(80, Math.min(2652, y)); // Use tween for smooth movement tween(player, { x: targetX, y: targetY }, { duration: 500 }); } // Override the existing down handler to detect double clicks and right clicks game.down = function (x, y, obj) { var currentTime = Date.now(); // Check for right click (simulate with touch hold detection) // We'll detect right click as a hold that lasts longer than normal tap LK.setTimeout(function () { if (isDragging && !rightClickDetected) { // This is a right click hold isRightClickHeld = true; rightClickDetected = true; fullAutoTimer = 0; } }, 200); // 200ms to detect hold if (currentTime - lastClickTime < doubleClickThreshold) { // Double click detected handleDoubleClick(x, y); lastClickTime = 0; // Reset to prevent triple click } else { // Single click - start drag isDragging = true; dragStartX = x; dragStartY = y; lastClickTime = currentTime; } }; // Main game loop game.update = function () { if (!gameStarted || !player || !currentRoom || isLevelingUp) return; // Update player player.update(); // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; bullet.update(); if (!bullet.active) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check collision with enemies for (var j = 0; j < currentRoom.enemies.length; j++) { var enemy = currentRoom.enemies[j]; if (enemy.active && bullet.intersects(enemy)) { enemy.takeDamage(bullet.damage); bullet.active = false; bullet.destroy(); playerBullets.splice(i, 1); break; } } } // Update enemy bullets for (var k = enemyBullets.length - 1; k >= 0; k--) { var enemyBullet = enemyBullets[k]; enemyBullet.update(); if (!enemyBullet.active) { enemyBullet.destroy(); enemyBullets.splice(k, 1); continue; } // Check collision with player if (enemyBullet.intersects(player)) { if (player.parryWindow > 0) { // Successful parry - find the enemy that shot this bullet and stun them var bulletShooter = null; var shortestDistance = Infinity; for (var bulletCheck = 0; bulletCheck < currentRoom.enemies.length; bulletCheck++) { var checkEnemy = currentRoom.enemies[bulletCheck]; if (checkEnemy.active) { var checkDx = checkEnemy.x - enemyBullet.x; var checkDy = checkEnemy.y - enemyBullet.y; var checkDistance = Math.sqrt(checkDx * checkDx + checkDy * checkDy); if (checkDistance < shortestDistance) { shortestDistance = checkDistance; bulletShooter = checkEnemy; } } } // Stun the enemy that shot the bullet if (bulletShooter) { if (player.currentMelee === 'hammer') { // Hammer kills the enemy instead of stunning bulletShooter.takeDamage(bulletShooter.health); } else if (player.currentMelee === 'sword') { // Sword stuns enemy for 5 seconds bulletShooter.stun(300); // Stun for 5 seconds (300 ticks at 60fps) } else { // Other weapons stun the enemy for 2 seconds bulletShooter.stun(120); // Stun for 2 seconds (120 ticks at 60fps) } } var meleeStat = player.meleeStats[player.currentMelee]; // Give sword users 5 seconds of invincibility frames if (player.currentMelee === 'sword') { player.invincibilityFrames = 300; // 5 seconds at 60fps // Visual feedback for invincibility tween(player, { alpha: 0.5 }, { duration: 5000, onFinish: function onFinish() { player.alpha = 1; } }); } if (meleeStat.effect === 'reflect') { // Reflect bullet back var reflectedBullet = new Bullet(true, 'pistol'); reflectedBullet.x = enemyBullet.x; reflectedBullet.y = enemyBullet.y; reflectedBullet.startX = enemyBullet.x; reflectedBullet.startY = enemyBullet.y; reflectedBullet.direction = enemyBullet.direction + Math.PI; reflectedBullet.speed = 15; playerBullets.push(reflectedBullet); game.addChild(reflectedBullet); } else if (meleeStat.effect === 'shockwave') { // Damage nearby enemies for (var l = 0; l < currentRoom.enemies.length; l++) { var nearbyEnemy = currentRoom.enemies[l]; var dx = nearbyEnemy.x - player.x; var dy = nearbyEnemy.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150 && nearbyEnemy.active) { if (player.currentMelee === 'hammer') { // Hammer kills nearby enemies nearbyEnemy.takeDamage(nearbyEnemy.health); } else { // Other weapons damage nearby enemies nearbyEnemy.takeDamage(2); } } } } LK.effects.flashObject(player, meleeStat.color, 300); LK.setScore(LK.getScore() + 3); } else { // Player takes damage (unless they have invincibility frames) if (!player.invincibilityFrames || player.invincibilityFrames <= 0) { player.takeDamage(); } } enemyBullet.active = false; enemyBullet.destroy(); enemyBullets.splice(k, 1); } } // Update enemies for (var m = 0; m < currentRoom.enemies.length; m++) { var enemy = currentRoom.enemies[m]; if (enemy.active) { enemy.update(); } } // Update pickups for (var n = pickups.length - 1; n >= 0; n--) { var pickup = pickups[n]; pickup.update(); if (!pickup.active) { pickups.splice(n, 1); } } // Update shotgun ammo pickups for (var o = shotgunAmmoPickups.length - 1; o >= 0; o--) { var ammoPickup = shotgunAmmoPickups[o]; ammoPickup.update(); if (!ammoPickup.active) { shotgunAmmoPickups.splice(o, 1); } } // Check room completion if (currentRoom.checkCleared()) { // Check if player reaches door if (currentRoom.door && player.intersects(currentRoom.door)) { generateNewRoom(); } } // Reset trash icon when no weapon is selected if (!selectedWeapon && trashIcon.tint !== 0xc0392b) { tween(trashIcon, { tint: 0xc0392b }, { duration: 100 }); } // Handle aimed shooting for rifle while held if (isRightClickHeld && player.currentGun === 'rifle') { fullAutoTimer++; if (fullAutoTimer >= fullAutoInterval) { // Use current mouse/touch position for aiming var currentX = dragStartX; // This gets updated in move handler var currentY = dragStartY; // This gets updated in move handler player.shoot(currentX, currentY); fullAutoTimer = 0; } } // Update UI periodically if (LK.ticks % 30 === 0) { updateUI(); } };
===================================================================
--- original.js
+++ change.js
@@ -967,17 +967,172 @@
// Regenerate HP when entering new room
player.heal(1); // Heal 1 HP when entering a new room
updateUI();
}
-// Initialize game
-currentRoom = new Room(roomLevel);
-currentRoom.generateRoom();
-game.addChild(currentRoom);
-player = new Player();
-player.x = 1024;
-player.y = 2400;
-game.addChild(player);
-updateUI();
+// Game state management
+var gameStarted = false;
+var weaponSelectionUI = null;
+// Show weapon selection screen
+function showWeaponSelection() {
+ // Create overlay background
+ var overlay = game.attachAsset('wall', {
+ width: 2048,
+ height: 2732,
+ anchorX: 0,
+ anchorY: 0,
+ x: 0,
+ y: 0,
+ alpha: 0.9,
+ tint: 0x2c3e50
+ });
+ // Title text
+ var titleText = new Text2('Choose Your Weapon', {
+ size: 60,
+ fill: '#ffffff'
+ });
+ titleText.anchor.set(0.5, 0.5);
+ titleText.x = 1024;
+ titleText.y = 800;
+ game.addChild(titleText);
+ // Create weapon choice buttons
+ var choiceY = 1366; // Center Y
+ var choiceSpacing = 400;
+ // Hammer choice
+ var hammerChoice = game.attachAsset('wall', {
+ width: 300,
+ height: 200,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024 - choiceSpacing,
+ y: choiceY,
+ tint: 0x8e44ad
+ });
+ var hammerIcon = game.attachAsset('hammer', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024 - choiceSpacing,
+ y: choiceY - 20,
+ scaleX: 3,
+ scaleY: 3
+ });
+ var hammerText = new Text2('HAMMER', {
+ size: 32,
+ fill: '#ffffff'
+ });
+ hammerText.anchor.set(0.5, 0.5);
+ hammerText.x = 1024 - choiceSpacing;
+ hammerText.y = choiceY + 50;
+ game.addChild(hammerText);
+ var hammerDesc = new Text2('Kills enemies\nwhen parrying', {
+ size: 24,
+ fill: '#ecf0f1'
+ });
+ hammerDesc.anchor.set(0.5, 0.5);
+ hammerDesc.x = 1024 - choiceSpacing;
+ hammerDesc.y = choiceY + 80;
+ game.addChild(hammerDesc);
+ // Sword choice
+ var swordChoice = game.attachAsset('wall', {
+ width: 300,
+ height: 200,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024 + choiceSpacing,
+ y: choiceY,
+ tint: 0xe67e22
+ });
+ var swordIcon = game.attachAsset('sword', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024 + choiceSpacing,
+ y: choiceY - 20,
+ scaleX: 3,
+ scaleY: 3
+ });
+ var swordText = new Text2('SWORD', {
+ size: 32,
+ fill: '#ffffff'
+ });
+ swordText.anchor.set(0.5, 0.5);
+ swordText.x = 1024 + choiceSpacing;
+ swordText.y = choiceY + 50;
+ game.addChild(swordText);
+ var swordDesc = new Text2('Gives invincibility\nframes when parrying', {
+ size: 24,
+ fill: '#ecf0f1'
+ });
+ swordDesc.anchor.set(0.5, 0.5);
+ swordDesc.x = 1024 + choiceSpacing;
+ swordDesc.y = choiceY + 80;
+ game.addChild(swordDesc);
+ // Store references for cleanup
+ weaponSelectionUI = {
+ overlay: overlay,
+ titleText: titleText,
+ hammerChoice: hammerChoice,
+ hammerIcon: hammerIcon,
+ hammerText: hammerText,
+ hammerDesc: hammerDesc,
+ swordChoice: swordChoice,
+ swordIcon: swordIcon,
+ swordText: swordText,
+ swordDesc: swordDesc
+ };
+ // Add click handlers
+ hammerChoice.down = function () {
+ chooseWeapon('hammer');
+ };
+ swordChoice.down = function () {
+ chooseWeapon('sword');
+ };
+}
+// Handle weapon selection
+function chooseWeapon(weaponType) {
+ if (!weaponSelectionUI) return;
+ // Clean up weapon selection UI
+ weaponSelectionUI.overlay.destroy();
+ weaponSelectionUI.titleText.destroy();
+ weaponSelectionUI.hammerChoice.destroy();
+ weaponSelectionUI.hammerIcon.destroy();
+ weaponSelectionUI.hammerText.destroy();
+ weaponSelectionUI.hammerDesc.destroy();
+ weaponSelectionUI.swordChoice.destroy();
+ weaponSelectionUI.swordIcon.destroy();
+ weaponSelectionUI.swordText.destroy();
+ weaponSelectionUI.swordDesc.destroy();
+ weaponSelectionUI = null;
+ // Start the game with chosen weapon
+ startGameWithWeapon(weaponType);
+}
+// Initialize game with chosen weapon
+function startGameWithWeapon(startingWeapon) {
+ gameStarted = true;
+ // Initialize game
+ currentRoom = new Room(roomLevel);
+ currentRoom.generateRoom();
+ game.addChild(currentRoom);
+ player = new Player();
+ player.x = 1024;
+ player.y = 2400;
+ game.addChild(player);
+ // Set the chosen starting weapon
+ player.switchMelee(startingWeapon);
+ // Update hotbar to reflect chosen weapon
+ hotbarSlots[1].weapon = startingWeapon;
+ hotbarSlots[1].weaponType = 'melee';
+ if (hotbarSlots[1].weaponGraphics) {
+ hotbarSlots[1].weaponGraphics.destroy();
+ }
+ hotbarSlots[1].weaponGraphics = hotbarSlots[1].attachAsset(startingWeapon, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+ });
+ updateUI();
+}
+// Show weapon selection at start
+showWeaponSelection();
// Touch controls
game.down = function (x, y, obj) {
isDragging = true;
dragStartX = x;
@@ -1057,9 +1212,9 @@
}
};
// Main game loop
game.update = function () {
- if (!player || !currentRoom || isLevelingUp) return;
+ if (!gameStarted || !player || !currentRoom || isLevelingUp) return;
// Update player
player.update();
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {