User prompt
make the gun assets vertical to better display a gun
User prompt
add 1 more variant to each gun asset labeled as "firedgun" display it for a short period of time when a character shoots then go back to displaying the main asset
User prompt
shoot a projectile simulating the bullet from the character who draws first and wins the round
User prompt
scores should be placed behind the players
User prompt
Fix the visual layout and positioning of the elements in the Quick Draw Duel game. 1. Make sure the two characters are correctly positioned: - The player's character should be clearly visible and centered on the **left side** of the screen. - The AI character should be clearly visible and centered on the **right side** of the screen. - Both characters should be vertically aligned near the middle of the screen. 2. The "DRAW!" text should appear centered at the top or middle of the screen and must be clearly visible when triggered. 3. The win indicators (stars, bullets, or icons) for each side should appear: - At the top-left for the player’s score - At the top-right for the AI’s score 4. The tap area should be clearly divided: - The **left half** of the screen should register player taps. - The **right half** can remain inactive or optionally show AI action feedback. 5. After the match ends, show a centered restart button below the characters. Ensure all elements are clearly spaced, properly scaled for mobile screens, and visually balanced. Avoid overlapping or misaligned components.
Code edit (1 edits merged)
Please save this source code
User prompt
Quick Draw Duel
Initial prompt
Create a fast-paced reaction duel game called "Quick Draw Duel". Gameplay Summary: - Two characters face each other in a western-style standoff. - After a short random delay (between 1 to 3 seconds), a big "DRAW!" signal appears at the center of the screen. - The player must tap the gun image located their side of the screen as quickly as possible after the "DRAW!" signal appears. - The AI opponent will also respond with a random reaction time (between 200ms and 350ms). - If the player taps before "DRAW!" appears, it counts as a false start and the round is lost. - If the player taps after "DRAW!" and faster than the AI, the player wins the round. - If the AI is faster, the player loses the round. - The duel is best-of-5: the first to 3 wins is declared the overall winner. UI and Visuals: - Divide the screen into left and right halves. - Show two characters on each side: the player on the left, AI on the right. - Use simple animations or expressions to indicate win or loss (e.g., recoil, smoke puff, victory pose). - Show "DRAW!" as a large centered text when it's time to react. - Show round wins with small icons (e.g. bullet holes or stars) at the top of each side. - Add a restart button after the match ends. Audio: - Include a ticking sound or tense music during wait phase. - Gunshot sound when a tap is registered. - Short "you win" or "you lose" jingle after each round. Make the game loop tight and replayable.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // AI Gun Class var AIGun = Container.expand(function () { var self = Container.call(this); var gun = self.attachAsset('aiGun', { anchorX: 0.5, anchorY: 0.5 }); self.gun = gun; self.firedGun = null; self.flash = null; self.shoot = function () { // Swap to fired gun asset if (!self.firedGun) { var firedGun = LK.getAsset('aiFiredGun', { anchorX: 0.5, anchorY: 0.5 }); firedGun.x = self.gun.x; firedGun.y = self.gun.y; firedGun.visible = false; self.firedGun = firedGun; self.addChildAt(firedGun, self.getChildIndex(self.gun)); } self.gun.visible = false; self.firedGun.visible = true; // Revert to normal gun after short delay LK.setTimeout(function () { if (self.firedGun) self.firedGun.visible = false; if (self.gun) self.gun.visible = true; }, 180); if (self.flash) { self.removeChild(self.flash); self.flash = null; } var flash = LK.getAsset('muzzleFlash', { anchorX: 0.5, anchorY: 0.5 }); flash.x = -120; flash.y = 0; self.addChild(flash); self.flash = flash; tween(flash, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { if (self.flash) { self.removeChild(self.flash); self.flash = null; } } }); }; return self; }); // Bullet class for simulating the projectile var Bullet = Container.expand(function () { var self = Container.call(this); // shooter: 'player' or 'ai' self.shooter = null; // Attach a simple ellipse for the bullet var bulletShape = self.attachAsset('muzzleFlash', { anchorX: 0.5, anchorY: 0.5 }); bulletShape.width = 60; bulletShape.height = 60; self.bulletShape = bulletShape; // Set initial position and velocity self.vx = 0; self.vy = 0; // Track lastY for good-practice event triggers self.lastY = null; // Set bullet color based on shooter self.setShooter = function (shooter) { self.shooter = shooter; if (shooter === 'player') { bulletShape.tint = 0xFFD700; } else { bulletShape.tint = 0xAAAAAA; } }; // Called every tick self.update = function () { if (self.lastY === null) self.lastY = self.y; self.x += self.vx; self.y += self.vy; // Remove bullet if it leaves the screen if (self.shooter === 'player' && self.lastY >= aiGun.y && self.y < aiGun.y) { // Player bullet reached AI gun // Optionally: add a little smoke or effect here self.destroy(); } else if (self.shooter === 'ai' && self.lastY <= playerGun.y && self.y > playerGun.y) { // AI bullet reached player gun self.destroy(); } self.lastY = self.y; }; return self; }); // Player Gun Class var PlayerGun = Container.expand(function () { var self = Container.call(this); var gun = self.attachAsset('playerGun', { anchorX: 0.5, anchorY: 0.5 }); self.gun = gun; self.firedGun = null; self.flash = null; // Show muzzle flash and swap to fired gun self.shoot = function () { // Swap to fired gun asset if (!self.firedGun) { var firedGun = LK.getAsset('playerFiredGun', { anchorX: 0.5, anchorY: 0.5 }); firedGun.x = self.gun.x; firedGun.y = self.gun.y; firedGun.visible = false; self.firedGun = firedGun; self.addChildAt(firedGun, self.getChildIndex(self.gun)); } self.gun.visible = false; self.firedGun.visible = true; // Revert to normal gun after short delay LK.setTimeout(function () { if (self.firedGun) self.firedGun.visible = false; if (self.gun) self.gun.visible = true; }, 180); if (self.flash) { self.removeChild(self.flash); self.flash = null; } var flash = LK.getAsset('muzzleFlash', { anchorX: 0.5, anchorY: 0.5 }); flash.x = 120; flash.y = 0; self.addChild(flash); self.flash = flash; tween(flash, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { if (self.flash) { self.removeChild(self.flash); self.flash = null; } } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2d1a07 }); /**** * Game Code ****/ // fired variant // fired variant // Game state variables // Guns // Bullet flash // "DRAW!" signal // Win/Lose round indicator // Sound effects var round = 1; var playerScore = 0; var aiScore = 0; var maxRounds = 5; var winScore = 3; var state = 'waiting'; // 'waiting', 'ready', 'draw', 'playerShot', 'aiShot', 'falsestart', 'roundEnd' var drawTimeout = null; var aiShotTimeout = null; var canShoot = false; var playerReactTime = null; var aiReactTime = null; var drawTime = null; var playerShot = false; var aiShot = false; // UI elements var playerGun = new PlayerGun(); var aiGun = new AIGun(); var drawSign = null; var infoText = null; var roundDots = []; var aiRoundDots = []; var resultText = null; // Layout constants var centerX = 2048 / 2; var playerGunY = 2732 - 350; var aiGunY = 350; // Add guns to game playerGun.x = centerX; playerGun.y = playerGunY; game.addChild(playerGun); aiGun.x = centerX; aiGun.y = aiGunY; game.addChild(aiGun); // Draw round win/loss dots function updateRoundDots() { // Remove old dots for (var i = 0; i < roundDots.length; i++) { if (playerGun.children.indexOf(roundDots[i]) !== -1) { playerGun.removeChild(roundDots[i]); } } for (var i = 0; i < aiRoundDots.length; i++) { if (aiGun.children.indexOf(aiRoundDots[i]) !== -1) { aiGun.removeChild(aiRoundDots[i]); } } roundDots = []; aiRoundDots = []; // Player dots (behind player gun) for (var i = 0; i < winScore; i++) { var dot; if (i < playerScore) { dot = LK.getAsset('winDot', { anchorX: 0.5, anchorY: 0.5 }); } else { dot = LK.getAsset('loseDot', { anchorX: 0.5, anchorY: 0.5 }); dot.alpha = 0.3; } // Arrange dots horizontally behind the player gun dot.x = -180 + i * 80 - (winScore - 1) * 80 / 2; dot.y = 120; playerGun.addChild(dot); roundDots.push(dot); } // AI dots (behind AI gun) for (var j = 0; j < winScore; j++) { var dot2; if (j < aiScore) { dot2 = LK.getAsset('winDot', { anchorX: 0.5, anchorY: 0.5 }); } else { dot2 = LK.getAsset('loseDot', { anchorX: 0.5, anchorY: 0.5 }); dot2.alpha = 0.3; } // Arrange dots horizontally behind the AI gun dot2.x = 180 - j * 80 + (winScore - 1) * 80 / 2; dot2.y = -120; aiGun.addChild(dot2); aiRoundDots.push(dot2); } } updateRoundDots(); // Info text infoText = new Text2('Get Ready...', { size: 120, fill: 0xFFF7D0 }); infoText.anchor.set(0.5, 0); infoText.x = LK.gui.top.width / 2; infoText.y = 200; LK.gui.top.addChild(infoText); // Result text (centered, hidden by default) resultText = new Text2('', { size: 180, fill: 0xFFF7D0 }); resultText.anchor.set(0.5, 0.5); resultText.x = LK.gui.center.width / 2; resultText.y = LK.gui.center.height / 2; resultText.visible = false; LK.gui.center.addChild(resultText); // DRAW! sign (hidden by default) function showDrawSign() { if (drawSign) { game.removeChild(drawSign); drawSign = null; } drawSign = LK.getAsset('drawSign', { anchorX: 0.5, anchorY: 0.5 }); drawSign.x = centerX; drawSign.y = 2732 / 2; game.addChild(drawSign); var drawText = new Text2('DRAW!', { size: 180, fill: "#000" }); drawText.anchor.set(0.5, 0.5); drawText.x = drawSign.width / 2; drawText.y = drawSign.height / 2; drawSign.addChild(drawText); tween(drawSign, { scaleX: 1.2, scaleY: 1.2 }, { duration: 120, easing: tween.bounceOut, onFinish: function onFinish() { tween(drawSign, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.linear }); } }); LK.getSound('draw').play(); } function hideDrawSign() { if (drawSign) { game.removeChild(drawSign); drawSign = null; } } // Start a new round function startRound() { state = 'waiting'; canShoot = false; playerReactTime = null; aiReactTime = null; playerShot = false; aiShot = false; drawTime = null; infoText.setText('Get Ready...'); resultText.visible = false; hideDrawSign(); // Animate guns to neutral playerGun.rotation = 0; aiGun.rotation = 0; // Wait a short moment, then start suspense timer var suspenseDelay = 700 + Math.floor(Math.random() * 400); LK.setTimeout(function () { infoText.setText('...'); // Random suspense before DRAW! var suspense = 1200 + Math.floor(Math.random() * 1200); drawTimeout = LK.setTimeout(function () { state = 'draw'; canShoot = true; drawTime = Date.now(); showDrawSign(); infoText.setText('DRAW!'); // AI will react after a random delay (simulate reflex) var aiDelay = 180 + Math.floor(Math.random() * 320); // 180-500ms aiShotTimeout = LK.setTimeout(function () { if (!aiShot && !playerShot) { aiShoot(); } }, aiDelay); }, suspense); }, suspenseDelay); } // Player shoots function playerShoot() { if (state === 'draw' && canShoot && !playerShot && !aiShot) { playerShot = true; playerReactTime = Date.now() - drawTime; playerGun.shoot(); LK.getSound('gunshot').play(); // Animate gun recoil tween(playerGun, { rotation: -0.18 }, { duration: 80, onFinish: function onFinish() { tween(playerGun, { rotation: 0 }, { duration: 120 }); } }); // If AI hasn't shot yet, player wins if (!aiShot) { // Fire bullet from player gun toward AI gun var bullet = new Bullet(); bullet.setShooter('player'); bullet.x = playerGun.x + 120; // muzzle flash offset bullet.y = playerGun.y; // Calculate velocity to AI gun var dx = aiGun.x - bullet.x - 120; // aim for AI muzzle var dy = aiGun.y - bullet.y; var dist = Math.sqrt(dx * dx + dy * dy); var speed = 80; // px per frame, fast for effect bullet.vx = dx / dist * speed; bullet.vy = dy / dist * speed; game.addChild(bullet); endRound('player'); } } else if (state === 'waiting' || state === 'ready') { // False start state = 'falsestart'; canShoot = false; playerShot = true; playerGun.shoot(); LK.getSound('falsestart').play(); infoText.setText('False Start!'); resultText.setText('You Shot Too Early!'); resultText.visible = true; endRound('ai', true); } } // AI shoots function aiShoot() { if (state === 'draw' && canShoot && !aiShot && !playerShot) { aiShot = true; aiReactTime = Date.now() - drawTime; aiGun.shoot(); LK.getSound('gunshot').play(); // Animate gun recoil tween(aiGun, { rotation: 0.18 }, { duration: 80, onFinish: function onFinish() { tween(aiGun, { rotation: 0 }, { duration: 120 }); } }); // If player hasn't shot yet, AI wins if (!playerShot) { // Fire bullet from AI gun toward player gun var bullet = new Bullet(); bullet.setShooter('ai'); bullet.x = aiGun.x - 120; // muzzle flash offset bullet.y = aiGun.y; // Calculate velocity to player gun var dx = playerGun.x - bullet.x + 120; // aim for player muzzle var dy = playerGun.y - bullet.y; var dist = Math.sqrt(dx * dx + dy * dy); var speed = 80; // px per frame, fast for effect bullet.vx = dx / dist * speed; bullet.vy = dy / dist * speed; game.addChild(bullet); endRound('ai'); } } } // End round, winner: 'player' or 'ai', falsestart: true/false function endRound(winner, falsestart) { canShoot = false; state = 'roundEnd'; // Clear timeouts if (drawTimeout) { LK.clearTimeout(drawTimeout); drawTimeout = null; } if (aiShotTimeout) { LK.clearTimeout(aiShotTimeout); aiShotTimeout = null; } // Update scores if (winner === 'player') { playerScore += 1; infoText.setText('You Win the Round!'); resultText.setText('You Win!'); resultText.visible = true; LK.effects.flashObject(playerGun, 0x00FF00, 600); } else { aiScore += 1; if (falsestart) { infoText.setText('False Start!'); resultText.setText('You Shot Too Early!'); } else { infoText.setText('AI Wins the Round!'); resultText.setText('AI Wins!'); } resultText.visible = true; LK.effects.flashObject(aiGun, 0xFF0000, 600); } updateRoundDots(); // Check for match end if (playerScore >= winScore) { LK.setScore(playerScore); LK.showYouWin(); return; } if (aiScore >= winScore) { LK.setScore(playerScore); LK.showGameOver(); return; } // Next round after short delay LK.setTimeout(function () { round += 1; startRound(); }, 1400); } // Handle player tap on gun playerGun.down = function (x, y, obj) { if (state === 'draw' || state === 'waiting' || state === 'ready') { playerShoot(); } }; // Also allow tapping anywhere in lower half to shoot (mobile friendly) game.down = function (x, y, obj) { if (y > 2732 / 2) { playerShoot(); } }; // Prevent AI gun from being tapped aiGun.down = function (x, y, obj) {}; // Start first round startRound(); // No need for update loop, as all logic is event/timer driven
===================================================================
--- original.js
+++ change.js
@@ -13,10 +13,30 @@
anchorX: 0.5,
anchorY: 0.5
});
self.gun = gun;
+ self.firedGun = null;
self.flash = null;
self.shoot = function () {
+ // Swap to fired gun asset
+ if (!self.firedGun) {
+ var firedGun = LK.getAsset('aiFiredGun', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ firedGun.x = self.gun.x;
+ firedGun.y = self.gun.y;
+ firedGun.visible = false;
+ self.firedGun = firedGun;
+ self.addChildAt(firedGun, self.getChildIndex(self.gun));
+ }
+ self.gun.visible = false;
+ self.firedGun.visible = true;
+ // Revert to normal gun after short delay
+ LK.setTimeout(function () {
+ if (self.firedGun) self.firedGun.visible = false;
+ if (self.gun) self.gun.visible = true;
+ }, 180);
if (self.flash) {
self.removeChild(self.flash);
self.flash = null;
}
@@ -94,11 +114,31 @@
anchorX: 0.5,
anchorY: 0.5
});
self.gun = gun;
+ self.firedGun = null;
self.flash = null;
- // Show muzzle flash
+ // Show muzzle flash and swap to fired gun
self.shoot = function () {
+ // Swap to fired gun asset
+ if (!self.firedGun) {
+ var firedGun = LK.getAsset('playerFiredGun', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ firedGun.x = self.gun.x;
+ firedGun.y = self.gun.y;
+ firedGun.visible = false;
+ self.firedGun = firedGun;
+ self.addChildAt(firedGun, self.getChildIndex(self.gun));
+ }
+ self.gun.visible = false;
+ self.firedGun.visible = true;
+ // Revert to normal gun after short delay
+ LK.setTimeout(function () {
+ if (self.firedGun) self.firedGun.visible = false;
+ if (self.gun) self.gun.visible = true;
+ }, 180);
if (self.flash) {
self.removeChild(self.flash);
self.flash = null;
}
@@ -134,8 +174,10 @@
/****
* Game Code
****/
+// fired variant
+// fired variant
// Game state variables
// Guns
// Bullet flash
// "DRAW!" signal
a western revolver. In-Game asset. High contrast. No shadows
a firing western revolver In-Game asset. High contrast. No shadows
bullet. In-Game asset. High contrast. No shadows
empty bullet cap. In-Game asset. High contrast. No shadows
a western themed alert box that says DRAW! on it. In-Game asset. High contrast. No shadows
a western setting duel arena, place one cowboy at the top of the screen facing down and another cowboy at the bottom facing up. In-Game asset. 2d. High contrast. No shadows
western style alert box that says You Shot Too Early!. In-Game asset. 2d. High contrast. No shadows
western style alert box that says "AI Wins!". In-Game asset. 2d. High contrast. No shadows
western style alert box that says "You Win!". In-Game asset. 2d. High contrast. No shadows