User prompt
make longer but not width other long
User prompt
made up longer enemy box
User prompt
Please fix the bug: 's.apply(...).then is not a function' in or related to this line: 'self.patternTick++;' Line Number: 52
User prompt
put the enemy a little up
User prompt
a little longer
User prompt
bigger health bar
User prompt
put the enemy middle and put the health bar more down
User prompt
put the enemy up
User prompt
put the health bar under enemy
User prompt
put a bi
User prompt
put enemy health bar
User prompt
deletele choose spare or fight
User prompt
heart will always follow mouse
User prompt
put the enemy middle
User prompt
make easy attacks for enemy those attacks are ımpossible
User prompt
small heart
Code edit (1 edits merged)
Please save this source code
User prompt
Undertale: Heart of the Underground
Initial prompt
lets do a big proje.undertale what you think?
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy (for future expansion, currently just a box at the top)
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyBox = self.attachAsset('enemyBox', {
width: 220,
height: 120,
color: 0x2222ff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Enemy Bullet
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
// Attach bullet asset (yellow circle)
var bullet = self.attachAsset('enemyBullet', {
width: 60,
height: 60,
color: 0xf7e017,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
// Movement properties
self.vx = 0;
self.vy = 0;
// For pattern logic
self.pattern = null;
self.patternTick = 0;
// Called every tick
self.update = function () {
if (self.pattern) {
self.pattern(self, self.patternTick);
self.patternTick++;
} else {
self.x += self.vx;
self.y += self.vy;
}
};
return self;
});
// Heart-shaped Soul (Player)
var Soul = Container.expand(function () {
var self = Container.call(this);
// Attach heart asset (ellipse, red, scaled to look like a heart)
// Since we can't draw a heart, use an ellipse and scale it to look heart-like
var heart = self.attachAsset('soulHeart', {
width: 60,
height: 50,
color: 0xff2d55,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
// Squash to make it more heart-like
heart.scaleY = 1.1;
heart.scaleX = 1.2;
// For hit feedback
self.flash = function () {
tween(heart, {
tint: 0xffffff
}, {
duration: 80,
onFinish: function onFinish() {
tween(heart, {
tint: 0xff2d55
}, {
duration: 120
});
}
});
};
// For movement bounds
self.radius = 30;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Game area (the "box" where the soul can move)
// Tween plugin for movement and effects
var boxWidth = 900;
var boxHeight = 900;
var boxX = (2048 - boxWidth) / 2;
var boxY = 2732 - boxHeight - 200;
// Draw the box (white border, transparent fill)
var boxBorder = LK.getAsset('boxBorder', {
width: boxWidth,
height: boxHeight,
color: 0xffffff,
shape: 'box',
anchorX: 0,
anchorY: 0
});
boxBorder.alpha = 0.15;
boxBorder.x = boxX;
boxBorder.y = boxY;
game.addChild(boxBorder);
// Add enemy at the vertical center of the game area
var enemy = new Enemy();
enemy.x = 2048 / 2;
enemy.y = 2732 / 2;
game.addChild(enemy);
// Add soul (player) at center of box
var soul = new Soul();
soul.x = boxX + boxWidth / 2;
soul.y = boxY + boxHeight / 2;
game.addChild(soul);
// Health system
var maxHP = 5;
var hp = maxHP;
// Score (number of waves survived)
var score = 0;
// Bullets array
var enemyBullets = [];
// GUI: HP display (top right, avoid top left)
var hpText = new Text2('HP: ' + hp, {
size: 90,
fill: 0xFF2D55
});
hpText.anchor.set(1, 0);
LK.gui.topRight.addChild(hpText);
// GUI: Score display (top center)
var scoreText = new Text2('WAVES: 0', {
size: 90,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// GUI: Pacifist/Aggressive choice (bottom center)
var choiceText = new Text2('Choose: [SPARE] or [FIGHT]', {
size: 70,
fill: 0xFFFFFF
});
choiceText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(choiceText);
// Choice state
var playerChoice = null; // null, 'spare', 'fight'
// Touch controls for soul movement
var draggingSoul = false;
var dragOffsetX = 0;
var dragOffsetY = 0;
// Helper: clamp soul inside box
function clampSoulPosition(x, y) {
var r = soul.radius;
var minX = boxX + r;
var maxX = boxX + boxWidth - r;
var minY = boxY + r;
var maxY = boxY + boxHeight - r;
if (x < minX) x = minX;
if (x > maxX) x = maxX;
if (y < minY) y = minY;
if (y > maxY) y = maxY;
return {
x: x,
y: y
};
}
// Touch down: start dragging if inside soul
game.down = function (x, y, obj) {
// Only allow drag if inside soul
var dx = x - soul.x;
var dy = y - soul.y;
if (dx * dx + dy * dy <= soul.radius * soul.radius) {
draggingSoul = true;
dragOffsetX = soul.x - x;
dragOffsetY = soul.y - y;
}
};
// Touch up: stop dragging
game.up = function (x, y, obj) {
draggingSoul = false;
};
// Touch move: move soul
game.move = function (x, y, obj) {
if (draggingSoul) {
var pos = clampSoulPosition(x + dragOffsetX, y + dragOffsetY);
soul.x = pos.x;
soul.y = pos.y;
}
};
// Choice selection (tap bottom half of screen for SPARE, top half for FIGHT)
game.downChoice = function (x, y, obj) {
if (playerChoice !== null) return;
// Only allow choice if in choice phase
if (y > 2732 / 2) {
playerChoice = 'spare';
choiceText.setText('You chose: SPARE');
} else {
playerChoice = 'fight';
choiceText.setText('You chose: FIGHT');
}
// Hide choice after a moment
LK.setTimeout(function () {
choiceText.setText('');
}, 1000);
};
// Attach choice event to game
game.on('down', function (x, y, obj) {
// Only allow choice if in choice phase and not dragging soul
if (!draggingSoul && playerChoice === null && y > boxY + boxHeight + 40) {
game.downChoice(x, y, obj);
}
});
// Bullet patterns
function spawnWave(waveNum) {
// Clear bullets
for (var i = 0; i < enemyBullets.length; i++) {
enemyBullets[i].destroy();
}
enemyBullets.length = 0;
// Pick pattern based on waveNum
if (waveNum % 3 === 0) {
// Radial burst - easier: fewer bullets, slower speed, bigger gaps
var count = 8 + Math.floor(waveNum); // fewer bullets
for (var i = 0; i < count; i++) {
var angle = Math.PI * 2 * i / count;
var b = new EnemyBullet();
b.x = 2048 / 2;
b.y = boxY + 40;
b.vx = Math.cos(angle) * (3 + waveNum * 0.3); // slower
b.vy = Math.sin(angle) * (3 + waveNum * 0.3);
enemyBullets.push(b);
game.addChild(b);
}
} else if (waveNum % 3 === 1) {
// Sine wave bullets from left/right - easier: fewer bullets, slower, more vertical spacing
for (var i = 0; i < 5 + Math.floor(waveNum * 0.7); i++) {
var b = new EnemyBullet();
b.x = boxX + 40;
b.y = boxY + 120 + i * 120;
b.vx = 4 + waveNum * 0.3;
b.vy = 0;
// Sine pattern
b.pattern = function (self, t) {
self.x += self.vx;
self.y += Math.sin((self.x + t * 2) / 80) * 5;
};
enemyBullets.push(b);
game.addChild(b);
}
for (var i = 0; i < 5 + Math.floor(waveNum * 0.7); i++) {
var b = new EnemyBullet();
b.x = boxX + boxWidth - 40;
b.y = boxY + 120 + i * 120;
b.vx = -4 - waveNum * 0.3;
b.vy = 0;
b.pattern = function (self, t) {
self.x += self.vx;
self.y += Math.sin((self.x + t * 2) / 80) * 5;
};
enemyBullets.push(b);
game.addChild(b);
}
} else {
// Falling bullets from above - easier: fewer, slower, more horizontal spacing
for (var i = 0; i < 8 + Math.floor(waveNum * 1.2); i++) {
var b = new EnemyBullet();
b.x = boxX + 80 + (boxWidth - 160) * (i / (8 + Math.floor(waveNum * 1.2)));
b.y = boxY + 20;
b.vx = 0;
b.vy = 4 + waveNum * 0.2; // slower
// Zigzag
b.pattern = function (self, t) {
self.y += self.vy;
self.x += Math.sin(self.y / 60) * 3;
};
enemyBullets.push(b);
game.addChild(b);
}
}
}
// Game state
var waveNum = 0;
var waveTimer = 0;
var waveDuration = 240; // 4 seconds per wave
// Invincibility after hit
var invincibleTicks = 0;
// Main update loop
game.update = function () {
// Update bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var b = enemyBullets[i];
b.update();
// Remove if out of box
if (b.x < boxX - 80 || b.x > boxX + boxWidth + 80 || b.y < boxY - 80 || b.y > boxY + boxHeight + 80) {
b.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Collision with soul
if (invincibleTicks === 0 && b.intersects(soul)) {
hp--;
soul.flash();
invincibleTicks = 60; // 1 second invincibility
hpText.setText('HP: ' + hp);
LK.effects.flashObject(soul, 0xffffff, 300);
if (hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
// Invincibility timer
if (invincibleTicks > 0) {
invincibleTicks--;
}
// Wave logic
waveTimer++;
if (waveTimer >= waveDuration) {
waveNum++;
score++;
scoreText.setText('WAVES: ' + score);
waveTimer = 0;
spawnWave(waveNum);
// Every 3 waves, present a choice
if (waveNum > 0 && waveNum % 3 === 0) {
playerChoice = null;
choiceText.setText('Choose: [SPARE] or [FIGHT]');
}
}
};
// Start first wave
spawnWave(waveNum); ===================================================================
--- original.js
+++ change.js
@@ -113,12 +113,12 @@
boxBorder.alpha = 0.15;
boxBorder.x = boxX;
boxBorder.y = boxY;
game.addChild(boxBorder);
-// Add enemy at the top center
+// Add enemy at the vertical center of the game area
var enemy = new Enemy();
enemy.x = 2048 / 2;
-enemy.y = 200;
+enemy.y = 2732 / 2;
game.addChild(enemy);
// Add soul (player) at center of box
var soul = new Soul();
soul.x = boxX + boxWidth / 2;