User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'destroy')' in or related to this line: 'enemies[j].destroy();' Line Number: 525
User prompt
buat aturan player menang setelah membunuh semua enemy
User prompt
add new wall asset
User prompt
create an animation of the enemy spinning around when shot ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
buat animasi player terpental saat terkena enemy ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
rubah maze menjadi lebih simple
User prompt
kurangi jumlah wall di dalam maze
User prompt
hapus aturan logika level. saat satu level selesai beralih ke maze selanjutnya tanpa ada rule level
User prompt
add more enemy on maze
User prompt
fix music background
User prompt
kecilkan sedikit luas maze
User prompt
buat luas floor 2 kali luas dari yang awal
User prompt
buat tujuh background yang bisa random muncul
User prompt
perbaiki level yang problem yang tiba tiba meloncat ke atas
User prompt
buat karakter bisa berbalik kekanan atau ke kiri ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make enemy 2 times move faster ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
the enemy can flip turn to move right or left ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
enemy bisa berbalik ke kanan atau ke kiri ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
enemy bisa bergerak berbalik ke depan dan belakang ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
pindahkan maze di bawah tombol pause
User prompt
ubah maze bentuk horizontal
User prompt
double tap control player can shoot enemy
User prompt
hilangkan tembakkan saat swipe
User prompt
tap for shoot
User prompt
ubah kontrol pelayer ke swipe
/****
* 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;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -490,19 +490,28 @@
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(enemies[j], {
- rotation: enemies[j].rotation + Math.PI * 4 // Spin 2 full rotations
+ 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
- enemies[j].destroy();
- enemies.splice(j, 1);
- updateEnemyCount();
+ 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);
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