User prompt
Bueno es mejor eliminar el modo de la nave.
User prompt
Corrige el error en el código porfa
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'x')' in or related to this line: 'if (!s.passed && s.x + 50 < cube.x) {' Line Number: 502
User prompt
As que en el nivel 3 y 4 haiga un nuevo modo:nave
User prompt
As un editor de niveles, también que ahora has 3 niveles que duren 1 minuto y un buscador de niveles ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Cube Runner: Spike Escape
Initial prompt
Quiero que el juego sea un runner infinito 2d,que el personaje sea un cubo,un menu con un personalizador de personaje y un botón para jugar y que los obstáculos sean pinchos
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
cubeColor: "cube_blue",
selectedLevel: 1
});
/****
* Classes
****/
// Player Cube
var Cube = Container.expand(function () {
var self = Container.call(this);
// Attach cube asset (color set externally)
self.cubeAsset = null;
self.setCubeColor = function (colorId) {
if (self.cubeAsset) {
self.removeChild(self.cubeAsset);
}
self.cubeAsset = self.attachAsset(colorId, {
anchorX: 0.5,
anchorY: 1
});
};
// Physics
self.vy = 0;
self.isOnGround = true;
// Jump method
self.jump = function () {
if (self.isOnGround) {
self.vy = -38;
self.isOnGround = false;
LK.getSound('jump').play();
}
};
// Update method
self.update = function () {
// Gravity
self.vy += 2.2;
self.y += self.vy;
// Ground collision
if (self.y > groundY) {
self.y = groundY;
self.vy = 0;
self.isOnGround = true;
}
};
return self;
});
// Nave (Spaceship) for levels 3 and 4
var Nave = Container.expand(function () {
var self = Container.call(this);
var naveAsset = self.attachAsset('nave', {
anchorX: 0.5,
anchorY: 0.5
});
// Nave physics
self.vy = 0;
self.moveUp = false;
self.moveDown = false;
self.maxY = 200; // Top boundary
self.minY = groundY - 100; // Bottom boundary
// Movement speed
self.moveSpeed = 15;
// Update method
self.update = function () {
if (self.moveUp) {
self.vy = -self.moveSpeed;
} else if (self.moveDown) {
self.vy = self.moveSpeed;
} else {
self.vy = 0;
}
self.y += self.vy;
// Boundary collision
if (self.y < self.maxY) {
self.y = self.maxY;
}
if (self.y > self.minY) {
self.y = self.minY;
}
};
return self;
});
// Spike Obstacle
var Spike = Container.expand(function () {
var self = Container.call(this);
var spikeAsset = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 1
});
self.passed = false; // For scoring
// Update method
self.update = function () {
self.x -= spikeSpeed;
};
return self;
});
/****
* Initialize Game
****/
// Level Configuration
var game = new LK.Game({
backgroundColor: 0xfafafa
});
/****
* Game Code
****/
// Level Configuration
// --- Global Variables ---
// Cube (player) - customizable color, default blue
// Spike obstacle
// Ground
// Jump sound
// Hit sound
// Music
var LevelConfig = {
1: {
name: 'Level 1: Warm Up',
initialSpikeInterval: 100,
initialSpikeSpeed: 12,
difficultyMultiplier: 0.8
},
2: {
name: 'Level 2: Challenge',
initialSpikeInterval: 75,
initialSpikeSpeed: 18,
difficultyMultiplier: 1.0
},
3: {
name: 'Level 3: Insane',
initialSpikeInterval: 60,
initialSpikeSpeed: 24,
difficultyMultiplier: 1.3,
isNaveMode: true
},
4: {
name: 'Level 4: Nave Mode',
initialSpikeInterval: 50,
initialSpikeSpeed: 28,
difficultyMultiplier: 1.5,
isNaveMode: true
} //{K_new}
};
var groundY = 2732 - 80; // y position of ground
var cube = null;
var spikes = [];
var spikeTimer = 0;
var spikeInterval = 90; // frames between spikes (decreases with difficulty)
var spikeSpeed = 18; // pixels per frame (increases with difficulty)
var score = 0;
var scoreTxt = null;
var running = false;
var menuContainer = null;
var playBtn = null;
var colorBtns = [];
var selectedColor = storage.cubeColor || 'cube_blue';
var ground = null;
var lastTick = 0;
var selectedLevel = storage.selectedLevel || 1;
var levelStartTime = 0;
var levelDuration = 60000; // 60 seconds in milliseconds
var levelTimerTxt = null;
var levelBtns = [];
var levelSelectorContainer = null;
var isNaveMode = false;
var nave = null;
// --- Main Menu ---
function showMenu() {
running = false;
// Remove game elements if present
if (cube) {
cube.destroy();
cube = null;
}
for (var i = 0; i < spikes.length; i++) {
spikes[i].destroy();
}
spikes = [];
if (ground) {
ground.destroy();
ground = null;
}
if (scoreTxt) {
scoreTxt.destroy();
scoreTxt = null;
}
if (levelTimerTxt) {
levelTimerTxt.destroy();
levelTimerTxt = null;
}
// Menu container
menuContainer = new Container();
// Title
var title = new Text2('Cube Runner', {
size: 180,
fill: 0x222222
});
title.anchor.set(0.5, 0);
title.x = 2048 / 2;
title.y = 220;
menuContainer.addChild(title);
// Subtitle
var subtitle = new Text2('Spike Escape', {
size: 90,
fill: 0x888888
});
subtitle.anchor.set(0.5, 0);
subtitle.x = 2048 / 2;
subtitle.y = 420;
menuContainer.addChild(subtitle);
// Level selector label
var levelLabel = new Text2('Select Level', {
size: 70,
fill: 0x444444
}); //{level_label}
levelLabel.anchor.set(0.5, 0);
levelLabel.x = 2048 / 2;
levelLabel.y = 600;
menuContainer.addChild(levelLabel);
// Level buttons
levelBtns = [];
for (var l = 1; l <= 4; l++) {
(function (levelNum) {
var levelBtn = new Container();
var levelBtnShape = levelBtn.attachAsset('cube_blue', {
anchorX: 0.5,
anchorY: 0.5
});
levelBtnShape.width = 280;
levelBtnShape.height = 100;
levelBtn.x = 2048 / 2 - 300 + (levelNum - 1) * 300;
levelBtn.y = 750;
// Highlight if selected
if (selectedLevel === levelNum) {
levelBtnShape.tint = 0x2ecc71;
}
// Label with level name
var levelNameTxt = new Text2(LevelConfig[levelNum].name, {
size: 36,
fill: 0xFFFFFF
});
levelNameTxt.anchor.set(0.5, 0.5);
levelBtn.addChild(levelNameTxt);
// Touch event
levelBtn.down = function (x, y, obj) {
selectedLevel = levelNum;
storage.selectedLevel = selectedLevel;
showMenu();
};
levelBtns.push(levelBtn);
menuContainer.addChild(levelBtn);
})(l);
}
// Customizer label
var customLabel = new Text2('Customize Your Cube', {
size: 70,
fill: 0x444444
});
customLabel.anchor.set(0.5, 0);
customLabel.x = 2048 / 2;
customLabel.y = 950;
menuContainer.addChild(customLabel);
// Color buttons
var colors = ['cube_blue', 'cube_red', 'cube_green', 'cube_yellow', 'cube_purple'];
var colorNames = ['Blue', 'Red', 'Green', 'Yellow', 'Purple'];
colorBtns = [];
for (var i = 0; i < colors.length; i++) {
(function (idx) {
var btn = new Container();
var asset = btn.attachAsset(colors[idx], {
anchorX: 0.5,
anchorY: 0.5
});
btn.x = 2048 / 2 - 350 + idx * 175;
btn.y = 1150;
btn.scale.set(1.1, 1.1);
// Highlight if selected
if (selectedColor === colors[idx]) {
asset.width += 18;
asset.height += 18;
}
// Label
var lbl = new Text2(colorNames[idx], {
size: 38,
fill: 0x222222
});
lbl.anchor.set(0.5, 0);
lbl.x = 0;
lbl.y = 90;
btn.addChild(lbl);
// Touch event
btn.down = function (x, y, obj) {
selectedColor = colors[idx];
storage.cubeColor = selectedColor;
showMenu();
};
colorBtns.push(btn);
menuContainer.addChild(btn);
})(i);
}
// Play button
playBtn = new Container();
var playBtnShape = playBtn.attachAsset('cube_green', {
anchorX: 0.5,
anchorY: 0.5
});
playBtnShape.width = 320;
playBtnShape.height = 120;
playBtn.x = 2048 / 2;
playBtn.y = 1450;
var playTxt = new Text2('PLAY', {
size: 80,
fill: 0xFFFFFF
});
playTxt.anchor.set(0.5, 0.5);
playBtn.addChild(playTxt);
playBtn.down = function (x, y, obj) {
startGame();
};
menuContainer.addChild(playBtn);
// Instructions
var inst = new Text2('Tap to jump. Dodge the spikes!\nSelect a level and customize your cube.', {
size: 50,
fill: 0x666666
});
inst.anchor.set(0.5, 0);
inst.x = 2048 / 2;
inst.y = 1700;
menuContainer.addChild(inst);
game.addChild(menuContainer);
// Play music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
}
// --- Start Game ---
function startGame() {
running = true;
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
}
// Reset variables
score = 0;
spikeTimer = 0;
// Apply level-specific settings
var levelConfig = LevelConfig[selectedLevel];
spikeInterval = levelConfig.initialSpikeInterval;
spikeSpeed = levelConfig.initialSpikeSpeed;
isNaveMode = levelConfig.isNaveMode || false;
spikes = [];
levelStartTime = Date.now();
// Ground
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0
});
ground.x = 0;
ground.y = groundY;
game.addChild(ground);
// Create player based on mode
if (isNaveMode) {
nave = new Nave();
nave.x = 420;
nave.y = groundY - 100;
game.addChild(nave);
cube = null;
} else {
cube = new Cube();
cube.setCubeColor(selectedColor);
cube.x = 420;
cube.y = groundY;
game.addChild(cube);
nave = null;
}
// Score text
scoreTxt = new Text2('0', {
size: 120,
fill: 0x222222
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Level timer text
levelTimerTxt = new Text2('60', {
size: 100,
fill: 0x222222
});
levelTimerTxt.anchor.set(0.5, 0);
levelTimerTxt.x = 2048 - 150;
levelTimerTxt.y = 40;
LK.gui.top.addChild(levelTimerTxt);
// Play music (if not already playing)
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
}
// --- Game Over ---
function gameOver() {
running = false;
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
// After game over, return to menu
LK.setTimeout(function () {
showMenu();
}, 1200);
}
// --- Game Tap (Jump) or Nave Control ---
game.down = function (x, y, obj) {
if (!running) return;
if (isNaveMode && nave) {
if (y < 2732 / 2) {
nave.moveUp = true;
} else {
nave.moveDown = true;
}
} else if (cube) {
cube.jump();
}
};
// --- Game Up (Stop Nave Movement) ---
game.up = function (x, y, obj) {
if (!running) return;
if (isNaveMode && nave) {
nave.moveUp = false;
nave.moveDown = false;
}
};
// --- Main Update Loop ---
game.update = function () {
if (!running) return;
// Update player
if (cube) cube.update();
if (nave) nave.update();
// Check level timer
var elapsedTime = Date.now() - levelStartTime;
var remainingSeconds = Math.ceil((levelDuration - elapsedTime) / 1000);
if (remainingSeconds < 0) remainingSeconds = 0;
if (levelTimerTxt) {
levelTimerTxt.setText(remainingSeconds);
}
// Win condition: survive 60 seconds
if (elapsedTime >= levelDuration) {
running = false;
LK.showYouWin();
LK.setTimeout(function () {
showMenu();
}, 1200);
return;
}
// Update spikes
for (var i = spikes.length - 1; i >= 0; i--) {
var s = spikes[i];
s.update();
// Remove if off screen
if (s.x < -120) {
s.destroy();
spikes.splice(i, 1);
continue;
}
// Score if passed
var playerX = isNaveMode ? nave ? nave.x : 0 : cube ? cube.x : 0;
if (playerX > 0 && !s.passed && s.x + 50 < playerX) {
s.passed = true;
score += 1;
scoreTxt.setText(score);
// Increase difficulty based on level multiplier
var difficultyMultiplier = LevelConfig[selectedLevel].difficultyMultiplier;
if (score % 10 === 0 && spikeInterval > 30) {
spikeInterval -= Math.ceil(7 * difficultyMultiplier);
spikeSpeed += 2.5 * difficultyMultiplier;
}
}
// Collision
var playerCollider = isNaveMode ? nave : cube;
if (playerCollider && playerCollider.intersects(s)) {
gameOver();
return;
}
}
// Spawn spikes
spikeTimer++;
if (spikeTimer >= spikeInterval) {
spikeTimer = 0;
var spike = new Spike();
spike.x = 2048 + 80;
spike.y = groundY;
game.addChild(spike);
spikes.push(spike);
}
};
// --- Show Menu on Load ---
showMenu(); ===================================================================
--- original.js
+++ change.js
@@ -472,9 +472,9 @@
continue;
}
// Score if passed
var playerX = isNaveMode ? nave ? nave.x : 0 : cube ? cube.x : 0;
- if (!s.passed && s.x + 50 < playerX) {
+ if (playerX > 0 && !s.passed && s.x + 50 < playerX) {
s.passed = true;
score += 1;
scoreTxt.setText(score);
// Increase difficulty based on level multiplier