/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Agent base class
var Agent = Container.expand(function () {
var self = Container.call(this);
self.team = null; // 'CT' or 'T'
self.isPlayer = false;
self.speed = 12;
self.radius = 60;
self.targetX = null;
self.targetY = null;
self.canShoot = true;
self.shootCooldown = 20; // frames
self.shootTimer = 0;
self.isAlive = true;
self.hasBomb = false;
self.isDefusing = false;
self.isPlanting = false;
self.defuseTimer = 0;
self.plantTimer = 0;
self.defuseTime = 90; // frames (1.5s)
self.plantTime = 90; // frames (1.5s)
self.asset = null;
self.setTeam = function (team) {
self.team = team;
if (team === 'CT') {
self.asset = self.attachAsset('ct_agent', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
self.asset = self.attachAsset('t_agent', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.setPlayer = function (isPlayer) {
self.isPlayer = isPlayer;
if (isPlayer) {
// Add a white border for player
self.asset.width += 10;
self.asset.height += 10;
}
};
self.moveTo = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.update = function () {
if (!self.isAlive) return;
// Movement
if (self.targetX !== null && self.targetY !== null) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > self.speed) {
self.x += self.speed * dx / dist;
self.y += self.speed * dy / dist;
} else {
self.x = self.targetX;
self.y = self.targetY;
self.targetX = null;
self.targetY = null;
}
}
// Shooting cooldown
if (!self.canShoot) {
self.shootTimer--;
if (self.shootTimer <= 0) {
self.canShoot = true;
}
}
// Planting/defusing
if (self.isPlanting) {
self.plantTimer++;
if (self.plantTimer >= self.plantTime) {
self.isPlanting = false;
self.plantTimer = 0;
game.bombPlanted(self);
}
}
if (self.isDefusing) {
self.defuseTimer++;
if (self.defuseTimer >= self.defuseTime) {
self.isDefusing = false;
self.defuseTimer = 0;
game.bombDefused(self);
}
}
};
self.shoot = function (tx, ty) {
if (!self.canShoot || !self.isAlive) return;
self.canShoot = false;
self.shootTimer = self.shootCooldown;
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.owner = self;
var dx = tx - self.x;
var dy = ty - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
bullet.vx = 36 * dx / dist;
bullet.vy = 36 * dy / dist;
game.addChild(bullet);
game.bullets.push(bullet);
LK.getSound('shoot').play();
};
self.die = function () {
self.isAlive = false;
self.visible = false;
if (self.hasBomb) {
// Drop bomb at death location
game.dropBomb(self.x, self.y);
self.hasBomb = false;
}
};
return self;
});
// Bomb class
var Bomb = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPlanted = false;
self.timer = 0;
self.plantX = null;
self.plantY = null;
self.plantDuration = 600; // 10 seconds (60fps)
self.update = function () {
if (self.isPlanted) {
self.timer++;
if (self.timer >= self.plantDuration) {
// Bomb explodes
game.bombExploded();
}
}
};
return self;
});
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = 0;
self.owner = null;
self.lifetime = 40; // frames
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
var idx = game.bullets.indexOf(self);
if (idx !== -1) game.bullets.splice(idx, 1);
}
};
return self;
});
// Wall class
var Wall = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// --- Game State ---
// Agents
// Bomb
// Simple wall
// Bullet
// Plant/defuse zone
// Buy zone
// Sounds
game.roundTime = 60 * 30; // 30 seconds per round
game.roundTimer = 0;
game.phase = 'buy'; // 'buy', 'play', 'plant', 'end'
game.phaseTimer = 0;
game.buyTime = 60 * 3; // 3 seconds
game.ctScore = 0;
game.tScore = 0;
game.maxScore = 5;
game.bullets = [];
game.agents = [];
game.walls = [];
game.bombZones = [];
game.buyZones = [];
game.bomb = null;
game.bombCarrier = null;
game.bombZone = null;
game.buyZoneCT = null;
game.buyZoneT = null;
game.player = null;
game.isPlayerCT = true; // Player is CT by default
game.tapState = 'move'; // 'move' or 'shoot'
game.lastTap = 0;
game.tapCooldown = 10;
game.infoText = null;
game.scoreText = null;
game.phaseText = null;
game.bombText = null;
// --- Map Layout (Simple) ---
function setupMap() {
// Clear previous
for (var i = 0; i < game.walls.length; ++i) game.walls[i].destroy();
for (var i = 0; i < game.bombZones.length; ++i) game.bombZones[i].destroy();
for (var i = 0; i < game.buyZones.length; ++i) game.buyZones[i].destroy();
game.walls = [];
game.bombZones = [];
game.buyZones = [];
// Walls (simple rectangle arena)
var wall1 = new Wall();
wall1.x = 2048 / 2;
wall1.y = 400;
wall1.width = 1200;
wall1.height = 40;
wall1.children[0].width = 1200;
wall1.children[0].height = 40;
game.addChild(wall1);
game.walls.push(wall1);
var wall2 = new Wall();
wall2.x = 2048 / 2;
wall2.y = 2732 - 400;
wall2.width = 1200;
wall2.height = 40;
wall2.children[0].width = 1200;
wall2.children[0].height = 40;
game.addChild(wall2);
game.walls.push(wall2);
var wall3 = new Wall();
wall3.x = 400;
wall3.y = 2732 / 2;
wall3.width = 40;
wall3.height = 1200;
wall3.children[0].width = 40;
wall3.children[0].height = 1200;
game.addChild(wall3);
game.walls.push(wall3);
var wall4 = new Wall();
wall4.x = 2048 - 400;
wall4.y = 2732 / 2;
wall4.width = 40;
wall4.height = 1200;
wall4.children[0].width = 40;
wall4.children[0].height = 1200;
game.addChild(wall4);
game.walls.push(wall4);
// Bomb zone (center)
var bombZone = LK.getAsset('zone', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
bombZone.alpha = 0.18;
game.addChild(bombZone);
game.bombZones.push(bombZone);
game.bombZone = bombZone;
// Buy zones (top and bottom)
var buyZoneCT = LK.getAsset('buyzone', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 600
});
buyZoneCT.alpha = 0.13;
game.addChild(buyZoneCT);
game.buyZones.push(buyZoneCT);
game.buyZoneCT = buyZoneCT;
var buyZoneT = LK.getAsset('buyzone', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 - 600
});
buyZoneT.alpha = 0.13;
game.addChild(buyZoneT);
game.buyZones.push(buyZoneT);
game.buyZoneT = buyZoneT;
}
// --- UI ---
function setupUI() {
if (game.infoText) game.infoText.destroy();
if (game.scoreText) game.scoreText.destroy();
if (game.phaseText) game.phaseText.destroy();
if (game.bombText) game.bombText.destroy();
if (game.moveLeftBtn) game.moveLeftBtn.destroy();
if (game.moveRightBtn) game.moveRightBtn.destroy();
if (game.moveUpBtn) game.moveUpBtn.destroy();
if (game.moveDownBtn) game.moveDownBtn.destroy();
if (game.shootBtn) game.shootBtn.destroy();
// Info text (center)
var infoText = new Text2('', {
size: 90,
fill: 0xFFFFFF
});
infoText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(infoText);
game.infoText = infoText;
// Score text (top)
var scoreText = new Text2('CT 0 : 0 T', {
size: 90,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
game.scoreText = scoreText;
// Phase text (bottom)
var phaseText = new Text2('', {
size: 70,
fill: 0xFFFF00
});
phaseText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(phaseText);
game.phaseText = phaseText;
// Bomb status (top right)
var bombText = new Text2('', {
size: 70,
fill: 0xFF4444
});
bombText.anchor.set(1, 0);
LK.gui.topRight.addChild(bombText);
game.bombText = bombText;
// --- Mobile Touch Controls ---
// Button size and margin
var btnSize = 220;
var btnMargin = 40;
var btnAlpha = 0.22;
var btnColor = 0xffffff;
// Move Left
var moveLeftBtn = new Container();
var leftShape = LK.getAsset('zone', {
anchorX: 0.5,
anchorY: 0.5,
width: btnSize,
height: btnSize,
color: btnColor
});
leftShape.alpha = btnAlpha;
moveLeftBtn.addChild(leftShape);
var leftTxt = new Text2('←', {
size: 120,
fill: 0x222222
});
leftTxt.anchor.set(0.5, 0.5);
moveLeftBtn.addChild(leftTxt);
moveLeftBtn.x = btnSize + btnMargin;
moveLeftBtn.y = 2732 - btnSize - btnMargin;
moveLeftBtn.interactive = true;
moveLeftBtn.down = function () {
if (game.phase !== 'play' || !game.player.isAlive) return;
var nx = Math.max(game.player.x - 120, game.player.radius);
game.player.moveTo(nx, game.player.y);
};
LK.gui.addChild(moveLeftBtn);
game.moveLeftBtn = moveLeftBtn;
// Move Right
var moveRightBtn = new Container();
var rightShape = LK.getAsset('zone', {
anchorX: 0.5,
anchorY: 0.5,
width: btnSize,
height: btnSize,
color: btnColor
});
rightShape.alpha = btnAlpha;
moveRightBtn.addChild(rightShape);
var rightTxt = new Text2('→', {
size: 120,
fill: 0x222222
});
rightTxt.anchor.set(0.5, 0.5);
moveRightBtn.addChild(rightTxt);
moveRightBtn.x = btnSize * 2 + btnMargin * 2;
moveRightBtn.y = 2732 - btnSize - btnMargin;
moveRightBtn.interactive = true;
moveRightBtn.down = function () {
if (game.phase !== 'play' || !game.player.isAlive) return;
var nx = Math.min(game.player.x + 120, 2048 - game.player.radius);
game.player.moveTo(nx, game.player.y);
};
LK.gui.addChild(moveRightBtn);
game.moveRightBtn = moveRightBtn;
// Move Up
var moveUpBtn = new Container();
var upShape = LK.getAsset('zone', {
anchorX: 0.5,
anchorY: 0.5,
width: btnSize,
height: btnSize,
color: btnColor
});
upShape.alpha = btnAlpha;
moveUpBtn.addChild(upShape);
var upTxt = new Text2('↑', {
size: 120,
fill: 0x222222
});
upTxt.anchor.set(0.5, 0.5);
moveUpBtn.addChild(upTxt);
moveUpBtn.x = btnSize * 1.5 + btnMargin * 1.5;
moveUpBtn.y = 2732 - btnSize * 2 - btnMargin * 2;
moveUpBtn.interactive = true;
moveUpBtn.down = function () {
if (game.phase !== 'play' || !game.player.isAlive) return;
var ny = Math.max(game.player.y - 120, game.player.radius);
game.player.moveTo(game.player.x, ny);
};
LK.gui.addChild(moveUpBtn);
game.moveUpBtn = moveUpBtn;
// Move Down
var moveDownBtn = new Container();
var downShape = LK.getAsset('zone', {
anchorX: 0.5,
anchorY: 0.5,
width: btnSize,
height: btnSize,
color: btnColor
});
downShape.alpha = btnAlpha;
moveDownBtn.addChild(downShape);
var downTxt = new Text2('↓', {
size: 120,
fill: 0x222222
});
downTxt.anchor.set(0.5, 0.5);
moveDownBtn.addChild(downTxt);
moveDownBtn.x = btnSize * 1.5 + btnMargin * 1.5;
moveDownBtn.y = 2732 - btnMargin;
moveDownBtn.interactive = true;
moveDownBtn.down = function () {
if (game.phase !== 'play' || !game.player.isAlive) return;
var ny = Math.min(game.player.y + 120, 2732 - game.player.radius);
game.player.moveTo(game.player.x, ny);
};
LK.gui.addChild(moveDownBtn);
game.moveDownBtn = moveDownBtn;
// Shoot Button (bottom right)
var shootBtn = new Container();
var shootShape = LK.getAsset('zone', {
anchorX: 0.5,
anchorY: 0.5,
width: btnSize,
height: btnSize,
color: 0xff4444
});
shootShape.alpha = btnAlpha + 0.08;
shootBtn.addChild(shootShape);
var shootTxt = new Text2('SHOOT', {
size: 60,
fill: 0xffffff
});
shootTxt.anchor.set(0.5, 0.5);
shootBtn.addChild(shootTxt);
shootBtn.x = 2048 - btnSize - btnMargin;
shootBtn.y = 2732 - btnSize - btnMargin;
shootBtn.interactive = true;
shootBtn.down = function () {
if (game.phase !== 'play' || !game.player.isAlive) return;
// Shoot towards enemy if visible, else forward
var tx = game.player.x,
ty = game.player.y - 300;
// Try to find nearest enemy
var minDist = 99999,
target = null;
for (var i = 0; i < game.agents.length; ++i) {
var ag = game.agents[i];
if (ag === game.player || !ag.isAlive || ag.team === game.player.team) continue;
var dx = ag.x - game.player.x;
var dy = ag.y - game.player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < minDist) {
minDist = dist;
target = ag;
}
}
if (target) {
tx = target.x;
ty = target.y;
}
game.player.shoot(tx, ty);
};
LK.gui.addChild(shootBtn);
game.shootBtn = shootBtn;
}
// --- Agents ---
function setupAgents() {
// Remove previous
for (var i = 0; i < game.agents.length; ++i) game.agents[i].destroy();
game.agents = [];
// Player
var player = new Agent();
player.setTeam(game.isPlayerCT ? 'CT' : 'T');
player.setPlayer(true);
if (game.isPlayerCT) {
player.x = 2048 / 2;
player.y = 700;
} else {
player.x = 2048 / 2;
player.y = 2732 - 700;
}
game.addChild(player);
game.agents.push(player);
game.player = player;
// AI teammates and enemies (1v1 for MVP, can expand)
var ai = new Agent();
ai.setTeam(game.isPlayerCT ? 'T' : 'CT');
ai.setPlayer(false);
if (game.isPlayerCT) {
ai.x = 2048 / 2;
ai.y = 2732 - 700;
} else {
ai.x = 2048 / 2;
ai.y = 700;
}
game.addChild(ai);
game.agents.push(ai);
// Assign bomb to T at start
for (var i = 0; i < game.agents.length; ++i) {
game.agents[i].hasBomb = false;
}
if (!game.isPlayerCT) {
player.hasBomb = true;
game.bombCarrier = player;
} else {
ai.hasBomb = true;
game.bombCarrier = ai;
}
}
// --- Bomb ---
function setupBomb() {
if (game.bomb) game.bomb.destroy();
var bomb = new Bomb();
bomb.visible = false;
game.addChild(bomb);
game.bomb = bomb;
}
// --- Round Start ---
function startRound() {
game.phase = 'buy';
game.phaseTimer = 0;
game.roundTimer = 0;
game.tapState = 'move';
setupMap();
setupAgents();
setupBomb();
setupUI();
game.infoText.setText('Buy Phase');
game.phaseText.setText('Tap to move. Double tap to shoot.');
game.bombText.setText('');
game.bullets = [];
}
// --- Round End ---
function endRound(winner) {
game.phase = 'end';
game.phaseTimer = 0;
if (winner === 'CT') {
game.ctScore++;
game.infoText.setText('Counter-Terrorists Win!');
LK.getSound('win').play();
} else if (winner === 'T') {
game.tScore++;
game.infoText.setText('Terrorists Win!');
LK.getSound('lose').play();
} else {
game.infoText.setText('Draw!');
}
game.scoreText.setText('CT ' + game.ctScore + ' : ' + game.tScore + ' T');
if (game.ctScore >= game.maxScore) {
LK.showYouWin();
} else if (game.tScore >= game.maxScore) {
LK.showGameOver();
}
}
// --- Bomb Plant/Defuse/Explode ---
game.bombPlanted = function (planter) {
game.bomb.isPlanted = true;
game.bomb.visible = true;
game.bomb.x = game.bombZone.x;
game.bomb.y = game.bombZone.y;
game.bomb.timer = 0;
game.bombCarrier = null;
game.infoText.setText('Bomb Planted!');
game.bombText.setText('Bomb: ' + ((game.bomb.plantDuration - game.bomb.timer) / 60).toFixed(1) + 's');
LK.getSound('plant').play();
};
game.bombDefused = function (defuser) {
game.bomb.isPlanted = false;
game.bomb.visible = false;
game.bomb.timer = 0;
game.bombText.setText('');
endRound('CT');
LK.getSound('defuse').play();
};
game.bombExploded = function () {
game.bomb.isPlanted = false;
game.bomb.visible = false;
game.bomb.timer = 0;
game.bombText.setText('');
endRound('T');
};
// --- Bomb Drop ---
game.dropBomb = function (x, y) {
game.bomb.visible = true;
game.bomb.x = x;
game.bomb.y = y;
game.bomb.isPlanted = false;
game.bomb.timer = 0;
game.bombCarrier = null;
game.bombText.setText('Bomb dropped!');
};
// --- Tap Handler ---
game.down = function (x, y, obj) {
if (game.phase === 'end') return;
if (!game.player.isAlive) return;
if (game.phase === 'buy') return;
// Tap to move or shoot
var now = LK.ticks;
if (now - game.lastTap < game.tapCooldown) {
// Double tap: shoot
game.tapState = 'shoot';
} else {
game.tapState = 'move';
}
game.lastTap = now;
if (game.tapState === 'move') {
// Move player
game.player.moveTo(x, y);
} else if (game.tapState === 'shoot') {
// Shoot towards tap
game.player.shoot(x, y);
}
};
// --- Update Handler ---
game.update = function () {
// --- Phase Management ---
if (game.phase === 'buy') {
game.phaseTimer++;
game.infoText.setText('Buy Phase');
game.phaseText.setText('Tap to move. Double tap to shoot.');
if (game.phaseTimer >= game.buyTime) {
game.phase = 'play';
game.infoText.setText('');
game.phaseText.setText('Eliminate enemy or plant/defuse bomb!');
}
return;
}
if (game.phase === 'end') {
game.phaseTimer++;
if (game.phaseTimer > 90) {
startRound();
}
return;
}
// --- Round Timer ---
game.roundTimer++;
var timeLeft = Math.max(0, Math.floor((game.roundTime - game.roundTimer) / 60));
game.phaseText.setText('Time: ' + timeLeft + 's');
if (game.roundTimer >= game.roundTime) {
endRound('Draw');
return;
}
// --- Update Agents ---
for (var i = 0; i < game.agents.length; ++i) {
var agent = game.agents[i];
agent.update();
}
// --- Update Bullets ---
for (var i = game.bullets.length - 1; i >= 0; --i) {
var bullet = game.bullets[i];
bullet.update();
// Remove if out of bounds
if (bullet.x < 0 || bullet.x > 2048 || bullet.y < 0 || bullet.y > 2732) {
bullet.destroy();
game.bullets.splice(i, 1);
continue;
}
// Check collision with agents
for (var j = 0; j < game.agents.length; ++j) {
var target = game.agents[j];
if (!target.isAlive) continue;
if (target === bullet.owner) continue;
var dx = bullet.x - target.x;
var dy = bullet.y - target.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < target.radius) {
// Hit!
target.die();
bullet.destroy();
game.bullets.splice(i, 1);
break;
}
}
}
// --- Update Bomb ---
if (game.bomb) {
game.bomb.update();
if (game.bomb.isPlanted) {
game.bombText.setText('Bomb: ' + ((game.bomb.plantDuration - game.bomb.timer) / 60).toFixed(1) + 's');
}
}
// --- Win/Lose Check ---
var ctAlive = false,
tAlive = false;
for (var i = 0; i < game.agents.length; ++i) {
if (!game.agents[i].isAlive) continue;
if (game.agents[i].team === 'CT') ctAlive = true;
if (game.agents[i].team === 'T') tAlive = true;
}
if (!ctAlive) {
endRound('T');
return;
}
if (!tAlive) {
endRound('CT');
return;
}
// --- Bomb Pickup ---
if (game.bomb && !game.bomb.isPlanted && !game.bombCarrier && game.bomb.visible) {
for (var i = 0; i < game.agents.length; ++i) {
var agent = game.agents[i];
if (!agent.isAlive) continue;
if (agent.team !== 'T') continue;
var dx = agent.x - game.bomb.x;
var dy = agent.y - game.bomb.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < agent.radius + 40) {
agent.hasBomb = true;
game.bombCarrier = agent;
game.bomb.visible = false;
game.bombText.setText('Bomb picked up!');
}
}
}
// --- Bomb Planting ---
if (game.bombCarrier && game.bombCarrier.isAlive && !game.bomb.isPlanted) {
var agent = game.bombCarrier;
var dx = agent.x - game.bombZone.x;
var dy = agent.y - game.bombZone.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 110) {
if (!agent.isPlanting) {
agent.isPlanting = true;
agent.plantTimer = 0;
game.infoText.setText('Planting...');
}
} else {
agent.isPlanting = false;
agent.plantTimer = 0;
}
}
// --- Bomb Defusing ---
if (game.bomb.isPlanted) {
for (var i = 0; i < game.agents.length; ++i) {
var agent = game.agents[i];
if (!agent.isAlive) continue;
if (agent.team !== 'CT') continue;
var dx = agent.x - game.bomb.x;
var dy = agent.y - game.bomb.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 110) {
if (!agent.isDefusing) {
agent.isDefusing = true;
agent.defuseTimer = 0;
game.infoText.setText('Defusing...');
}
} else {
agent.isDefusing = false;
agent.defuseTimer = 0;
}
}
}
// --- Simple AI ---
for (var i = 0; i < game.agents.length; ++i) {
var agent = game.agents[i];
if (agent.isPlayer || !agent.isAlive) continue;
// If has bomb, go to bomb zone
if (agent.hasBomb && !game.bomb.isPlanted) {
if (!agent.targetX || Math.abs(agent.x - game.bombZone.x) > 10 || Math.abs(agent.y - game.bombZone.y) > 10) {
agent.moveTo(game.bombZone.x, game.bombZone.y);
}
} else if (game.bomb.isPlanted && agent.team === 'CT') {
// Go to bomb to defuse
if (!agent.targetX || Math.abs(agent.x - game.bomb.x) > 10 || Math.abs(agent.y - game.bomb.y) > 10) {
agent.moveTo(game.bomb.x, game.bomb.y);
}
} else {
// Seek enemy
var target = null;
for (var j = 0; j < game.agents.length; ++j) {
if (game.agents[j].team !== agent.team && game.agents[j].isAlive) {
target = game.agents[j];
break;
}
}
if (target) {
var dx = target.x - agent.x;
var dy = target.y - agent.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 200) {
agent.moveTo(target.x, target.y);
} else {
// Shoot at enemy
agent.shoot(target.x, target.y);
}
}
}
}
};
// --- Start Game ---
startRound(); ===================================================================
--- original.js
+++ change.js
@@ -188,16 +188,16 @@
/****
* Game Code
****/
-// Sounds
-// Buy zone
-// Plant/defuse zone
-// Bullet
-// Simple wall
-// Bomb
-// Agents
// --- Game State ---
+// Agents
+// Bomb
+// Simple wall
+// Bullet
+// Plant/defuse zone
+// Buy zone
+// Sounds
game.roundTime = 60 * 30; // 30 seconds per round
game.roundTimer = 0;
game.phase = 'buy'; // 'buy', 'play', 'plant', 'end'
game.phaseTimer = 0;
@@ -308,8 +308,13 @@
if (game.infoText) game.infoText.destroy();
if (game.scoreText) game.scoreText.destroy();
if (game.phaseText) game.phaseText.destroy();
if (game.bombText) game.bombText.destroy();
+ if (game.moveLeftBtn) game.moveLeftBtn.destroy();
+ if (game.moveRightBtn) game.moveRightBtn.destroy();
+ if (game.moveUpBtn) game.moveUpBtn.destroy();
+ if (game.moveDownBtn) game.moveDownBtn.destroy();
+ if (game.shootBtn) game.shootBtn.destroy();
// Info text (center)
var infoText = new Text2('', {
size: 90,
fill: 0xFFFFFF
@@ -340,8 +345,169 @@
});
bombText.anchor.set(1, 0);
LK.gui.topRight.addChild(bombText);
game.bombText = bombText;
+ // --- Mobile Touch Controls ---
+ // Button size and margin
+ var btnSize = 220;
+ var btnMargin = 40;
+ var btnAlpha = 0.22;
+ var btnColor = 0xffffff;
+ // Move Left
+ var moveLeftBtn = new Container();
+ var leftShape = LK.getAsset('zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: btnSize,
+ height: btnSize,
+ color: btnColor
+ });
+ leftShape.alpha = btnAlpha;
+ moveLeftBtn.addChild(leftShape);
+ var leftTxt = new Text2('←', {
+ size: 120,
+ fill: 0x222222
+ });
+ leftTxt.anchor.set(0.5, 0.5);
+ moveLeftBtn.addChild(leftTxt);
+ moveLeftBtn.x = btnSize + btnMargin;
+ moveLeftBtn.y = 2732 - btnSize - btnMargin;
+ moveLeftBtn.interactive = true;
+ moveLeftBtn.down = function () {
+ if (game.phase !== 'play' || !game.player.isAlive) return;
+ var nx = Math.max(game.player.x - 120, game.player.radius);
+ game.player.moveTo(nx, game.player.y);
+ };
+ LK.gui.addChild(moveLeftBtn);
+ game.moveLeftBtn = moveLeftBtn;
+ // Move Right
+ var moveRightBtn = new Container();
+ var rightShape = LK.getAsset('zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: btnSize,
+ height: btnSize,
+ color: btnColor
+ });
+ rightShape.alpha = btnAlpha;
+ moveRightBtn.addChild(rightShape);
+ var rightTxt = new Text2('→', {
+ size: 120,
+ fill: 0x222222
+ });
+ rightTxt.anchor.set(0.5, 0.5);
+ moveRightBtn.addChild(rightTxt);
+ moveRightBtn.x = btnSize * 2 + btnMargin * 2;
+ moveRightBtn.y = 2732 - btnSize - btnMargin;
+ moveRightBtn.interactive = true;
+ moveRightBtn.down = function () {
+ if (game.phase !== 'play' || !game.player.isAlive) return;
+ var nx = Math.min(game.player.x + 120, 2048 - game.player.radius);
+ game.player.moveTo(nx, game.player.y);
+ };
+ LK.gui.addChild(moveRightBtn);
+ game.moveRightBtn = moveRightBtn;
+ // Move Up
+ var moveUpBtn = new Container();
+ var upShape = LK.getAsset('zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: btnSize,
+ height: btnSize,
+ color: btnColor
+ });
+ upShape.alpha = btnAlpha;
+ moveUpBtn.addChild(upShape);
+ var upTxt = new Text2('↑', {
+ size: 120,
+ fill: 0x222222
+ });
+ upTxt.anchor.set(0.5, 0.5);
+ moveUpBtn.addChild(upTxt);
+ moveUpBtn.x = btnSize * 1.5 + btnMargin * 1.5;
+ moveUpBtn.y = 2732 - btnSize * 2 - btnMargin * 2;
+ moveUpBtn.interactive = true;
+ moveUpBtn.down = function () {
+ if (game.phase !== 'play' || !game.player.isAlive) return;
+ var ny = Math.max(game.player.y - 120, game.player.radius);
+ game.player.moveTo(game.player.x, ny);
+ };
+ LK.gui.addChild(moveUpBtn);
+ game.moveUpBtn = moveUpBtn;
+ // Move Down
+ var moveDownBtn = new Container();
+ var downShape = LK.getAsset('zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: btnSize,
+ height: btnSize,
+ color: btnColor
+ });
+ downShape.alpha = btnAlpha;
+ moveDownBtn.addChild(downShape);
+ var downTxt = new Text2('↓', {
+ size: 120,
+ fill: 0x222222
+ });
+ downTxt.anchor.set(0.5, 0.5);
+ moveDownBtn.addChild(downTxt);
+ moveDownBtn.x = btnSize * 1.5 + btnMargin * 1.5;
+ moveDownBtn.y = 2732 - btnMargin;
+ moveDownBtn.interactive = true;
+ moveDownBtn.down = function () {
+ if (game.phase !== 'play' || !game.player.isAlive) return;
+ var ny = Math.min(game.player.y + 120, 2732 - game.player.radius);
+ game.player.moveTo(game.player.x, ny);
+ };
+ LK.gui.addChild(moveDownBtn);
+ game.moveDownBtn = moveDownBtn;
+ // Shoot Button (bottom right)
+ var shootBtn = new Container();
+ var shootShape = LK.getAsset('zone', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ width: btnSize,
+ height: btnSize,
+ color: 0xff4444
+ });
+ shootShape.alpha = btnAlpha + 0.08;
+ shootBtn.addChild(shootShape);
+ var shootTxt = new Text2('SHOOT', {
+ size: 60,
+ fill: 0xffffff
+ });
+ shootTxt.anchor.set(0.5, 0.5);
+ shootBtn.addChild(shootTxt);
+ shootBtn.x = 2048 - btnSize - btnMargin;
+ shootBtn.y = 2732 - btnSize - btnMargin;
+ shootBtn.interactive = true;
+ shootBtn.down = function () {
+ if (game.phase !== 'play' || !game.player.isAlive) return;
+ // Shoot towards enemy if visible, else forward
+ var tx = game.player.x,
+ ty = game.player.y - 300;
+ // Try to find nearest enemy
+ var minDist = 99999,
+ target = null;
+ for (var i = 0; i < game.agents.length; ++i) {
+ var ag = game.agents[i];
+ if (ag === game.player || !ag.isAlive || ag.team === game.player.team) continue;
+ var dx = ag.x - game.player.x;
+ var dy = ag.y - game.player.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < minDist) {
+ minDist = dist;
+ target = ag;
+ }
+ }
+ if (target) {
+ tx = target.x;
+ ty = target.y;
+ }
+ game.player.shoot(tx, ty);
+ };
+ LK.gui.addChild(shootBtn);
+ game.shootBtn = shootBtn;
}
// --- Agents ---
function setupAgents() {
// Remove previous
@@ -361,51 +527,30 @@
game.addChild(player);
game.agents.push(player);
game.player = player;
// AI teammates and enemies (1v1 for MVP, can expand)
- var aiAgents = [];
- var tCount = 0;
- var ctCount = 0;
- var totalT = 5;
- var totalCT = 1; // Only 1 CT AI if player is T, else all others are T
- // Place AI agents in a spread formation
- for (var i = 0; i < 5; ++i) {
- var ai = new Agent();
- // If player is CT, add 5 T agents. If player is T, add 5 CT agents.
- if (game.isPlayerCT) {
- ai.setTeam('T');
- tCount++;
- // Spread spawn positions for T
- ai.x = 2048 / 2 + (i - 2) * 120;
- ai.y = 2732 - 700 + i % 2 * 80;
- } else {
- ai.setTeam('CT');
- ctCount++;
- // Spread spawn positions for CT
- ai.x = 2048 / 2 + (i - 2) * 120;
- ai.y = 700 + i % 2 * 80;
- }
- ai.setPlayer(false);
- game.addChild(ai);
- game.agents.push(ai);
- aiAgents.push(ai);
+ var ai = new Agent();
+ ai.setTeam(game.isPlayerCT ? 'T' : 'CT');
+ ai.setPlayer(false);
+ if (game.isPlayerCT) {
+ ai.x = 2048 / 2;
+ ai.y = 2732 - 700;
+ } else {
+ ai.x = 2048 / 2;
+ ai.y = 700;
}
- // Assign bomb to a random T at start
+ game.addChild(ai);
+ game.agents.push(ai);
+ // Assign bomb to T at start
for (var i = 0; i < game.agents.length; ++i) {
game.agents[i].hasBomb = false;
}
if (!game.isPlayerCT) {
player.hasBomb = true;
game.bombCarrier = player;
} else {
- // Pick a random T agent to carry the bomb
- var tAgents = [];
- for (var i = 0; i < aiAgents.length; ++i) {
- if (aiAgents[i].team === 'T') tAgents.push(aiAgents[i]);
- }
- var bombCarrierIdx = Math.floor(Math.random() * tAgents.length);
- tAgents[bombCarrierIdx].hasBomb = true;
- game.bombCarrier = tAgents[bombCarrierIdx];
+ ai.hasBomb = true;
+ game.bombCarrier = ai;
}
}
// --- Bomb ---
function setupBomb() {