User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(effect).to({' Line Number: 172
User prompt
Make the zombies be able to kill you and then add a jump scare.
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(effect).to({' Line Number: 170
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(effect).to({' Line Number: 169
User prompt
Please fix the bug: 'TypeError: tween.to is not a function' in or related to this line: 'tween.to(effect, {' Line Number: 169
User prompt
Make a golden zombie segment
User prompt
Make sure the monsters can move around and also make them follow you and try and kill you.
User prompt
Add the skeleton, and the golden zombie, and the golden skeleton.
User prompt
Make the maze a lot harder
User prompt
Add the monsters back in
User prompt
i can't move can you like do it where like you when you tap on the place it moves to that place
User prompt
Make a way to move, please!
User prompt
Make it a maze instead of that. It's a big maze and the character moves through the maze and cannot pass through walls.
Code edit (1 edits merged)
Please save this source code
User prompt
Monster Mash: Undead Defense
User prompt
Monsters are the zombie, the skeleton, the golden zombie, the golden skeleton.
Initial prompt
It was like the first game but with a higher difficulty and also more monsters.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Monster class for AI movement and attack
var Monster = Container.expand(function () {
var self = Container.call(this);
self.type = null;
self.col = 0;
self.row = 0;
self.targetCol = 0;
self.targetRow = 0;
self.lastCol = 0;
self.lastRow = 0;
self.moveSpeed = 8; // px per frame, slower than player
self.path = null;
self.pathStepIndex = 0;
self.isMoving = false;
self.attackCooldown = 0;
self.attackDelay = 60; // frames between attacks
self.asset = null;
// Set up monster asset
self.init = function (type, col, row) {
self.type = type;
self.col = col;
self.row = row;
self.targetCol = col;
self.targetRow = row;
var assetId = type;
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
width: MAZE_CELL_SIZE * 0.8,
height: MAZE_CELL_SIZE * 0.8
});
self.x = col * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
self.y = row * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
};
// Find path to player using BFS
self.findPathToPlayer = function (playerCol, playerRow) {
// Defensive: check bounds
if (playerCol < 0 || playerCol >= MAZE_COLS || playerRow < 0 || playerRow >= MAZE_ROWS) return null;
if (maze[playerRow][playerCol] === 1) return null;
var queue = [];
var visited = [];
for (var y = 0; y < MAZE_ROWS; y++) {
visited[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
visited[y][x] = false;
}
}
var prev = [];
for (var y = 0; y < MAZE_ROWS; y++) {
prev[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
prev[y][x] = null;
}
}
queue.push({
col: self.col,
row: self.row
});
visited[self.row][self.col] = true;
var found = false;
while (queue.length > 0) {
var curr = queue.shift();
if (curr.col === playerCol && curr.row === playerRow) {
found = true;
break;
}
var dirs = [{
dc: 0,
dr: -1
},
// up
{
dc: 0,
dr: 1
},
// down
{
dc: -1,
dr: 0
},
// left
{
dc: 1,
dr: 0
} // right
];
for (var d = 0; d < dirs.length; d++) {
var nc = curr.col + dirs[d].dc;
var nr = curr.row + dirs[d].dr;
if (nc >= 0 && nc < MAZE_COLS && nr >= 0 && nr < MAZE_ROWS && !visited[nr][nc] && maze[nr][nc] !== 1) {
queue.push({
col: nc,
row: nr
});
visited[nr][nc] = true;
prev[nr][nc] = {
col: curr.col,
row: curr.row
};
}
}
}
if (!found) return null;
// Reconstruct path
var path = [];
var currCol = playerCol,
currRow = playerRow;
while (!(currCol === self.col && currRow === self.row)) {
path.unshift({
col: currCol,
row: currRow
});
var p = prev[currRow][currCol];
currCol = p.col;
currRow = p.row;
}
return path;
};
// Monster update: move toward player, attack if adjacent
self.update = function () {
// Track last position for event logic
self.lastCol = self.col;
self.lastRow = self.row;
// Only recalc path every 15 frames for performance
if (LK.ticks % 15 === 0 || !self.path || self.path.length === 0) {
self.path = self.findPathToPlayer(charCol, charRow);
self.pathStepIndex = 0;
}
// If adjacent to player, attack
var dx = Math.abs(self.col - charCol);
var dy = Math.abs(self.row - charRow);
if (dx + dy === 1) {
// Attack cooldown
if (self.attackCooldown <= 0) {
// Show attack effect
var effect = LK.getAsset('attackEffect', {
anchorX: 0.5,
anchorY: 0.5,
x: charNode.x,
y: charNode.y,
width: MAZE_CELL_SIZE * 0.7,
height: MAZE_CELL_SIZE * 0.7
});
effect.alpha = 1;
game.addChild(effect);
// Defensive: ensure effect is defined and tween is a function
if (effect && typeof tween === "function" && typeof tween(effect).to === "function") {
tween(effect).to({
alpha: 0
}, 400).onComplete(function () {
effect.destroy();
});
}
// Flash screen red and show jump scare before game over
LK.effects.flashScreen(0xff0000, 800);
// Create a jump scare overlay (big zombie face in center, fades in/out)
var jumpScare = LK.getAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT / 2,
width: GAME_WIDTH * 0.8,
height: GAME_WIDTH * 0.8
});
jumpScare.alpha = 0;
game.addChild(jumpScare);
// Fade in, then out, then game over
if (typeof tween === "function") {
tween(jumpScare).to({
alpha: 1
}, 120).onComplete(function () {
tween(jumpScare).to({
alpha: 0
}, 400).onComplete(function () {
jumpScare.destroy();
LK.showGameOver();
});
});
} else {
// Fallback: just show game over
LK.showGameOver();
}
self.attackCooldown = self.attackDelay;
}
} else if (self.path && self.path.length > 0 && self.pathStepIndex < self.path.length) {
// Move toward next cell in path
var next = self.path[self.pathStepIndex];
var targetX = next.col * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
var targetY = next.row * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
var ddx = targetX - self.x;
var ddy = targetY - self.y;
var dist = Math.sqrt(ddx * ddx + ddy * ddy);
if (dist > 2) {
var step = Math.min(self.moveSpeed, dist);
self.x += ddx / dist * step;
self.y += ddy / dist * step;
} else {
// Snap to cell
self.x = targetX;
self.y = targetY;
self.col = next.col;
self.row = next.row;
self.pathStepIndex++;
}
}
if (self.attackCooldown > 0) self.attackCooldown--;
};
return self;
});
/****
* Initialize Game
****/
// No classes needed for maze logic
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Maze configuration
// 0 = empty, 1 = wall, 2 = start, 3 = goal
// Each cell is 128x128 px, so 16x21 grid fits in 2048x2688
var MAZE_CELL_SIZE = 128;
var MAZE_COLS = 16;
var MAZE_ROWS = 21;
// Example maze: outer walls, a few inner walls, start at (1,1), goal at (14,19)
var maze = [];
for (var y = 0; y < MAZE_ROWS; y++) {
maze[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
if (y === 0 || y === MAZE_ROWS - 1 || x === 0 || x === MAZE_COLS - 1) {
maze[y][x] = 1; // border wall
} else {
maze[y][x] = 0; // empty
}
}
}
// Add a much harder maze pattern with more inner walls and dead ends
for (var i = 2; i < 14; i++) {
maze[3][i] = 1;
maze[7][i] = 1;
maze[12][i] = 1;
maze[16][i] = 1;
}
// Add vertical walls and dead ends
for (var i = 2; i < 19; i++) {
if (i !== 7 && i !== 12) maze[i][4] = 1;
if (i !== 3 && i !== 16) maze[i][11] = 1;
}
for (var i = 5; i < 11; i++) {
maze[9][i] = 1;
}
for (var i = 6; i < 15; i++) {
if (i !== 10) maze[15][i] = 1;
}
for (var i = 2; i < 8; i++) {
maze[i][7] = 1;
}
for (var i = 13; i < 19; i++) {
maze[i][8] = 1;
}
maze[5][2] = 1;
maze[6][2] = 1;
maze[8][2] = 1;
maze[10][2] = 1;
maze[14][2] = 1;
maze[18][2] = 1;
maze[2][13] = 1;
maze[4][13] = 1;
maze[6][13] = 1;
maze[8][13] = 1;
maze[10][13] = 1;
maze[14][13] = 1;
maze[18][13] = 1;
maze[1][1] = 2; // start
maze[19][14] = 3; // goal
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFF700
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Draw maze walls and monsters
var wallNodes = [];
var monsterNodes = [];
// Place monsters at specific hard maze locations for challenge
var monsterSpawns = [{
type: 'skeleton',
col: 5,
row: 5
}, {
type: 'goldenZombie',
col: 10,
row: 10
}, {
type: 'goldenSkeleton',
col: 7,
row: 15
}, {
type: 'goldenZombie',
col: 12,
row: 6
}, {
type: 'goldenZombie',
col: 3,
row: 17
}];
for (var y = 0; y < MAZE_ROWS; y++) {
for (var x = 0; x < MAZE_COLS; x++) {
if (maze[y][x] === 1) {
var wall = LK.getAsset('base', {
anchorX: 0.5,
anchorY: 0.5,
x: x * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2,
y: y * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2,
width: MAZE_CELL_SIZE,
height: MAZE_CELL_SIZE
});
wallNodes.push(wall);
game.addChild(wall);
}
if (maze[y][x] === 3) {
// Goal marker
var goalNode = LK.getAsset('goldenZombie', {
anchorX: 0.5,
anchorY: 0.5,
x: x * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2,
y: y * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2,
width: MAZE_CELL_SIZE,
height: MAZE_CELL_SIZE
});
game.addChild(goalNode);
}
// Place monsters at their spawn locations
for (var mi = 0; mi < monsterSpawns.length; mi++) {
var m = monsterSpawns[mi];
if (m.col === x && m.row === y) {
var monster = new Monster();
monster.init(m.type, x, y);
monsterNodes.push(monster);
game.addChild(monster);
}
}
}
}
// Character
var charNode = LK.getAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5,
width: MAZE_CELL_SIZE * 0.8,
height: MAZE_CELL_SIZE * 0.8
});
game.addChild(charNode);
// Find start position
var charCol = 1,
charRow = 1;
for (var y = 0; y < MAZE_ROWS; y++) {
for (var x = 0; x < MAZE_COLS; x++) {
if (maze[y][x] === 2) {
charCol = x;
charRow = y;
}
}
}
charNode.x = charCol * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
charNode.y = charRow * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
// Movement state
var moveTargetCol = charCol;
var moveTargetRow = charRow;
var isMoving = false;
var moveSpeed = 16; // px per frame
// Touch/drag movement: tap or drag to adjacent cell
function getCellFromPos(x, y) {
var col = Math.floor(x / MAZE_CELL_SIZE);
var row = Math.floor(y / MAZE_CELL_SIZE);
return {
col: col,
row: row
};
}
// Simple BFS pathfinding to allow tap-to-move to any reachable cell
function findPath(startCol, startRow, endCol, endRow) {
// Defensive: check bounds
if (endCol < 0 || endCol >= MAZE_COLS || endRow < 0 || endRow >= MAZE_ROWS) return null;
if (maze[endRow][endCol] === 1) return null;
var queue = [];
var visited = [];
for (var y = 0; y < MAZE_ROWS; y++) {
visited[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
visited[y][x] = false;
}
}
var prev = [];
for (var y = 0; y < MAZE_ROWS; y++) {
prev[y] = [];
for (var x = 0; x < MAZE_COLS; x++) {
prev[y][x] = null;
}
}
queue.push({
col: startCol,
row: startRow
});
visited[startRow][startCol] = true;
var found = false;
while (queue.length > 0) {
var curr = queue.shift();
if (curr.col === endCol && curr.row === endRow) {
found = true;
break;
}
var dirs = [{
dc: 0,
dr: -1
},
// up
{
dc: 0,
dr: 1
},
// down
{
dc: -1,
dr: 0
},
// left
{
dc: 1,
dr: 0
} // right
];
for (var d = 0; d < dirs.length; d++) {
var nc = curr.col + dirs[d].dc;
var nr = curr.row + dirs[d].dr;
if (nc >= 0 && nc < MAZE_COLS && nr >= 0 && nr < MAZE_ROWS && !visited[nr][nc] && maze[nr][nc] !== 1) {
queue.push({
col: nc,
row: nr
});
visited[nr][nc] = true;
prev[nr][nc] = {
col: curr.col,
row: curr.row
};
}
}
}
if (!found) return null;
// Reconstruct path
var path = [];
var currCol = endCol,
currRow = endRow;
while (!(currCol === startCol && currRow === startRow)) {
path.unshift({
col: currCol,
row: currRow
});
var p = prev[currRow][currCol];
currCol = p.col;
currRow = p.row;
}
return path;
}
var pathToFollow = null;
var pathStepIndex = 0;
game.down = function (x, y, obj) {
// Prevent new move if already moving
if (isMoving) return;
var cell = getCellFromPos(x, y);
// Defensive: check bounds
if (cell.col < 0 || cell.col >= MAZE_COLS || cell.row < 0 || cell.row >= MAZE_ROWS) return;
// Don't move if already at that cell
if (cell.col === charCol && cell.row === charRow) return;
// Find path
var path = findPath(charCol, charRow, cell.col, cell.row);
if (path && path.length > 0) {
pathToFollow = path;
pathStepIndex = 0;
moveTargetCol = pathToFollow[0].col;
moveTargetRow = pathToFollow[0].row;
isMoving = true;
}
};
game.move = function (x, y, obj) {
// Only allow drag-move if not already moving
if (!isMoving) {
game.down(x, y, obj);
}
};
game.up = function (x, y, obj) {
// No-op
};
game.update = function () {
// Move character toward target cell
var targetX = moveTargetCol * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
var targetY = moveTargetRow * MAZE_CELL_SIZE + MAZE_CELL_SIZE / 2;
var dx = targetX - charNode.x;
var dy = targetY - charNode.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (isMoving && dist > 2) {
var step = Math.min(moveSpeed, dist);
charNode.x += dx / dist * step;
charNode.y += dy / dist * step;
} else if (isMoving) {
// Snap to cell
charNode.x = targetX;
charNode.y = targetY;
charCol = moveTargetCol;
charRow = moveTargetRow;
// If following a path, advance to next step
if (typeof pathToFollow !== "undefined" && pathToFollow && pathStepIndex < pathToFollow.length - 1) {
pathStepIndex++;
moveTargetCol = pathToFollow[pathStepIndex].col;
moveTargetRow = pathToFollow[pathStepIndex].row;
// Remain isMoving = true
} else {
isMoving = false;
pathToFollow = null;
pathStepIndex = 0;
// Check for goal
if (maze[charRow][charCol] === 3) {
LK.effects.flashScreen(0x00ff00, 800);
LK.showYouWin();
}
}
}
// Update all monsters
for (var i = 0; i < monsterNodes.length; i++) {
if (monsterNodes[i] && typeof monsterNodes[i].update === "function") {
monsterNodes[i].update();
}
}
// Show current cell in score text (for debugging movement)
scoreTxt.setText("Cell: " + charCol + "," + charRow);
}; ===================================================================
--- original.js
+++ change.js
@@ -151,9 +151,9 @@
});
effect.alpha = 1;
game.addChild(effect);
// Defensive: ensure effect is defined and tween is a function
- if (effect && typeof tween === "function") {
+ if (effect && typeof tween === "function" && typeof tween(effect).to === "function") {
tween(effect).to({
alpha: 0
}, 400).onComplete(function () {
effect.destroy();
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Monster Mash: Undead Defense" and with the description "Defend your base from zombies, skeletons, and their golden counterparts by tapping or dragging to attack. Survive waves and score points!". No text on banner!
Zombie with long red eyes. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A zombie with long eyes but everything is golden. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A golden terrifying skeleton. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A zombie fixed with a skeleton. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Ghost. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Heart. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Monster with big hands and ginger hair. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat