User prompt
If our character stands in front of a skeleton, let the skeleton stand still.
User prompt
If our character encounters a skeleton, the skeleton should stay where it is.
User prompt
No skeleton spawn where our character is born
User prompt
The kill button should appear when you get close to the skeleton.
User prompt
Sword swinging is currently buggy, when you click once there should be a very short waiting time and the sword should not rotate around itself continuously. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add sword swing effect ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Skeletons have a very large hitbox and move very fast.
User prompt
Adjust skeletons hitbox properly
User prompt
character can kill monster with kill button not with double click
User prompt
If the character can kill all the skeletons he can open the chest
User prompt
add key and chest and door must open with key
User prompt
give the character a sword
User prompt
If the character double clicks, he can damage the skeletons.
User prompt
make a start screen
User prompt
player can walk with mouse
Code edit (1 edits merged)
Please save this source code
User prompt
Dungeon Dash
Initial prompt
make me a dungeon type game
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Door class (for next room)
var Door = Container.expand(function () {
var self = Container.call(this);
// Attach door asset (purple box)
var doorSprite = self.attachAsset('door', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = doorSprite.width;
self.height = doorSprite.height;
return self;
});
// Hero class
var Hero = Container.expand(function () {
var self = Container.call(this);
// Attach hero asset (red box)
var heroSprite = self.attachAsset('hero', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = heroSprite.width;
self.height = heroSprite.height;
// Hero stats
self.maxHealth = 3;
self.health = self.maxHealth;
self.invincible = false;
self.invincibleTimer = 0;
// Flash when hit
self.flash = function () {
tween(heroSprite, {
tint: 0xffffff
}, {
duration: 100,
onFinish: function onFinish() {
tween(heroSprite, {
tint: 0xd83318
}, {
duration: 200
});
}
});
};
// Take damage
self.takeDamage = function () {
if (self.invincible) return;
self.health -= 1;
self.flash();
self.invincible = true;
self.invincibleTimer = 60; // 1 second at 60fps
LK.effects.flashObject(self, 0xff0000, 300);
updateHealthDisplay();
if (self.health <= 0) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
};
// Heal
self.heal = function () {
if (self.health < self.maxHealth) {
self.health += 1;
updateHealthDisplay();
LK.effects.flashObject(self, 0x83de44, 300);
}
};
// Called every tick
self.update = function () {
if (self.invincible) {
self.invincibleTimer--;
if (self.invincibleTimer <= 0) {
self.invincible = false;
}
}
};
return self;
});
// Monster class
var Monster = Container.expand(function () {
var self = Container.call(this);
// Attach monster asset (green ellipse)
var monsterSprite = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = monsterSprite.width;
self.height = monsterSprite.height;
// Movement direction
self.vx = 0;
self.vy = 0;
self.speed = 3 + Math.random() * 2;
// Set random direction
self.setRandomDirection = function () {
var angle = Math.random() * Math.PI * 2;
self.vx = Math.cos(angle) * self.speed;
self.vy = Math.sin(angle) * self.speed;
};
self.setRandomDirection();
// Called every tick
self.update = function () {
self.x += self.vx;
self.y += self.vy;
// Bounce off room walls
if (self.x < roomBounds.x + self.width / 2) {
self.x = roomBounds.x + self.width / 2;
self.vx *= -1;
}
if (self.x > roomBounds.x + roomBounds.width - self.width / 2) {
self.x = roomBounds.x + roomBounds.width - self.width / 2;
self.vx *= -1;
}
if (self.y < roomBounds.y + self.height / 2) {
self.y = roomBounds.y + self.height / 2;
self.vy *= -1;
}
if (self.y > roomBounds.y + roomBounds.height - self.height / 2) {
self.y = roomBounds.y + roomBounds.height - self.height / 2;
self.vy *= -1;
}
};
return self;
});
// Trap class
var Trap = Container.expand(function () {
var self = Container.call(this);
// Attach trap asset (yellow box)
var trapSprite = self.attachAsset('trap', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = trapSprite.width;
self.height = trapSprite.height;
return self;
});
// Treasure class
var Treasure = Container.expand(function () {
var self = Container.call(this);
// Attach treasure asset (blue ellipse)
var treasureSprite = self.attachAsset('treasure', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = treasureSprite.width;
self.height = treasureSprite.height;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Tween plugin for animations
// Room bounds (centered, with margin)
var roomMargin = 120;
var roomBounds = {
x: roomMargin,
y: roomMargin + 100,
// leave top 100px for menu
width: 2048 - roomMargin * 2,
height: 2732 - roomMargin * 2 - 100
};
// Game state
var hero;
var monsters = [];
var traps = [];
var treasures = [];
var door;
var draggingHero = false;
var lastMoveX = 0,
lastMoveY = 0;
var currentRoom = 1;
var maxRooms = 5;
var treasuresCollected = 0;
var monstersDefeated = 0;
var roomCleared = false;
// GUI elements
var scoreTxt = new Text2('Score: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var healthTxt = new Text2('♥♥♥', {
size: 90,
fill: 0xFF4444
});
healthTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(healthTxt);
healthTxt.y = 100;
// Helper to update health display
function updateHealthDisplay() {
var hearts = '';
for (var i = 0; i < hero.maxHealth; i++) {
hearts += i < hero.health ? '♥' : '♡';
}
healthTxt.setText(hearts);
}
// Helper to update score display
function updateScoreDisplay() {
var score = treasuresCollected * 10 + monstersDefeated * 5;
scoreTxt.setText('Score: ' + score);
}
// Helper to clear room
function clearRoom() {
for (var i = 0; i < monsters.length; i++) monsters[i].destroy();
for (var i = 0; i < traps.length; i++) traps[i].destroy();
for (var i = 0; i < treasures.length; i++) treasures[i].destroy();
monsters = [];
traps = [];
treasures = [];
if (door) {
door.destroy();
door = null;
}
roomCleared = false;
}
// Helper to generate a room
function generateRoom(roomNum) {
clearRoom();
// Place hero at entrance (bottom center)
hero.x = roomBounds.x + roomBounds.width / 2;
hero.y = roomBounds.y + roomBounds.height - hero.height;
// Place monsters
var monsterCount = 2 + roomNum;
for (var i = 0; i < monsterCount; i++) {
var m = new Monster();
m.x = roomBounds.x + 100 + Math.random() * (roomBounds.width - 200);
m.y = roomBounds.y + 200 + Math.random() * (roomBounds.height - 400);
monsters.push(m);
game.addChild(m);
}
// Place traps
var trapCount = 1 + Math.floor(roomNum / 2);
for (var i = 0; i < trapCount; i++) {
var t = new Trap();
t.x = roomBounds.x + 100 + Math.random() * (roomBounds.width - 200);
t.y = roomBounds.y + 200 + Math.random() * (roomBounds.height - 400);
traps.push(t);
game.addChild(t);
}
// Place treasures
var treasureCount = 1 + Math.floor(roomNum / 2);
for (var i = 0; i < treasureCount; i++) {
var tr = new Treasure();
tr.x = roomBounds.x + 100 + Math.random() * (roomBounds.width - 200);
tr.y = roomBounds.y + 200 + Math.random() * (roomBounds.height - 400);
treasures.push(tr);
game.addChild(tr);
}
// Place door (top center)
door = new Door();
door.x = roomBounds.x + roomBounds.width / 2;
door.y = roomBounds.y + door.height / 2;
game.addChild(door);
door.visible = false; // Only show when room is cleared
roomCleared = false;
}
// Create hero
hero = new Hero();
game.addChild(hero);
updateHealthDisplay();
// Start first room
generateRoom(currentRoom);
updateScoreDisplay();
// Dragging logic
game.down = function (x, y, obj) {
// Only start drag if touch is on hero
var local = hero.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x > -hero.width / 2 && local.x < hero.width / 2 && local.y > -hero.height / 2 && local.y < hero.height / 2) {
draggingHero = true;
lastMoveX = x;
lastMoveY = y;
}
};
game.up = function (x, y, obj) {
draggingHero = false;
};
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
// Walk-to destination variables
var walkToActive = false;
var walkToX = 0;
var walkToY = 0;
var walkToSpeed = 22;
// Move handler
game.move = function (x, y, obj) {
if (draggingHero) {
// Clamp hero inside room bounds
var hx = clamp(x, roomBounds.x + hero.width / 2, roomBounds.x + roomBounds.width - hero.width / 2);
var hy = clamp(y, roomBounds.y + hero.height / 2, roomBounds.y + roomBounds.height - hero.height / 2);
hero.x = hx;
hero.y = hy;
walkToActive = false; // Cancel walk-to if dragging
}
};
// Tap-to-walk logic: on down, if not on hero, set walk-to destination
var oldGameDown = game.down;
game.down = function (x, y, obj) {
// Only start drag if touch is on hero
var local = hero.toLocal(game.toGlobal({
x: x,
y: y
}));
if (local.x > -hero.width / 2 && local.x < hero.width / 2 && local.y > -hero.height / 2 && local.y < hero.height / 2) {
draggingHero = true;
lastMoveX = x;
lastMoveY = y;
walkToActive = false;
} else {
// Set walk-to destination if tap is inside room
var hx = clamp(x, roomBounds.x + hero.width / 2, roomBounds.x + roomBounds.width - hero.width / 2);
var hy = clamp(y, roomBounds.y + hero.height / 2, roomBounds.y + roomBounds.height - hero.height / 2);
walkToX = hx;
walkToY = hy;
walkToActive = true;
}
if (typeof oldGameDown === "function") oldGameDown(x, y, obj);
};
// In update, move hero toward walk-to destination if active
var oldGameUpdate = game.update;
game.update = function () {
// Walk-to logic
if (walkToActive && !draggingHero) {
var dx = walkToX - hero.x;
var dy = walkToY - hero.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > walkToSpeed) {
hero.x += dx / dist * walkToSpeed;
hero.y += dy / dist * walkToSpeed;
} else {
hero.x = walkToX;
hero.y = walkToY;
walkToActive = false;
}
}
if (typeof oldGameUpdate === "function") oldGameUpdate();
};
// Main update loop
game.update = function () {
// Update hero
hero.update();
// Update monsters
for (var i = 0; i < monsters.length; i++) {
monsters[i].update();
}
// Check collisions: hero vs monsters
for (var i = monsters.length - 1; i >= 0; i--) {
var m = monsters[i];
if (hero.intersects(m)) {
hero.takeDamage();
// Knockback
var dx = hero.x - m.x;
var dy = hero.y - m.y;
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
hero.x += dx / dist * 60;
hero.y += dy / dist * 60;
// Remove monster
m.destroy();
monsters.splice(i, 1);
monstersDefeated++;
updateScoreDisplay();
}
}
// Check collisions: hero vs traps
for (var i = 0; i < traps.length; i++) {
var t = traps[i];
if (hero.intersects(t)) {
hero.takeDamage();
// Move hero away from trap
var dx = hero.x - t.x;
var dy = hero.y - t.y;
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
hero.x += dx / dist * 40;
hero.y += dy / dist * 40;
}
}
// Check collisions: hero vs treasures
for (var i = treasures.length - 1; i >= 0; i--) {
var tr = treasures[i];
if (hero.intersects(tr)) {
tr.destroy();
treasures.splice(i, 1);
treasuresCollected++;
updateScoreDisplay();
hero.heal();
}
}
// Room clear check
if (!roomCleared && monsters.length === 0) {
roomCleared = true;
door.visible = true;
LK.effects.flashObject(door, 0x83de44, 600);
}
// Check hero at door to next room
if (roomCleared && door && hero.intersects(door)) {
if (currentRoom < maxRooms) {
currentRoom++;
generateRoom(currentRoom);
} else {
// Win!
LK.setScore(treasuresCollected * 10 + monstersDefeated * 5);
LK.showYouWin();
}
}
};
/****
* Asset Initialization
****/
// Hero: red box
// Monster: green ellipse
// Trap: yellow box
// Treasure: blue ellipse
// Door: purple box ===================================================================
--- original.js
+++ change.js
@@ -292,18 +292,66 @@
};
function clamp(val, min, max) {
return Math.max(min, Math.min(max, val));
}
+// Walk-to destination variables
+var walkToActive = false;
+var walkToX = 0;
+var walkToY = 0;
+var walkToSpeed = 22;
// Move handler
game.move = function (x, y, obj) {
if (draggingHero) {
// Clamp hero inside room bounds
var hx = clamp(x, roomBounds.x + hero.width / 2, roomBounds.x + roomBounds.width - hero.width / 2);
var hy = clamp(y, roomBounds.y + hero.height / 2, roomBounds.y + roomBounds.height - hero.height / 2);
hero.x = hx;
hero.y = hy;
+ walkToActive = false; // Cancel walk-to if dragging
}
};
+// Tap-to-walk logic: on down, if not on hero, set walk-to destination
+var oldGameDown = game.down;
+game.down = function (x, y, obj) {
+ // Only start drag if touch is on hero
+ var local = hero.toLocal(game.toGlobal({
+ x: x,
+ y: y
+ }));
+ if (local.x > -hero.width / 2 && local.x < hero.width / 2 && local.y > -hero.height / 2 && local.y < hero.height / 2) {
+ draggingHero = true;
+ lastMoveX = x;
+ lastMoveY = y;
+ walkToActive = false;
+ } else {
+ // Set walk-to destination if tap is inside room
+ var hx = clamp(x, roomBounds.x + hero.width / 2, roomBounds.x + roomBounds.width - hero.width / 2);
+ var hy = clamp(y, roomBounds.y + hero.height / 2, roomBounds.y + roomBounds.height - hero.height / 2);
+ walkToX = hx;
+ walkToY = hy;
+ walkToActive = true;
+ }
+ if (typeof oldGameDown === "function") oldGameDown(x, y, obj);
+};
+// In update, move hero toward walk-to destination if active
+var oldGameUpdate = game.update;
+game.update = function () {
+ // Walk-to logic
+ if (walkToActive && !draggingHero) {
+ var dx = walkToX - hero.x;
+ var dy = walkToY - hero.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist > walkToSpeed) {
+ hero.x += dx / dist * walkToSpeed;
+ hero.y += dy / dist * walkToSpeed;
+ } else {
+ hero.x = walkToX;
+ hero.y = walkToY;
+ walkToActive = false;
+ }
+ }
+ if (typeof oldGameUpdate === "function") oldGameUpdate();
+};
// Main update loop
game.update = function () {
// Update hero
hero.update();
dungeon door. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
png
dungeon hero sword. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
dungeon key. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
dungeon chest. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
dungeon demon. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
dungeon wizard. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a mage who throws fireballs. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
big dungeon snake. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a spider. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat