/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, level: 1 }); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); self.type = "player"; // default, can be "enemy" self.speed = 15; self.damage = 10; self.isActive = true; self.init = function (type) { self.type = type || "player"; var assetId = self.type === "player" ? "playerBullet" : "enemyBullet"; self.bulletGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); return self; }; self.update = function () { if (self.type === "player") { self.x += self.speed; } else { self.x -= self.speed; } // Remove bullets that go off screen if (self.x > 2048 || self.x < 0) { self.isActive = false; } }; return self; }); var Character = Container.expand(function () { var self = Container.call(this); self.health = 100; self.maxHealth = 100; self.isPlayer = true; self.canShoot = true; self.reactionTime = 0; self.gunDrawn = false; self.level = 1; self.init = function (isPlayer) { self.isPlayer = isPlayer; var assetId = self.isPlayer ? "playerGun" : "enemyGun"; self.gunGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); if (!self.isPlayer) { self.gunGraphics.scaleX = -1; // Flip enemy gun // Adjust enemy difficulty based on level self.reactionTime = Math.max(1000 - currentLevel * 100, 300); // Minimum 300ms reaction time } // Initially guns are holstered (not visible) self.gunGraphics.alpha = 0; return self; }; self.drawGun = function () { if (self.gunDrawn) return; self.gunGraphics.alpha = 1; self.gunGraphics.y = 0; self.gunDrawn = true; LK.getSound('reload').play(); tween(self.gunGraphics, { y: -20 }, { duration: 200, easing: tween.easeOut }); }; self.holsterGun = function () { if (!self.gunDrawn) return; tween(self.gunGraphics, { alpha: 0 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.gunDrawn = false; self.gunGraphics.y = 0; } }); }; self.shoot = function () { if (!self.canShoot || !self.gunDrawn) return null; LK.getSound('gunshot').play(); // Create muzzle flash effect var flash = LK.getAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); flash.tint = 0xFFFFAA; var xOffset = self.isPlayer ? 75 : -75; flash.x = self.x + xOffset; flash.y = self.y; game.addChild(flash); tween(flash, { alpha: 0, scaleX: 3, scaleY: 3 }, { duration: 100, onFinish: function onFinish() { flash.destroy(); } }); // Gun recoil animation var recoilX = self.isPlayer ? -15 : 15; tween(self.gunGraphics, { x: recoilX }, { duration: 50, onFinish: function onFinish() { tween(self.gunGraphics, { x: 0 }, { duration: 100 }); } }); // Create bullet var bullet = new Bullet().init(self.isPlayer ? "player" : "enemy"); bullet.x = self.x + xOffset; bullet.y = self.y; // Add cooldown self.canShoot = false; LK.setTimeout(function () { self.canShoot = true; }, 1000); return bullet; }; self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { self.health = 0; return true; // Character died } // Flash red when hit LK.effects.flashObject(self, 0xFF0000, 300); LK.getSound('hit').play(); return false; // Character still alive }; return self; }); var HealthBar = Container.expand(function () { var self = Container.call(this); self.init = function (isPlayer) { self.isPlayer = isPlayer; self.maxWidth = 300; self.healthBar = self.attachAsset(isPlayer ? 'playerHealth' : 'enemyHealth', { anchorX: 0, anchorY: 0.5 }); self.healthText = new Text2('100/100', { size: 36, fill: 0xFFFFFF }); if (isPlayer) { self.healthText.anchor.set(0, 0.5); self.healthText.x = 10; } else { self.healthText.anchor.set(1, 0.5); self.healthText.x = -10; } self.addChild(self.healthText); return self; }; self.update = function (current, max) { var percentage = Math.max(0, current / max); self.healthBar.width = this.maxWidth * percentage; // Change color based on health if (percentage > 0.6) { self.healthBar.tint = 0x00FF00; // Green } else if (percentage > 0.3) { self.healthBar.tint = 0xFFFF00; // Yellow } else { self.healthBar.tint = 0xFF0000; // Red } self.healthText.setText(Math.floor(current) + '/' + max); }; return self; }); var SignDisplay = Container.expand(function () { var self = Container.call(this); self.currentSign = null; self.init = function () { self.readySign = self.attachAsset('readySign', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.drawSign = self.attachAsset('drawSign', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.readyText = new Text2('READY', { size: 100, fill: 0x000000 }); self.readyText.anchor.set(0.5, 0.5); self.readySign.addChild(self.readyText); self.drawText = new Text2('DRAW!', { size: 120, fill: 0x000000 }); self.drawText.anchor.set(0.5, 0.5); self.drawSign.addChild(self.drawText); return self; }; self.showReady = function () { self.currentSign = "ready"; self.readySign.alpha = 1; self.drawSign.alpha = 0; tween(self.readySign, { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self.readySign, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeInOut }); } }); }; self.showDraw = function () { self.currentSign = "draw"; self.readySign.alpha = 0; self.drawSign.alpha = 1; // Make it pop in with a scale effect self.drawSign.scaleX = 0.5; self.drawSign.scaleY = 0.5; tween(self.drawSign, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.elastic, onFinish: function onFinish() { tween(self.drawSign, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); }; self.hideAll = function () { self.currentSign = null; tween(self.readySign, { alpha: 0 }, { duration: 200 }); tween(self.drawSign, { alpha: 0 }, { duration: 200 }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game state variables var gameState = "startup"; // startup, ready, waiting, shooting, cooldown, gameover var currentLevel = storage.level || 1; var score = 0; var highScore = storage.highScore || 0; var playerShot = false; var enemyShot = false; var drawTime = 0; var playerReactionTime = 0; var earliestAllowedDrawTime = 0; var waitStartTime = 0; var bullets = []; var readyToAdvance = false; // Create main game background var background = game.addChild(LK.getAsset('background', { x: 0, y: 0, anchorX: 0, anchorY: 0 })); // Create player and enemy var player = new Character().init(true); player.x = 400; player.y = 2732 / 2; game.addChild(player); var enemy = new Character().init(false); enemy.x = 2048 - 400; enemy.y = 2732 / 2; game.addChild(enemy); // Create signage for READY and DRAW var signDisplay = new SignDisplay().init(); signDisplay.x = 2048 / 2; signDisplay.y = 2732 / 3; game.addChild(signDisplay); // Create health bars var playerHealth = new HealthBar().init(true); playerHealth.x = 50; playerHealth.y = 100; game.addChild(playerHealth); var enemyHealth = new HealthBar().init(false); enemyHealth.x = 2048 - 50; enemyHealth.y = 100; game.addChild(enemyHealth); // Text displays var levelText = new Text2('Level ' + currentLevel, { size: 70, fill: 0xFFFFFF }); levelText.anchor.set(0.5, 0); LK.gui.top.addChild(levelText); var scoreText = new Text2('Score: 0', { size: 50, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); scoreText.y = 80; LK.gui.top.addChild(scoreText); var messageText = new Text2('', { size: 50, fill: 0xFFFFFF }); messageText.anchor.set(0.5, 0.5); messageText.x = 2048 / 2; messageText.y = 2732 / 2 + 300; game.addChild(messageText); var reactionTimeText = new Text2('', { size: 40, fill: 0xFFFFFF }); reactionTimeText.anchor.set(0.5, 0.5); reactionTimeText.x = 2048 / 2; reactionTimeText.y = 2732 / 2 + 400; game.addChild(reactionTimeText); // Helper functions function resetRound() { gameState = "ready"; playerShot = false; enemyShot = false; playerReactionTime = 0; drawTime = 0; waitStartTime = 0; // Clear any bullets for (var i = 0; i < bullets.length; i++) { if (bullets[i] && bullets[i].parent) { bullets[i].destroy(); } } bullets = []; // Reset characters player.holsterGun(); enemy.holsterGun(); player.canShoot = true; enemy.canShoot = true; // Hide messages reactionTimeText.setText(''); messageText.setText(''); // Start the ready sequence signDisplay.showReady(); // Wait 2-4 seconds before showing DRAW var waitTime = 2000 + Math.random() * 2000; LK.setTimeout(function () { if (gameState !== "ready") return; gameState = "waiting"; waitStartTime = Date.now(); earliestAllowedDrawTime = waitStartTime; signDisplay.showDraw(); drawTime = Date.now(); // Enemy reaction LK.setTimeout(function () { if (gameState !== "waiting" && gameState !== "shooting") return; enemy.drawGun(); // Enemy shoots after drawing LK.setTimeout(function () { if (gameState !== "waiting" && gameState !== "shooting") return; if (!enemyShot && enemy.canShoot) { var bullet = enemy.shoot(); if (bullet) { bullets.push(bullet); game.addChild(bullet); enemyShot = true; } } }, 200); }, enemy.reactionTime); }, waitTime); } function updateScore(points) { score += points; LK.setScore(score); scoreText.setText('Score: ' + score); if (score > highScore) { highScore = score; storage.highScore = highScore; } } function calculatePoints() { if (playerReactionTime <= 0) return 0; // Faster reaction gets more points var basePoints = 500; var timeBonus = Math.max(0, 1000 - playerReactionTime); var levelBonus = currentLevel * 50; return basePoints + timeBonus + levelBonus; } function advanceLevel() { currentLevel++; storage.level = currentLevel; levelText.setText('Level ' + currentLevel); // Make enemy more challenging as levels increase enemy.reactionTime = Math.max(1000 - currentLevel * 100, 300); // Reset health for next level player.health = player.maxHealth; enemy.health = enemy.maxHealth; playerHealth.update(player.health, player.maxHealth); enemyHealth.update(enemy.health, enemy.maxHealth); readyToAdvance = false; resetRound(); } function showMessage(text, duration) { messageText.setText(text); if (duration) { LK.setTimeout(function () { messageText.setText(''); }, duration); } } // Set up touch events game.down = function (x, y, obj) { if (gameState === "ready") { // Too early - false start playerReactionTime = -1; gameState = "cooldown"; player.drawGun(); showMessage("False start! Wait for the DRAW signal!", 2000); LK.setTimeout(function () { resetRound(); }, 2000); return; } if (gameState === "waiting" || gameState === "shooting") { // Player draws gun if (!player.gunDrawn) { player.drawGun(); gameState = "shooting"; // Calculate reaction time if (drawTime > 0) { playerReactionTime = Date.now() - drawTime; reactionTimeText.setText('Reaction time: ' + playerReactionTime + 'ms'); } } // Player shoots else if (!playerShot && player.canShoot) { var bullet = player.shoot(); if (bullet) { bullets.push(bullet); game.addChild(bullet); playerShot = true; } } } if (gameState === "cooldown" && readyToAdvance) { advanceLevel(); } }; // Start initial music LK.playMusic('westernTheme', { fade: { start: 0, end: 0.3, duration: 1000 } }); // Start the game LK.setTimeout(function () { resetRound(); }, 500); // Game update loop game.update = function () { // Update health bars playerHealth.update(player.health, player.maxHealth); enemyHealth.update(enemy.health, enemy.maxHealth); // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (!bullet.isActive) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check for player hit if (bullet.type === "enemy" && bullet.intersects(player)) { var isDead = player.takeDamage(bullet.damage); bullet.isActive = false; if (isDead) { gameState = "gameover"; showMessage("You were shot! Game over.", 3000); LK.setTimeout(function () { LK.showGameOver(); }, 3000); } } // Check for enemy hit if (bullet.type === "player" && bullet.intersects(enemy)) { var isEnemyDead = enemy.takeDamage(bullet.damage); bullet.isActive = false; if (isEnemyDead) { gameState = "cooldown"; var points = calculatePoints(); updateScore(points); showMessage("Nice shot! +" + points + " points!", 2000); readyToAdvance = true; LK.setTimeout(function () { if (gameState === "cooldown") { messageText.setText("Tap to continue to level " + (currentLevel + 1)); } }, 2000); } } } // Check if both player and enemy have shot if (gameState === "shooting" && playerShot && enemyShot) { gameState = "cooldown"; LK.setTimeout(function () { resetRound(); }, 2000); } };
===================================================================
--- original.js
+++ change.js
@@ -281,9 +281,9 @@
/****
* Initialize Game
****/
var game = new LK.Game({
- backgroundColor: 0x804000
+ backgroundColor: 0x000000
});
/****
* Game Code