/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.directionX = 0; self.directionY = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1; self.moveTimer = 0; self.moveDirection = 0; // 0=up, 1=right, 2=down, 3=left self.speed = 1; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; // Multi-directional movement pattern - can move in any direction self.moveTimer++; if (self.moveTimer > 120) { // Change direction every 2 seconds // Stop current tweens tween.stop(self, { x: true, y: true }); // Calculate movement range in all directions var leftBound = self.x - 100; var rightBound = self.x + 100; var upBound = self.y - 100; var downBound = self.y + 100; // Ensure bounds are within maze var gridLeftX = Math.floor(leftBound / cellSize); var gridRightX = Math.floor(rightBound / cellSize); var gridUpY = Math.floor((upBound - mazeOffsetY) / cellSize); var gridDownY = Math.floor((downBound - mazeOffsetY) / cellSize); var gridCurrentY = Math.floor((self.y - mazeOffsetY) / cellSize); var gridCurrentX = Math.floor(self.x / cellSize); // Adjust bounds to avoid walls while (gridLeftX >= 0 && maze[gridCurrentY] && maze[gridCurrentY][gridLeftX] === 1) { leftBound += cellSize; gridLeftX++; } while (gridRightX < mazeWidth && maze[gridCurrentY] && maze[gridCurrentY][gridRightX] === 1) { rightBound -= cellSize; gridRightX--; } while (gridUpY >= 0 && maze[gridUpY] && maze[gridUpY][gridCurrentX] === 1) { upBound += cellSize; gridUpY++; } while (gridDownY < mazeHeight && maze[gridDownY] && maze[gridDownY][gridCurrentX] === 1) { downBound -= cellSize; gridDownY--; } // Choose direction: 0 = right, 1 = left, 2 = up, 3 = down var direction = Math.floor(Math.random() * 4); var targetX = self.x; var targetY = self.y; switch (direction) { case 0: // right targetX = rightBound; // Flip to face right enemyGraphics.scaleX = Math.abs(enemyGraphics.scaleX); break; case 1: // left targetX = leftBound; // Flip to face left enemyGraphics.scaleX = -Math.abs(enemyGraphics.scaleX); break; case 2: // up targetY = upBound; break; case 3: // down targetY = downBound; break; } // Ensure target is valid if (!checkWallCollision(targetX, targetY)) { // Move to target position over 2 seconds tween(self, { x: targetX, y: targetY }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // After reaching target, choose a new random direction var newDirection = Math.floor(Math.random() * 4); var newTargetX = self.x; var newTargetY = self.y; switch (newDirection) { case 0: // right newTargetX = rightBound; // Flip to face right enemyGraphics.scaleX = Math.abs(enemyGraphics.scaleX); break; case 1: // left newTargetX = leftBound; // Flip to face left enemyGraphics.scaleX = -Math.abs(enemyGraphics.scaleX); break; case 2: // up newTargetY = upBound; break; case 3: // down newTargetY = downBound; break; } if (!checkWallCollision(newTargetX, newTargetY)) { tween(self, { x: newTargetX, y: newTargetY }, { duration: 2000, easing: tween.easeInOut }); } } }); } self.moveTimer = 0; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.health = 3; self.speed = 3; self.shootCooldown = 0; self.lastX = 0; self.lastY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.shootCooldown > 0) { self.shootCooldown--; } }; self.setDirection = function (deltaX) { if (deltaX > 0) { // Moving right - face right playerGraphics.scaleX = Math.abs(playerGraphics.scaleX); } else if (deltaX < 0) { // Moving left - face left playerGraphics.scaleX = -Math.abs(playerGraphics.scaleX); } }; self.shoot = function (targetX, targetY) { if (self.shootCooldown > 0) return; var dx = targetX - self.x; var dy = targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; bullet.directionX = dx / distance; bullet.directionY = dy / distance; bullet.lastX = bullet.x; bullet.lastY = bullet.y; bullets.push(bullet); game.addChild(bullet); self.shootCooldown = 15; LK.getSound('shoot').play(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game variables var player; var enemies = []; var bullets = []; var walls = []; var wall2s = []; var mazeWidth = 28; var mazeHeight = 22; var cellSize = 50; var maze = []; var mazeOffsetY = 150; // Consistent offset for maze positioning var currentBackground = null; var backgroundAssets = ['background1', 'background2', 'background3', 'background4', 'background5', 'background6', 'background7']; function setRandomBackground() { // Remove current background if exists if (currentBackground) { currentBackground.destroy(); } // Select random background var randomIndex = Math.floor(Math.random() * backgroundAssets.length); var selectedBackground = backgroundAssets[randomIndex]; // Create and add new background currentBackground = LK.getAsset(selectedBackground, { x: 0, y: 0, anchorX: 0, anchorY: 0 }); // Add background at the bottom layer game.addChildAt(currentBackground, 0); } // UI elements var healthText = new Text2('Health: 3', { size: 50, fill: 0xFF0000 }); healthText.anchor.set(0, 0); healthText.x = 150; healthText.y = 20; LK.gui.topLeft.addChild(healthText); var enemyCountText = new Text2('Enemies: 0', { size: 50, fill: 0xFFFF00 }); enemyCountText.anchor.set(1, 0); LK.gui.topRight.addChild(enemyCountText); // Maze generation function generateMaze() { // Initialize maze with all floors (open space) maze = []; for (var y = 0; y < mazeHeight; y++) { maze[y] = []; for (var x = 0; x < mazeWidth; x++) { maze[y][x] = 0; // 0 = floor, 1 = wall } } // Add border walls for (var x = 0; x < mazeWidth; x++) { maze[0][x] = 1; // top border maze[mazeHeight - 1][x] = 1; // bottom border } for (var y = 0; y < mazeHeight; y++) { maze[y][0] = 1; // left border maze[y][mazeWidth - 1] = 1; // right border } // Add a few scattered walls randomly for minimal obstacles var wallCount = Math.floor(mazeWidth * mazeHeight * 0.1); // Only 10% walls for (var i = 0; i < wallCount; i++) { var rx = Math.floor(Math.random() * (mazeWidth - 2)) + 1; var ry = Math.floor(Math.random() * (mazeHeight - 2)) + 1; maze[ry][rx] = 1; } } function createMazeWalls() { // Clear existing walls for (var i = walls.length - 1; i >= 0; i--) { walls[i].destroy(); } for (var i = wall2s.length - 1; i >= 0; i--) { wall2s[i].destroy(); } walls = []; wall2s = []; // Create wall objects for (var y = 0; y < mazeHeight; y++) { for (var x = 0; x < mazeWidth; x++) { if (maze[y][x] === 1) { // Randomly choose between wall types var useWall2 = Math.random() < 0.5; if (useWall2) { var wall = LK.getAsset('wall2', { x: x * cellSize + cellSize / 2, y: y * cellSize + cellSize / 2 + mazeOffsetY, anchorX: 0.5, anchorY: 0.5 }); wall2s.push(wall); game.addChild(wall); } else { var wall = LK.getAsset('wall', { x: x * cellSize + cellSize / 2, y: y * cellSize + cellSize / 2 + mazeOffsetY, anchorX: 0.5, anchorY: 0.5 }); walls.push(wall); game.addChild(wall); } } } } } function findFloorPosition() { var attempts = 0; while (attempts < 100) { var x = Math.floor(Math.random() * mazeWidth); var y = Math.floor(Math.random() * mazeHeight); if (maze[y][x] === 0) { return { x: x * cellSize + cellSize / 2, y: y * cellSize + cellSize / 2 + mazeOffsetY }; } attempts++; } // Fallback to a guaranteed floor position return { x: cellSize + cellSize / 2, y: cellSize + cellSize / 2 + mazeOffsetY }; } function checkWallCollision(x, y) { var gridX = Math.floor(x / cellSize); var gridY = Math.floor((y - mazeOffsetY) / cellSize); if (gridX < 0 || gridX >= mazeWidth || gridY < 0 || gridY >= mazeHeight) { return true; } return maze[gridY][gridX] === 1; } function spawnEnemies() { // Clear existing enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); } enemies = []; var enemyCount = 15; // Fixed enemy count for (var i = 0; i < enemyCount; i++) { var pos = findFloorPosition(); var enemy = new Enemy(); enemy.x = pos.x; enemy.y = pos.y; enemy.lastX = enemy.x; enemy.lastY = enemy.y; enemies.push(enemy); game.addChild(enemy); } updateEnemyCount(); } function initLevel() { setRandomBackground(); generateMaze(); createMazeWalls(); // Position player var playerPos = findFloorPosition(); player.x = playerPos.x; player.y = playerPos.y; player.lastX = player.x; player.lastY = player.y; spawnEnemies(); } function updateEnemyCount() { enemyCountText.setText('Enemies: ' + enemies.length); } function updateHealthText() { healthText.setText('Health: ' + player.health); } function nextMaze() { // Clear bullets for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].destroy(); bullets.splice(i, 1); } initLevel(); } // Initialize player player = new Player(); game.addChild(player); // Initialize first level initLevel(); updateHealthText(); // Start background music LK.playMusic('123huntin'); // Swipe controls var swipeStartX = 0; var swipeStartY = 0; var isSwipeActive = false; var moveX = 0; var moveY = 0; var minSwipeDistance = 30; // Double tap controls var lastTapTime = 0; var doubleTapDelay = 300; // milliseconds var lastTapX = 0; var lastTapY = 0; var tapDistance = 50; // max distance between taps to consider as double tap game.down = function (x, y, obj) { var currentTime = Date.now(); var timeDiff = currentTime - lastTapTime; var distanceDiff = Math.sqrt(Math.pow(x - lastTapX, 2) + Math.pow(y - lastTapY, 2)); // Check for double tap if (timeDiff < doubleTapDelay && distanceDiff < tapDistance) { // Double tap detected - shoot player.shoot(x, y); lastTapTime = 0; // Reset to prevent triple tap } else { // Single tap - prepare for swipe swipeStartX = x; swipeStartY = y; isSwipeActive = true; lastTapTime = currentTime; lastTapX = x; lastTapY = y; } }; game.move = function (x, y, obj) { if (isSwipeActive) { var swipeDeltaX = x - swipeStartX; var swipeDeltaY = y - swipeStartY; var swipeDistance = Math.sqrt(swipeDeltaX * swipeDeltaX + swipeDeltaY * swipeDeltaY); if (swipeDistance > minSwipeDistance) { // Normalize swipe direction and apply player speed moveX = swipeDeltaX / swipeDistance * player.speed; moveY = swipeDeltaY / swipeDistance * player.speed; } } }; game.up = function (x, y, obj) { isSwipeActive = false; moveX = 0; moveY = 0; }; // Main game loop game.update = function () { // Move player if (moveX !== 0 || moveY !== 0) { var newX = player.x + moveX; var newY = player.y + moveY; if (!checkWallCollision(newX, newY)) { // Update player direction for visual flipping player.setDirection(moveX); player.x = newX; player.y = newY; } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Check wall collision if (checkWallCollision(bullet.x, bullet.y)) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check bounds if (bullet.x < 0 || bullet.x > mazeWidth * cellSize || bullet.y < mazeOffsetY || bullet.y > mazeHeight * cellSize + mazeOffsetY) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check enemy collision var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { if (bullet.intersects(enemies[j])) { LK.getSound('enemyHit').play(); LK.effects.flashObject(enemies[j], 0xffffff, 200); // Store reference to the enemy before starting animation var enemyToDestroy = enemies[j]; var enemyIndex = j; // Add spinning animation before destroying enemy tween(enemyToDestroy, { rotation: enemyToDestroy.rotation + Math.PI * 4 // Spin 2 full rotations }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { // Destroy enemy after animation completes if (enemyToDestroy && enemyToDestroy.parent) { enemyToDestroy.destroy(); // Find and remove enemy from array safely var indexToRemove = enemies.indexOf(enemyToDestroy); if (indexToRemove !== -1) { enemies.splice(indexToRemove, 1); } updateEnemyCount(); } } }); bullet.destroy(); bullets.splice(i, 1); hitEnemy = true; break; } } if (hitEnemy) continue; } // Check player-enemy collision for (var i = enemies.length - 1; i >= 0; i--) { if (player.intersects(enemies[i])) { LK.getSound('playerHit').play(); LK.effects.flashObject(player, 0xff0000, 500); player.health--; updateHealthText(); // Calculate knockback direction (away from enemy) var knockbackX = player.x - enemies[i].x; var knockbackY = player.y - enemies[i].y; var distance = Math.sqrt(knockbackX * knockbackX + knockbackY * knockbackY); if (distance > 0) { // Normalize direction and apply knockback force knockbackX = knockbackX / distance * 80; knockbackY = knockbackY / distance * 80; // Calculate target position for knockback var targetX = player.x + knockbackX; var targetY = player.y + knockbackY; // Ensure target position is valid (not in wall) if (!checkWallCollision(targetX, targetY)) { // Create bouncing knockback animation tween(player, { x: targetX, y: targetY }, { duration: 200, easing: tween.bounceOut }); } } // Move enemy away to prevent multiple hits enemies[i].x += (Math.random() - 0.5) * 60; enemies[i].y += (Math.random() - 0.5) * 60; if (player.health <= 0) { LK.showGameOver(); return; } } } // Check win condition if (enemies.length === 0) { LK.showYouWin(); return; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.directionX = 0;
self.directionY = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.moveTimer = 0;
self.moveDirection = 0; // 0=up, 1=right, 2=down, 3=left
self.speed = 1;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Multi-directional movement pattern - can move in any direction
self.moveTimer++;
if (self.moveTimer > 120) {
// Change direction every 2 seconds
// Stop current tweens
tween.stop(self, {
x: true,
y: true
});
// Calculate movement range in all directions
var leftBound = self.x - 100;
var rightBound = self.x + 100;
var upBound = self.y - 100;
var downBound = self.y + 100;
// Ensure bounds are within maze
var gridLeftX = Math.floor(leftBound / cellSize);
var gridRightX = Math.floor(rightBound / cellSize);
var gridUpY = Math.floor((upBound - mazeOffsetY) / cellSize);
var gridDownY = Math.floor((downBound - mazeOffsetY) / cellSize);
var gridCurrentY = Math.floor((self.y - mazeOffsetY) / cellSize);
var gridCurrentX = Math.floor(self.x / cellSize);
// Adjust bounds to avoid walls
while (gridLeftX >= 0 && maze[gridCurrentY] && maze[gridCurrentY][gridLeftX] === 1) {
leftBound += cellSize;
gridLeftX++;
}
while (gridRightX < mazeWidth && maze[gridCurrentY] && maze[gridCurrentY][gridRightX] === 1) {
rightBound -= cellSize;
gridRightX--;
}
while (gridUpY >= 0 && maze[gridUpY] && maze[gridUpY][gridCurrentX] === 1) {
upBound += cellSize;
gridUpY++;
}
while (gridDownY < mazeHeight && maze[gridDownY] && maze[gridDownY][gridCurrentX] === 1) {
downBound -= cellSize;
gridDownY--;
}
// Choose direction: 0 = right, 1 = left, 2 = up, 3 = down
var direction = Math.floor(Math.random() * 4);
var targetX = self.x;
var targetY = self.y;
switch (direction) {
case 0:
// right
targetX = rightBound;
// Flip to face right
enemyGraphics.scaleX = Math.abs(enemyGraphics.scaleX);
break;
case 1:
// left
targetX = leftBound;
// Flip to face left
enemyGraphics.scaleX = -Math.abs(enemyGraphics.scaleX);
break;
case 2:
// up
targetY = upBound;
break;
case 3:
// down
targetY = downBound;
break;
}
// Ensure target is valid
if (!checkWallCollision(targetX, targetY)) {
// Move to target position over 2 seconds
tween(self, {
x: targetX,
y: targetY
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// After reaching target, choose a new random direction
var newDirection = Math.floor(Math.random() * 4);
var newTargetX = self.x;
var newTargetY = self.y;
switch (newDirection) {
case 0:
// right
newTargetX = rightBound;
// Flip to face right
enemyGraphics.scaleX = Math.abs(enemyGraphics.scaleX);
break;
case 1:
// left
newTargetX = leftBound;
// Flip to face left
enemyGraphics.scaleX = -Math.abs(enemyGraphics.scaleX);
break;
case 2:
// up
newTargetY = upBound;
break;
case 3:
// down
newTargetY = downBound;
break;
}
if (!checkWallCollision(newTargetX, newTargetY)) {
tween(self, {
x: newTargetX,
y: newTargetY
}, {
duration: 2000,
easing: tween.easeInOut
});
}
}
});
}
self.moveTimer = 0;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.speed = 3;
self.shootCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.setDirection = function (deltaX) {
if (deltaX > 0) {
// Moving right - face right
playerGraphics.scaleX = Math.abs(playerGraphics.scaleX);
} else if (deltaX < 0) {
// Moving left - face left
playerGraphics.scaleX = -Math.abs(playerGraphics.scaleX);
}
};
self.shoot = function (targetX, targetY) {
if (self.shootCooldown > 0) return;
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.directionX = dx / distance;
bullet.directionY = dy / distance;
bullet.lastX = bullet.x;
bullet.lastY = bullet.y;
bullets.push(bullet);
game.addChild(bullet);
self.shootCooldown = 15;
LK.getSound('shoot').play();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game variables
var player;
var enemies = [];
var bullets = [];
var walls = [];
var wall2s = [];
var mazeWidth = 28;
var mazeHeight = 22;
var cellSize = 50;
var maze = [];
var mazeOffsetY = 150; // Consistent offset for maze positioning
var currentBackground = null;
var backgroundAssets = ['background1', 'background2', 'background3', 'background4', 'background5', 'background6', 'background7'];
function setRandomBackground() {
// Remove current background if exists
if (currentBackground) {
currentBackground.destroy();
}
// Select random background
var randomIndex = Math.floor(Math.random() * backgroundAssets.length);
var selectedBackground = backgroundAssets[randomIndex];
// Create and add new background
currentBackground = LK.getAsset(selectedBackground, {
x: 0,
y: 0,
anchorX: 0,
anchorY: 0
});
// Add background at the bottom layer
game.addChildAt(currentBackground, 0);
}
// UI elements
var healthText = new Text2('Health: 3', {
size: 50,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
healthText.x = 150;
healthText.y = 20;
LK.gui.topLeft.addChild(healthText);
var enemyCountText = new Text2('Enemies: 0', {
size: 50,
fill: 0xFFFF00
});
enemyCountText.anchor.set(1, 0);
LK.gui.topRight.addChild(enemyCountText);
// Maze generation
function generateMaze() {
// Initialize maze with all floors (open space)
maze = [];
for (var y = 0; y < mazeHeight; y++) {
maze[y] = [];
for (var x = 0; x < mazeWidth; x++) {
maze[y][x] = 0; // 0 = floor, 1 = wall
}
}
// Add border walls
for (var x = 0; x < mazeWidth; x++) {
maze[0][x] = 1; // top border
maze[mazeHeight - 1][x] = 1; // bottom border
}
for (var y = 0; y < mazeHeight; y++) {
maze[y][0] = 1; // left border
maze[y][mazeWidth - 1] = 1; // right border
}
// Add a few scattered walls randomly for minimal obstacles
var wallCount = Math.floor(mazeWidth * mazeHeight * 0.1); // Only 10% walls
for (var i = 0; i < wallCount; i++) {
var rx = Math.floor(Math.random() * (mazeWidth - 2)) + 1;
var ry = Math.floor(Math.random() * (mazeHeight - 2)) + 1;
maze[ry][rx] = 1;
}
}
function createMazeWalls() {
// Clear existing walls
for (var i = walls.length - 1; i >= 0; i--) {
walls[i].destroy();
}
for (var i = wall2s.length - 1; i >= 0; i--) {
wall2s[i].destroy();
}
walls = [];
wall2s = [];
// Create wall objects
for (var y = 0; y < mazeHeight; y++) {
for (var x = 0; x < mazeWidth; x++) {
if (maze[y][x] === 1) {
// Randomly choose between wall types
var useWall2 = Math.random() < 0.5;
if (useWall2) {
var wall = LK.getAsset('wall2', {
x: x * cellSize + cellSize / 2,
y: y * cellSize + cellSize / 2 + mazeOffsetY,
anchorX: 0.5,
anchorY: 0.5
});
wall2s.push(wall);
game.addChild(wall);
} else {
var wall = LK.getAsset('wall', {
x: x * cellSize + cellSize / 2,
y: y * cellSize + cellSize / 2 + mazeOffsetY,
anchorX: 0.5,
anchorY: 0.5
});
walls.push(wall);
game.addChild(wall);
}
}
}
}
}
function findFloorPosition() {
var attempts = 0;
while (attempts < 100) {
var x = Math.floor(Math.random() * mazeWidth);
var y = Math.floor(Math.random() * mazeHeight);
if (maze[y][x] === 0) {
return {
x: x * cellSize + cellSize / 2,
y: y * cellSize + cellSize / 2 + mazeOffsetY
};
}
attempts++;
}
// Fallback to a guaranteed floor position
return {
x: cellSize + cellSize / 2,
y: cellSize + cellSize / 2 + mazeOffsetY
};
}
function checkWallCollision(x, y) {
var gridX = Math.floor(x / cellSize);
var gridY = Math.floor((y - mazeOffsetY) / cellSize);
if (gridX < 0 || gridX >= mazeWidth || gridY < 0 || gridY >= mazeHeight) {
return true;
}
return maze[gridY][gridX] === 1;
}
function spawnEnemies() {
// Clear existing enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
enemies = [];
var enemyCount = 15; // Fixed enemy count
for (var i = 0; i < enemyCount; i++) {
var pos = findFloorPosition();
var enemy = new Enemy();
enemy.x = pos.x;
enemy.y = pos.y;
enemy.lastX = enemy.x;
enemy.lastY = enemy.y;
enemies.push(enemy);
game.addChild(enemy);
}
updateEnemyCount();
}
function initLevel() {
setRandomBackground();
generateMaze();
createMazeWalls();
// Position player
var playerPos = findFloorPosition();
player.x = playerPos.x;
player.y = playerPos.y;
player.lastX = player.x;
player.lastY = player.y;
spawnEnemies();
}
function updateEnemyCount() {
enemyCountText.setText('Enemies: ' + enemies.length);
}
function updateHealthText() {
healthText.setText('Health: ' + player.health);
}
function nextMaze() {
// Clear bullets
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].destroy();
bullets.splice(i, 1);
}
initLevel();
}
// Initialize player
player = new Player();
game.addChild(player);
// Initialize first level
initLevel();
updateHealthText();
// Start background music
LK.playMusic('123huntin');
// Swipe controls
var swipeStartX = 0;
var swipeStartY = 0;
var isSwipeActive = false;
var moveX = 0;
var moveY = 0;
var minSwipeDistance = 30;
// Double tap controls
var lastTapTime = 0;
var doubleTapDelay = 300; // milliseconds
var lastTapX = 0;
var lastTapY = 0;
var tapDistance = 50; // max distance between taps to consider as double tap
game.down = function (x, y, obj) {
var currentTime = Date.now();
var timeDiff = currentTime - lastTapTime;
var distanceDiff = Math.sqrt(Math.pow(x - lastTapX, 2) + Math.pow(y - lastTapY, 2));
// Check for double tap
if (timeDiff < doubleTapDelay && distanceDiff < tapDistance) {
// Double tap detected - shoot
player.shoot(x, y);
lastTapTime = 0; // Reset to prevent triple tap
} else {
// Single tap - prepare for swipe
swipeStartX = x;
swipeStartY = y;
isSwipeActive = true;
lastTapTime = currentTime;
lastTapX = x;
lastTapY = y;
}
};
game.move = function (x, y, obj) {
if (isSwipeActive) {
var swipeDeltaX = x - swipeStartX;
var swipeDeltaY = y - swipeStartY;
var swipeDistance = Math.sqrt(swipeDeltaX * swipeDeltaX + swipeDeltaY * swipeDeltaY);
if (swipeDistance > minSwipeDistance) {
// Normalize swipe direction and apply player speed
moveX = swipeDeltaX / swipeDistance * player.speed;
moveY = swipeDeltaY / swipeDistance * player.speed;
}
}
};
game.up = function (x, y, obj) {
isSwipeActive = false;
moveX = 0;
moveY = 0;
};
// Main game loop
game.update = function () {
// Move player
if (moveX !== 0 || moveY !== 0) {
var newX = player.x + moveX;
var newY = player.y + moveY;
if (!checkWallCollision(newX, newY)) {
// Update player direction for visual flipping
player.setDirection(moveX);
player.x = newX;
player.y = newY;
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Check wall collision
if (checkWallCollision(bullet.x, bullet.y)) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bounds
if (bullet.x < 0 || bullet.x > mazeWidth * cellSize || bullet.y < mazeOffsetY || bullet.y > mazeHeight * cellSize + mazeOffsetY) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check enemy collision
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
if (bullet.intersects(enemies[j])) {
LK.getSound('enemyHit').play();
LK.effects.flashObject(enemies[j], 0xffffff, 200);
// Store reference to the enemy before starting animation
var enemyToDestroy = enemies[j];
var enemyIndex = j;
// Add spinning animation before destroying enemy
tween(enemyToDestroy, {
rotation: enemyToDestroy.rotation + Math.PI * 4 // Spin 2 full rotations
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Destroy enemy after animation completes
if (enemyToDestroy && enemyToDestroy.parent) {
enemyToDestroy.destroy();
// Find and remove enemy from array safely
var indexToRemove = enemies.indexOf(enemyToDestroy);
if (indexToRemove !== -1) {
enemies.splice(indexToRemove, 1);
}
updateEnemyCount();
}
}
});
bullet.destroy();
bullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (hitEnemy) continue;
}
// Check player-enemy collision
for (var i = enemies.length - 1; i >= 0; i--) {
if (player.intersects(enemies[i])) {
LK.getSound('playerHit').play();
LK.effects.flashObject(player, 0xff0000, 500);
player.health--;
updateHealthText();
// Calculate knockback direction (away from enemy)
var knockbackX = player.x - enemies[i].x;
var knockbackY = player.y - enemies[i].y;
var distance = Math.sqrt(knockbackX * knockbackX + knockbackY * knockbackY);
if (distance > 0) {
// Normalize direction and apply knockback force
knockbackX = knockbackX / distance * 80;
knockbackY = knockbackY / distance * 80;
// Calculate target position for knockback
var targetX = player.x + knockbackX;
var targetY = player.y + knockbackY;
// Ensure target position is valid (not in wall)
if (!checkWallCollision(targetX, targetY)) {
// Create bouncing knockback animation
tween(player, {
x: targetX,
y: targetY
}, {
duration: 200,
easing: tween.bounceOut
});
}
}
// Move enemy away to prevent multiple hits
enemies[i].x += (Math.random() - 0.5) * 60;
enemies[i].y += (Math.random() - 0.5) * 60;
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
// Check win condition
if (enemies.length === 0) {
LK.showYouWin();
return;
}
};
2d big size side scroller wild warthog image. In-Game asset. 2d. High contrast. No shadows
2d hroizontal sidescroller average year country man is the hunter. holld shootgun and ready shoot. In-Game asset. 2d. High contrast. No shadows
2d side scroller anime green bushs asset. In-Game asset. 2d. High contrast. No shadows