User prompt
Increase the size you can click for up and down movement
User prompt
Increase the side of the range to click for left movement
User prompt
Increase the range of where you can click for up and down movement
User prompt
Make the range of the left and right button presses bigger
User prompt
Make it so the tap doesn’t have to be directly in line with the player, but just in the general direction
User prompt
Make it so if I tap in any direction of the player it moves 1 in that direction including up and down replace the old movement code
User prompt
Replace the swipe to move with a tap to move system
User prompt
Make it so if the player moves it does a a split second delay before it can be moved again
User prompt
Can you make a slight delay after each input before another input is pressed
User prompt
Redo the code for player movement
User prompt
Please fix the bug: 'Can't find variable: btnRight' in or related to this line: 'btnRight.visible = true;' Line Number: 153
User prompt
Show the buttons
User prompt
Make buttons using assets that when pressed control the movement of the player
User prompt
Make buttons for the movement
User prompt
Make the buttons show
User prompt
Make the player controlled using buttons
User prompt
Make the lower land go even lower
User prompt
Move the collectables and the enemies slightly down
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'player.visual.parent.addChild')' in or related to this line: 'player.visual.parent.addChild(player.visual);' Line Number: 472
User prompt
Make it so the player blocks the view of the enemies and collectables instead of them blocking the view of the player
User prompt
Make the player visual use an asset
User prompt
Change the controls so it uses 4 buttons to control it
User prompt
Make the up and down controls less sensitive
User prompt
Make it 6 lanes by adding a up and down feature
User prompt
Add a visual representation of where the player is
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Represents a single collectible in the corridor var Collectible = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('collectible', { anchorX: 0.5, anchorY: 1 }); self.lane = 1; self.depth = 0; self.type = 'collectible'; self.active = true; self.getHitbox = function () { return { x: self.x - sprite.width / 2, y: self.y - sprite.height, w: sprite.width, h: sprite.height }; }; return self; }); // Represents a single obstacle in the corridor var Obstacle = Container.expand(function () { var self = Container.call(this); var sprite = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 1 }); // Logical position in corridor space self.lane = 1; // 0=left, 1=center, 2=right self.depth = 0; // Distance from player (z) self.type = 'obstacle'; self.active = true; // For collision detection self.getHitbox = function () { // Returns {x, y, w, h} in screen space return { x: self.x - sprite.width / 2, y: self.y - sprite.height, w: sprite.width, h: sprite.height }; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Collectible (ellipse) // Obstacle (box) // Ceiling slice (horizontal rectangle, will be stretched/scaled for perspective) // Floor slice (horizontal rectangle, will be stretched/scaled for perspective) // Corridor wall slice (vertical rectangle, will be stretched/scaled for perspective) // --- Raycasting & Corridor Parameters --- var corridor = { width: 3, height: 2, // 2 rows: 0=top, 1=bottom // 6 lanes: (0,0)=top-left, (1,0)=top-center, (2,0)=top-right, (0,1)=bottom-left, (1,1)=bottom-center, (2,1)=bottom-right laneWidth: 700, rowHeight: 900, // vertical distance between rows (was 600, now lower lane is much lower) // vertical distance between rows depthSlices: 16, maxDepth: 16, fov: Math.PI / 3, wallColor: 0x4444aa, floorColor: 0x222222, ceilingColor: 0x111133 }; // Player state var player = { lane: 1, // 0=left, 1=center, 2=right row: 1, // 0=top, 1=bottom moving: false, moveTarget: 1, moveRowTarget: 1, moveTween: null, moveRowTween: null, alive: true }; // Input delay state var inputDelayActive = false; var inputDelayTimer = null; var inputDelayMs = 180; // ms, matches tween duration // Game state var speed = 0.18; // units per frame (z axis) var speedIncrease = 0.00004; // per frame var maxSpeed = 0.38; var objects = []; // all obstacles and collectibles var spawnTimer = 0; var spawnInterval = 38; // frames between spawns var score = 0; var distance = 0; // how far player has run (for difficulty) var lastTouchX = null; // --- GUI --- var scoreTxt = new Text2('0', { size: 220, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var distTxt = new Text2('0m', { size: 120, fill: "#aaa" }); distTxt.anchor.set(0.5, 0); LK.gui.top.addChild(distTxt); distTxt.y = 220; // --- Corridor rendering nodes --- var wallNodes = []; var floorNodes = []; var ceilingNodes = []; for (var i = 0; i < corridor.depthSlices; i++) { // Left wall var wl = LK.getAsset('wallSlice', { anchorX: 0.5, anchorY: 1 }); game.addChild(wl); wallNodes.push(wl); // Right wall var wr = LK.getAsset('wallSlice', { anchorX: 0.5, anchorY: 1 }); game.addChild(wr); wallNodes.push(wr); // Floor var fl = LK.getAsset('floorSlice', { anchorX: 0.5, anchorY: 0 }); game.addChild(fl); floorNodes.push(fl); // Ceiling var cl = LK.getAsset('ceilingSlice', { anchorX: 0.5, anchorY: 1 }); game.addChild(cl); ceilingNodes.push(cl); } // --- Helper: Perspective projection for fake-3D --- function projectZ(z) { // Returns scale and y offset for a given depth (z) // Camera is at y = horizonY, looking down corridor var screenH = 2732; var horizonY = screenH * 0.42; var vanishY = horizonY; var baseScale = 1.0; // Perspective: scale = nearPlane / (z + nearPlane) var near = 1.2; var scale = near / (z + near); var y = vanishY + screenH * 0.32 / (z + 0.7); return { scale: scale, y: y }; } // --- Helper: X position for lane at given depth --- function laneX(lane, z) { var centerX = 2048 / 2; var laneOffset = (lane - 1) * corridor.laneWidth; var p = projectZ(z); return centerX + laneOffset * p.scale; } // --- Helper: Y position for row at given depth --- function laneY(row, z) { // row: 0=top, 1=bottom var baseY = 0; var rowOffset = (row - 0.5) * corridor.rowHeight; var p = projectZ(z); return baseY + rowOffset * p.scale; } // --- Spawning obstacles and collectibles --- function spawnObject() { // Randomly choose obstacle or collectible var isObstacle = Math.random() < 0.7; var lane = Math.floor(Math.random() * corridor.width); var row = Math.floor(Math.random() * corridor.height); var depth = corridor.maxDepth + 2; // spawn just beyond farthest slice var obj; if (isObstacle) { obj = new Obstacle(); } else { obj = new Collectible(); } obj.lane = lane; obj.row = row; obj.depth = depth; obj.active = true; objects.push(obj); game.addChild(obj); } // --- Input: Improved player movement handling (tap and swipe) --- var lastTouchY = null; var swipeDeadzoneX = 220; var swipeDeadzoneY = 400; var tapDeadzoneX = 320; var tapDeadzoneY = 480; game.down = function (x, y, obj) { lastTouchX = x; lastTouchY = y; // Only allow tap-to-move if not moving, alive, and not in input delay if (!player.moving && player.alive && !inputDelayActive) { var centerX = 2048 / 2; var centerY = 2732 / 2; var moved = false; // Calculate tap direction relative to player var dx = x - centerX; var dy = y - centerY; // Determine the general direction of the tap // Use atan2 to get the angle, then map to 4 directions var angle = Math.atan2(dy, dx); // Directions: right (0), down (PI/2), left (PI or -PI), up (-PI/2) // We'll use wider sectors for left/right (±67.5° = 3*PI/8) // Expand up/down sectors to ±90° (PI/2) for even easier up/down movement if (angle >= -3 * Math.PI / 8 && angle < 3 * Math.PI / 8 && player.lane < 2) { // Right (expanded range) movePlayerTo(player.lane + 1, player.row); moved = true; } else if (angle >= 3 * Math.PI / 8 && angle < 5 * Math.PI / 8 && player.lane < 2) { // Right-Down diagonal (optional, still right) movePlayerTo(player.lane + 1, player.row); moved = true; } else if (angle >= 5 * Math.PI / 8 && angle < 11 * Math.PI / 8 && player.row < 1) { // Down (expanded range, now ±90°) movePlayerTo(player.lane, player.row + 1); moved = true; } else if ((angle >= 11 * Math.PI / 8 && angle <= Math.PI || angle <= -3 * Math.PI / 8 && angle >= -Math.PI) && player.lane > 0) { // Left (further expanded range) movePlayerTo(player.lane - 1, player.row); moved = true; } else if (angle >= -11 * Math.PI / 8 && angle < -5 * Math.PI / 8 && player.row > 0) { // Up (expanded range, now ±90°) movePlayerTo(player.lane, player.row - 1); moved = true; } else if (angle >= -5 * Math.PI / 8 && angle < -3 * Math.PI / 8 && player.lane < 2) { // Right-Up diagonal (optional, still right) movePlayerTo(player.lane + 1, player.row); moved = true; } if (moved) { inputDelayActive = true; if (inputDelayTimer !== null) LK.clearTimeout(inputDelayTimer); inputDelayTimer = LK.setTimeout(function () { inputDelayActive = false; inputDelayTimer = null; }, inputDelayMs); } } }; game.move = function (x, y, obj) { // No swipe-to-move: do nothing on move }; game.up = function (x, y, obj) { lastTouchX = null; lastTouchY = null; }; // --- Move player to lane with tween --- function movePlayerTo(targetLane, targetRow) { if (player.moving || !player.alive) return; if (typeof targetRow === "undefined") targetRow = player.row; player.moveTarget = targetLane; player.moveRowTarget = targetRow; player.moving = true; // Activate input delay immediately on move inputDelayActive = true; if (inputDelayTimer !== null) LK.clearTimeout(inputDelayTimer); inputDelayTimer = LK.setTimeout(function () { inputDelayActive = false; inputDelayTimer = null; }, inputDelayMs); var startLane = player.lane; var endLane = targetLane; var startRow = player.row; var endRow = targetRow; var t = { v: startLane }; var tr = { v: startRow }; player.moveTween = tween(t, { v: endLane }, { duration: 180, easing: tween.cubicOut, onFinish: function onFinish() { player.lane = endLane; player.moving = false; // If a move was queued during the tween, perform it now if (typeof player.queuedMove !== "undefined" && player.queuedMove !== null && (player.queuedMove !== player.lane || player.queuedRowMove !== player.row)) { var nextLane = player.queuedMove; var nextRow = player.queuedRowMove; player.queuedMove = null; player.queuedRowMove = null; movePlayerTo(nextLane, nextRow); } } }); player.moveRowTween = tween(tr, { v: endRow }, { duration: 180, easing: tween.cubicOut, onFinish: function onFinish() { player.row = endRow; } }); // We'll interpolate player.lane and player.row visually in render player.laneTweenObj = t; player.rowTweenObj = tr; } // --- Main update loop --- game.update = function () { if (!player.alive) return; // Increase speed over time speed += speedIncrease; if (speed > maxSpeed) speed = maxSpeed; distance += speed; distTxt.setText(Math.floor(distance) + "m"); // Spawn new objects spawnTimer--; if (spawnTimer <= 0) { spawnObject(); spawnTimer = spawnInterval - Math.floor(distance / 60); if (spawnTimer < 18) spawnTimer = 18; } // Move objects closer (decrease depth) for (var i = objects.length - 1; i >= 0; i--) { var obj = objects[i]; obj.depth -= speed; if (obj.depth < 0.2) { // Passed player, remove obj.destroy(); objects.splice(i, 1); continue; } // Project to screen var p = projectZ(obj.depth); obj.scaleX = obj.scaleY = p.scale * 1.2; if (typeof obj.row === "undefined") obj.row = 1; obj.x = laneX(obj.lane, obj.depth); obj.y = p.y + 320 * p.scale + laneY(obj.row, obj.depth); obj.visible = obj.depth > 0.2 && obj.depth < corridor.maxDepth + 2; } // Player lane interpolation (for smooth movement) var visLane = player.lane; var visRow = player.row; if (player.moving && player.laneTweenObj) { visLane = player.laneTweenObj.v; } if (player.moving && player.rowTweenObj) { visRow = player.rowTweenObj.v; } // --- Render corridor slices --- for (var i = 0; i < corridor.depthSlices; i++) { // Offset z by distance to make walls/floor/ceiling scroll opposite to objects var z = i + 1.2 - distance % 1; // reverse scroll direction var p = projectZ(z); // Walls var wallW = 80 * p.scale * 2.2; var wallH = 800 * p.scale * 2.2; // Left wall var wl = wallNodes[i * 2]; wl.x = laneX(0, z) - corridor.laneWidth * p.scale / 2 - wallW / 2; wl.y = p.y + wallH; wl.width = wallW; wl.height = wallH; wl.visible = true; // Right wall var wr = wallNodes[i * 2 + 1]; wr.x = laneX(2, z) + corridor.laneWidth * p.scale / 2 + wallW / 2; wr.y = p.y + wallH; wr.width = wallW; wr.height = wallH; wr.visible = true; // Floor var fl = floorNodes[i]; fl.x = 2048 / 2; fl.y = p.y + wallH; fl.width = corridor.laneWidth * corridor.width * p.scale * 1.1; fl.height = 80 * p.scale * 2.2; fl.visible = true; // Ceiling var cl = ceilingNodes[i]; cl.x = 2048 / 2; cl.y = p.y - 80 * p.scale * 1.2; cl.width = corridor.laneWidth * corridor.width * p.scale * 1.1; cl.height = 80 * p.scale * 2.2; cl.visible = true; } // --- Collision detection --- // Player is always at z=0, y=bottom of screen var playerZ = 0.7; var playerP = projectZ(playerZ); var playerX = laneX(visLane, playerZ); var playerY = playerP.y + 320 * playerP.scale + laneY(visRow, playerZ); var playerW = 340 * playerP.scale * 1.2; var playerH = 420 * playerP.scale * 1.2; // --- Render player visual representation --- if (typeof player.visual === "undefined") { // Create the player visual using a new asset, anchor center player.visual = LK.getAsset('player', { anchorX: 0.5, anchorY: 1 }); player.visual.width = 340; player.visual.height = 420; player.visual.alpha = 0.98; game.addChild(player.visual); } player.visual.visible = player.alive; player.visual.x = playerX; player.visual.y = playerY; player.visual.scaleX = playerW / player.visual.width; player.visual.scaleY = playerH / player.visual.height; // Move player visual to top of display list so it draws after all objects if (player.visual.parent && player.visual.parent.children) { var children = player.visual.parent.children; if (children[children.length - 1] !== player.visual) { // Remove and re-add to move to top, but only if parent still exists var parent = player.visual.parent; if (parent) { parent.removeChild(player.visual); parent.addChild(player.visual); } } } // For debugging, could render a player shadow here for (var i = objects.length - 1; i >= 0; i--) { var obj = objects[i]; if (!obj.active) continue; // Only check collision if close enough if (obj.depth < 1.2 && obj.depth > 0.2) { var dx = Math.abs(obj.x - playerX); var dy = Math.abs(obj.y - playerY); var hitW = (playerW + obj.width) / 2; var hitH = (playerH + obj.height) / 2; if (dx < hitW * 0.7 && dy < hitH * 0.7) { if (obj.type === 'obstacle') { // Hit obstacle: game over player.alive = false; LK.effects.flashScreen(0xff0000, 900); LK.showGameOver(); return; } else if (obj.type === 'collectible') { // Collect item obj.active = false; score += 1; LK.setScore(score); scoreTxt.setText(score); tween(obj, { scaleX: 2.2, scaleY: 2.2, alpha: 0 }, { duration: 220, easing: tween.cubicOut, onFinish: function onFinish() { obj.destroy(); } }); objects.splice(i, 1); } } } } }; // --- Reset game state on new game --- function resetGame() { // Remove all objects for (var i = 0; i < objects.length; i++) { objects[i].destroy(); } objects = []; player.lane = 1; player.row = 1; player.moving = false; player.moveTarget = 1; player.moveRowTarget = 1; player.moveTween = null; player.moveRowTween = null; player.queuedMove = null; player.queuedRowMove = null; player.alive = true; speed = 0.18; score = 0; distance = 0; spawnTimer = 18; scoreTxt.setText('0'); distTxt.setText('0m'); // Reset input delay state inputDelayActive = false; if (inputDelayTimer !== null) { LK.clearTimeout(inputDelayTimer); inputDelayTimer = null; } } resetGame(); // --- LK handles game over and reset automatically, but listen for new game start --- LK.on('gameStart', function () { resetGame(); });
===================================================================
--- original.js
+++ change.js
@@ -232,25 +232,33 @@
// Use atan2 to get the angle, then map to 4 directions
var angle = Math.atan2(dy, dx);
// Directions: right (0), down (PI/2), left (PI or -PI), up (-PI/2)
// We'll use wider sectors for left/right (±67.5° = 3*PI/8)
- // Expand up/down sectors to ±67.5° (3*PI/8) as well
+ // Expand up/down sectors to ±90° (PI/2) for even easier up/down movement
if (angle >= -3 * Math.PI / 8 && angle < 3 * Math.PI / 8 && player.lane < 2) {
// Right (expanded range)
movePlayerTo(player.lane + 1, player.row);
moved = true;
- } else if (angle >= 3 * Math.PI / 8 && angle < 9 * Math.PI / 8 && player.row < 1) {
- // Down (expanded range)
+ } else if (angle >= 3 * Math.PI / 8 && angle < 5 * Math.PI / 8 && player.lane < 2) {
+ // Right-Down diagonal (optional, still right)
+ movePlayerTo(player.lane + 1, player.row);
+ moved = true;
+ } else if (angle >= 5 * Math.PI / 8 && angle < 11 * Math.PI / 8 && player.row < 1) {
+ // Down (expanded range, now ±90°)
movePlayerTo(player.lane, player.row + 1);
moved = true;
- } else if ((angle >= 3 * Math.PI / 8 && angle <= Math.PI || angle <= -3 * Math.PI / 8 && angle >= -Math.PI) && player.lane > 0) {
+ } else if ((angle >= 11 * Math.PI / 8 && angle <= Math.PI || angle <= -3 * Math.PI / 8 && angle >= -Math.PI) && player.lane > 0) {
// Left (further expanded range)
movePlayerTo(player.lane - 1, player.row);
moved = true;
- } else if (angle >= -9 * Math.PI / 8 && angle < -3 * Math.PI / 8 && player.row > 0) {
- // Up (expanded range)
+ } else if (angle >= -11 * Math.PI / 8 && angle < -5 * Math.PI / 8 && player.row > 0) {
+ // Up (expanded range, now ±90°)
movePlayerTo(player.lane, player.row - 1);
moved = true;
+ } else if (angle >= -5 * Math.PI / 8 && angle < -3 * Math.PI / 8 && player.lane < 2) {
+ // Right-Up diagonal (optional, still right)
+ movePlayerTo(player.lane + 1, player.row);
+ moved = true;
}
if (moved) {
inputDelayActive = true;
if (inputDelayTimer !== null) LK.clearTimeout(inputDelayTimer);