User prompt
Please fix the bug: 'Uncaught TypeError: setTimeout is not a function' in or related to this line: 'setTimeout(syncKnobToNull, 100);' Line Number: 291
User prompt
make a slide bar to conroll null
User prompt
move null player down more
User prompt
make it so the player can only move left and right
User prompt
revert it to the original game
User prompt
do endless mode but make it a option at the begining
Code edit (1 edits merged)
Please save this source code
User prompt
Null Is The Way
Initial prompt
null is the way
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Fragment: Collectible fragments
var Fragment = Container.expand(function () {
var self = Container.call(this);
var frag = self.attachAsset('fragment', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
// Animate scale for a subtle pulse
function pulseUp() {
tween(frag, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 600,
easing: tween.sineInOut,
onFinish: pulseDown
});
}
function pulseDown() {
tween(frag, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 600,
easing: tween.sineInOut,
onFinish: pulseUp
});
}
frag.scaleX = frag.scaleY = 1.0;
pulseUp();
// Movement speed (downward)
self.speedY = 6;
// For collision
self.radius = frag.width * 0.5;
self.update = function () {
self.y += self.speedY;
};
return self;
});
// NullEntity: The player-controlled "null" entity.
var NullEntity = Container.expand(function () {
var self = Container.call(this);
var entity = self.attachAsset('nullEntity', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.18
});
// Add a subtle glow effect by animating alpha
tween(entity, {
alpha: 0.32
}, {
duration: 1200,
easing: tween.sineInOut,
onFinish: function onFinish() {
tween(entity, {
alpha: 0.18
}, {
duration: 1200,
easing: tween.sineInOut,
onFinish: function onFinish() {
// Loop
tween(entity, {
alpha: 0.32
}, {
duration: 1200,
easing: tween.sineInOut,
onFinish: arguments.callee
});
}
});
}
});
// For collision, use self's position and size
self.radius = entity.width * 0.5;
// No update needed; movement is handled by drag/tap
return self;
});
// Obstacle: Abstract void obstacles to avoid
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obs = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.32
});
// Randomize rotation for abstractness
obs.rotation = (Math.random() - 0.5) * 0.7;
// Movement speed (downward)
self.speedY = 7 + Math.random() * 3;
// For collision
self.width = obs.width;
self.height = obs.height;
self.update = function () {
self.y += self.speedY;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x111111 // Deep void
});
/****
* Game Code
****/
/*
We use minimalist shapes for the "null" entity, obstacles, and collectible fragments.
- nullEntity: a faint ellipse, representing the player.
- obstacle: a semi-transparent box, representing void obstacles.
- fragment: a small glowing ellipse, representing fragments to collect.
- messageBg: a translucent box for cryptic message popups.
*/
// --- Game State ---
var nullEntity = new NullEntity();
game.addChild(nullEntity);
// Start position: center horizontally, 80% down vertically
nullEntity.x = 2048 / 2;
nullEntity.y = 2732 * 0.8;
// Arrays for obstacles and fragments
var obstacles = [];
var fragments = [];
// Level and progress
var level = 1;
var fragmentsCollected = 0;
var fragmentsToNext = 5;
var showingMessage = false;
// Cryptic messages for fragments
var messages = ["Nothing is the beginning of everything.", "In emptiness, potential awaits.", "Absence shapes the void.", "Meaning emerges from nothing.", "The null is not empty, but full of possibility."];
// --- GUI: Progress Display ---
var progressTxt = new Text2('Fragments: 0/5', {
size: 90,
fill: 0xCCCCCC
});
progressTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(progressTxt);
// --- Message Popup ---
var messageContainer = new Container();
var messageBg = LK.getAsset('messageBg', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.82
});
messageContainer.addChild(messageBg);
var messageTxt = new Text2('', {
size: 70,
fill: 0xE0E0E0,
align: "center",
wordWrap: true,
wordWrapWidth: 800
});
messageTxt.anchor.set(0.5, 0.5);
messageTxt.x = 0;
messageTxt.y = 0;
messageContainer.addChild(messageTxt);
messageContainer.visible = false;
messageContainer.x = 2048 / 2;
messageContainer.y = 2732 / 2;
game.addChild(messageContainer);
// --- Drag/Touch Controls ---
var dragActive = false;
var dragOffsetX = 0;
var dragOffsetY = 0;
// Helper: Clamp nullEntity inside game bounds (with margin)
function clampNullEntity() {
var margin = 80;
var r = nullEntity.radius;
if (nullEntity.x < margin + r) nullEntity.x = margin + r;
if (nullEntity.x > 2048 - margin - r) nullEntity.x = 2048 - margin - r;
if (nullEntity.y < margin + r) nullEntity.y = margin + r;
if (nullEntity.y > 2732 - margin - r) nullEntity.y = 2732 - margin - r;
}
// --- Event Handlers ---
function handleMove(x, y, obj) {
if (showingMessage) return; // Pause movement when message is shown
if (dragActive) {
nullEntity.x = x - dragOffsetX;
nullEntity.y = y - dragOffsetY;
clampNullEntity();
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (showingMessage) {
// Hide message on tap
messageContainer.visible = false;
showingMessage = false;
return;
}
// Start drag if touch is near nullEntity
var dx = x - nullEntity.x;
var dy = y - nullEntity.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < nullEntity.radius * 1.2) {
dragActive = true;
dragOffsetX = x - nullEntity.x;
dragOffsetY = y - nullEntity.y;
}
};
game.up = function (x, y, obj) {
dragActive = false;
};
// --- Collision Helpers ---
function circleRectIntersect(cx, cy, cr, rx, ry, rw, rh) {
// Find closest point to circle within rectangle
var closestX = Math.max(rx - rw / 2, Math.min(cx, rx + rw / 2));
var closestY = Math.max(ry - rh / 2, Math.min(cy, ry + rh / 2));
var dx = cx - closestX;
var dy = cy - closestY;
return dx * dx + dy * dy < cr * cr;
}
function circleCircleIntersect(x1, y1, r1, x2, y2, r2) {
var dx = x1 - x2;
var dy = y1 - y2;
var distSq = dx * dx + dy * dy;
var rSum = r1 + r2;
return distSq < rSum * rSum;
}
// --- Spawning Obstacles and Fragments ---
var obstacleTimer = 0;
var fragmentTimer = 0;
function spawnObstacle() {
var obs = new Obstacle();
obs.x = 200 + Math.random() * (2048 - 400);
obs.y = -80;
obstacles.push(obs);
game.addChild(obs);
}
function spawnFragment() {
var frag = new Fragment();
frag.x = 200 + Math.random() * (2048 - 400);
frag.y = -60;
fragments.push(frag);
game.addChild(frag);
}
// --- Level Progression ---
function nextLevel() {
if (endlessMode) {
// In endless mode, do not level up, just keep going
return;
}
level += 1;
fragmentsCollected = 0;
fragmentsToNext = 5 + level * 2;
progressTxt.setText('Fragments: 0/' + fragmentsToNext);
// Show cryptic message
var msg = messages[(level - 2) % messages.length] || "The void deepens.";
messageTxt.setText(msg);
messageContainer.visible = true;
showingMessage = true;
// Increase difficulty: spawn rates
obstacleTimer = 0;
fragmentTimer = 0;
}
// --- Game Update Loop ---
game.update = function () {
if (showingMessage) return;
// Spawn obstacles
obstacleTimer++;
var obsInterval = Math.max(38 - level * 2, 16);
if (obstacleTimer >= obsInterval) {
spawnObstacle();
obstacleTimer = 0;
}
// Spawn fragments
fragmentTimer++;
var fragInterval = Math.max(120 - level * 8, 40);
if (fragmentTimer >= fragInterval) {
spawnFragment();
fragmentTimer = 0;
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// Remove if off screen
if (obs.y - obs.height / 2 > 2732 + 100) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with nullEntity
if (circleRectIntersect(nullEntity.x, nullEntity.y, nullEntity.radius * 0.8, obs.x, obs.y, obs.width, obs.height)) {
// Flash and game over
LK.effects.flashScreen(0xffffff, 900);
LK.showGameOver();
return;
}
}
// Update fragments
for (var j = fragments.length - 1; j >= 0; j--) {
var frag = fragments[j];
frag.update();
// Remove if off screen
if (frag.y - frag.radius > 2732 + 80) {
frag.destroy();
fragments.splice(j, 1);
continue;
}
// Collision with nullEntity
if (circleCircleIntersect(nullEntity.x, nullEntity.y, nullEntity.radius * 0.8, frag.x, frag.y, frag.radius)) {
// Collect fragment
fragmentsCollected += 1;
if (endlessMode) {
progressTxt.setText('Fragments: ' + fragmentsCollected);
} else {
progressTxt.setText('Fragments: ' + fragmentsCollected + '/' + fragmentsToNext);
}
// Subtle flash
LK.effects.flashObject(nullEntity, 0x8ecae6, 400);
frag.destroy();
fragments.splice(j, 1);
// Level up
if (!endlessMode && fragmentsCollected >= fragmentsToNext) {
nextLevel();
}
continue;
}
}
};
// --- Initial Progress Text ---
progressTxt.setText('Fragments: 0/' + fragmentsToNext);
// --- Mode Selection Popup ---
var modeSelectContainer = new Container();
var modeBg = LK.getAsset('messageBg', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.92
});
modeSelectContainer.addChild(modeBg);
modeSelectContainer.x = 2048 / 2;
modeSelectContainer.y = 2732 / 2;
var modeTitle = new Text2('Choose Mode', {
size: 90,
fill: 0xE0E0E0,
align: "center"
});
modeTitle.anchor.set(0.5, 0.5);
modeTitle.y = -110;
modeSelectContainer.addChild(modeTitle);
var btnNormal = new Text2('Progressive', {
size: 80,
fill: 0x8ecae6,
align: "center"
});
btnNormal.anchor.set(0.5, 0.5);
btnNormal.y = 0;
modeSelectContainer.addChild(btnNormal);
var btnEndless = new Text2('Endless', {
size: 80,
fill: 0x219ebc,
align: "center"
});
btnEndless.anchor.set(0.5, 0.5);
btnEndless.y = 110;
modeSelectContainer.addChild(btnEndless);
modeSelectContainer.visible = true;
game.addChild(modeSelectContainer);
var endlessMode = false;
// Helper: Hide mode select and start game
function startGameWithMode(isEndless) {
endlessMode = isEndless;
modeSelectContainer.visible = false;
messageContainer.visible = true;
showingMessage = true;
if (endlessMode) {
// Endless mode: show different intro
messageTxt.setText("Endless: Survive and collect as many fragments as you can!");
// Set up endless mode parameters
level = 1;
fragmentsCollected = 0;
fragmentsToNext = 99999; // never triggers nextLevel
progressTxt.setText('Fragments: 0');
} else {
// Normal mode
messageTxt.setText("Guide the null. Collect fragments. Avoid the void.");
level = 1;
fragmentsCollected = 0;
fragmentsToNext = 5;
progressTxt.setText('Fragments: 0/' + fragmentsToNext);
}
// Remove all obstacles/fragments if any
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
for (var j = fragments.length - 1; j >= 0; j--) {
fragments[j].destroy();
fragments.splice(j, 1);
}
// Reset timers
obstacleTimer = 0;
fragmentTimer = 0;
// Reset nullEntity position
nullEntity.x = 2048 / 2;
nullEntity.y = 2732 * 0.8;
}
// Touch handler for mode selection
modeSelectContainer.down = function (x, y, obj) {
var local = modeSelectContainer.toLocal({
x: x,
y: y
});
// Check if tap is on btnNormal
if (local.y > btnNormal.y - 60 && local.y < btnNormal.y + 60) {
startGameWithMode(false);
}
// Check if tap is on btnEndless
if (local.y > btnEndless.y - 60 && local.y < btnEndless.y + 60) {
startGameWithMode(true);
}
};
modeSelectContainer.interactive = true;
// --- Initial Message (Level 1) ---
// (Now handled by startGameWithMode)
messageContainer.visible = false;
showingMessage = false; ===================================================================
--- original.js
+++ change.js
@@ -245,8 +245,12 @@
game.addChild(frag);
}
// --- Level Progression ---
function nextLevel() {
+ if (endlessMode) {
+ // In endless mode, do not level up, just keep going
+ return;
+ }
level += 1;
fragmentsCollected = 0;
fragmentsToNext = 5 + level * 2;
progressTxt.setText('Fragments: 0/' + fragmentsToNext);
@@ -307,23 +311,118 @@
// Collision with nullEntity
if (circleCircleIntersect(nullEntity.x, nullEntity.y, nullEntity.radius * 0.8, frag.x, frag.y, frag.radius)) {
// Collect fragment
fragmentsCollected += 1;
- progressTxt.setText('Fragments: ' + fragmentsCollected + '/' + fragmentsToNext);
+ if (endlessMode) {
+ progressTxt.setText('Fragments: ' + fragmentsCollected);
+ } else {
+ progressTxt.setText('Fragments: ' + fragmentsCollected + '/' + fragmentsToNext);
+ }
// Subtle flash
LK.effects.flashObject(nullEntity, 0x8ecae6, 400);
frag.destroy();
fragments.splice(j, 1);
// Level up
- if (fragmentsCollected >= fragmentsToNext) {
+ if (!endlessMode && fragmentsCollected >= fragmentsToNext) {
nextLevel();
}
continue;
}
}
};
// --- Initial Progress Text ---
progressTxt.setText('Fragments: 0/' + fragmentsToNext);
+// --- Mode Selection Popup ---
+var modeSelectContainer = new Container();
+var modeBg = LK.getAsset('messageBg', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.92
+});
+modeSelectContainer.addChild(modeBg);
+modeSelectContainer.x = 2048 / 2;
+modeSelectContainer.y = 2732 / 2;
+var modeTitle = new Text2('Choose Mode', {
+ size: 90,
+ fill: 0xE0E0E0,
+ align: "center"
+});
+modeTitle.anchor.set(0.5, 0.5);
+modeTitle.y = -110;
+modeSelectContainer.addChild(modeTitle);
+var btnNormal = new Text2('Progressive', {
+ size: 80,
+ fill: 0x8ecae6,
+ align: "center"
+});
+btnNormal.anchor.set(0.5, 0.5);
+btnNormal.y = 0;
+modeSelectContainer.addChild(btnNormal);
+var btnEndless = new Text2('Endless', {
+ size: 80,
+ fill: 0x219ebc,
+ align: "center"
+});
+btnEndless.anchor.set(0.5, 0.5);
+btnEndless.y = 110;
+modeSelectContainer.addChild(btnEndless);
+modeSelectContainer.visible = true;
+game.addChild(modeSelectContainer);
+var endlessMode = false;
+// Helper: Hide mode select and start game
+function startGameWithMode(isEndless) {
+ endlessMode = isEndless;
+ modeSelectContainer.visible = false;
+ messageContainer.visible = true;
+ showingMessage = true;
+ if (endlessMode) {
+ // Endless mode: show different intro
+ messageTxt.setText("Endless: Survive and collect as many fragments as you can!");
+ // Set up endless mode parameters
+ level = 1;
+ fragmentsCollected = 0;
+ fragmentsToNext = 99999; // never triggers nextLevel
+ progressTxt.setText('Fragments: 0');
+ } else {
+ // Normal mode
+ messageTxt.setText("Guide the null. Collect fragments. Avoid the void.");
+ level = 1;
+ fragmentsCollected = 0;
+ fragmentsToNext = 5;
+ progressTxt.setText('Fragments: 0/' + fragmentsToNext);
+ }
+ // Remove all obstacles/fragments if any
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ obstacles[i].destroy();
+ obstacles.splice(i, 1);
+ }
+ for (var j = fragments.length - 1; j >= 0; j--) {
+ fragments[j].destroy();
+ fragments.splice(j, 1);
+ }
+ // Reset timers
+ obstacleTimer = 0;
+ fragmentTimer = 0;
+ // Reset nullEntity position
+ nullEntity.x = 2048 / 2;
+ nullEntity.y = 2732 * 0.8;
+}
+// Touch handler for mode selection
+modeSelectContainer.down = function (x, y, obj) {
+ var local = modeSelectContainer.toLocal({
+ x: x,
+ y: y
+ });
+ // Check if tap is on btnNormal
+ if (local.y > btnNormal.y - 60 && local.y < btnNormal.y + 60) {
+ startGameWithMode(false);
+ }
+ // Check if tap is on btnEndless
+ if (local.y > btnEndless.y - 60 && local.y < btnEndless.y + 60) {
+ startGameWithMode(true);
+ }
+};
+modeSelectContainer.interactive = true;
// --- Initial Message (Level 1) ---
-messageTxt.setText("Guide the null. Collect fragments. Avoid the void.");
-messageContainer.visible = true;
-showingMessage = true;
\ No newline at end of file
+// (Now handled by startGameWithMode)
+messageContainer.visible = false;
+showingMessage = false;
\ No newline at end of file