/****
* 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: 0x804000
});
/****
* 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
@@ -1,6 +1,556 @@
-/****
+/****
+* 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
-});
\ No newline at end of file
+ backgroundColor: 0x804000
+});
+
+/****
+* 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);
+ }
+};
\ No newline at end of file