/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Checkpoint class: save progress var Checkpoint = Container.expand(function () { var self = Container.call(this); var cp = self.attachAsset('checkpoint', { anchorX: 0.5, anchorY: 1 }); self.activated = false; self.activate = function () { if (!self.activated) { self.activated = true; tween(cp, { tint: 0x00ff00 }, { duration: 300 }); } }; return self; }); // Platform class: static or moving platform var Platform = Container.expand(function () { var self = Container.call(this); // Attach platform asset (box shape) var plat = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); // Platform movement config self.isMoving = false; self.moveAxis = 'x'; // 'x' or 'y' self.moveFrom = 0; self.moveTo = 0; self.moveDuration = 0; self.moveDir = 1; // For moving platforms, set up tween self.startMove = function () { if (!self.isMoving) return; var prop = {}; prop[self.moveAxis] = self.moveTo; tween(self, prop, { duration: self.moveDuration, easing: tween.linear, onFinish: function onFinish() { // Swap direction var tmp = self.moveFrom; self.moveFrom = self.moveTo; self.moveTo = tmp; self.startMove(); } }); }; return self; }); // Player class: main character var Player = Container.expand(function () { var self = Container.call(this); var _char = self.attachAsset('player', { anchorX: 0.5, anchorY: 1 }); self.width = _char.width; self.height = _char.height; self.vx = 0; self.vy = 0; self.onGround = false; self.dead = false; self.jumpQueued = false; self.respawn = function (x, y) { self.x = x; self.y = y; self.vx = 0; self.vy = 0; self.dead = false; }; return self; }); // Spike class: deadly obstacle var Spike = Container.expand(function () { var self = Container.call(this); // Attach spike asset (triangle shape, but use box for now) var spike = self.attachAsset('spike', { anchorX: 0.5, anchorY: 1 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // --- Asset Initialization --- // Tween plugin for platform/character movement and effects // --- Level Data (MVP: 1 level, hardcoded) --- /* Level is an array of objects: {type: 'platform'|'spike'|'checkpoint', x, y, [w], [h], [moveAxis], [moveFrom], [moveTo], [moveDuration]} All positions are in game coordinates. */ var levelData = [ // Floor { type: 'platform', x: 1024, y: 2600, w: 1200, h: 60 }, // First jump { type: 'platform', x: 600, y: 2200, w: 400, h: 40 }, { type: 'spike', x: 800, y: 2160 }, // Second jump { type: 'platform', x: 1400, y: 2000, w: 400, h: 40 }, { type: 'spike', x: 1200, y: 1960 }, // Moving platform { type: 'platform', x: 1024, y: 1700, w: 300, h: 40, moveAxis: 'x', moveFrom: 724, moveTo: 1324, moveDuration: 1800 }, { type: 'spike', x: 1024, y: 1660 }, // Checkpoint { type: 'checkpoint', x: 1024, y: 1600 }, // Final platform { type: 'platform', x: 1024, y: 1200, w: 400, h: 40 }, // End spike { type: 'spike', x: 1024, y: 1160 }]; // --- Game State --- var platforms = []; var spikes = []; var checkpoints = []; var player = null; var currentCheckpoint = null; var deaths = 0; var levelEndY = 1100; // Y position to reach to win // --- UI --- var deathsTxt = new Text2('Deaths: 0', { size: 90, fill: "#fff" }); deathsTxt.anchor.set(0.5, 0); LK.gui.top.addChild(deathsTxt); // --- Level Construction --- function buildLevel() { // Clear previous for (var i = 0; i < platforms.length; ++i) platforms[i].destroy(); for (var i = 0; i < spikes.length; ++i) spikes[i].destroy(); for (var i = 0; i < checkpoints.length; ++i) checkpoints[i].destroy(); platforms = []; spikes = []; checkpoints = []; currentCheckpoint = null; // Build for (var i = 0; i < levelData.length; ++i) { var obj = levelData[i]; if (obj.type === 'platform') { var plat = new Platform(); plat.x = obj.x; plat.y = obj.y; plat.width = obj.w || 400; plat.height = obj.h || 40; plat.children[0].width = plat.width; plat.children[0].height = plat.height; if (obj.moveAxis) { plat.isMoving = true; plat.moveAxis = obj.moveAxis; plat.moveFrom = obj.moveFrom; plat.moveTo = obj.moveTo; plat.moveDuration = obj.moveDuration; plat[plat.moveAxis] = plat.moveFrom; plat.startMove(); } game.addChild(plat); platforms.push(plat); } else if (obj.type === 'spike') { var spike = new Spike(); spike.x = obj.x; spike.y = obj.y; game.addChild(spike); spikes.push(spike); } else if (obj.type === 'checkpoint') { var cp = new Checkpoint(); cp.x = obj.x; cp.y = obj.y; game.addChild(cp); checkpoints.push(cp); } } } // --- Player Spawn --- function spawnPlayer() { if (player) player.destroy(); player = new Player(); var spawnX = 1024, spawnY = 2500; if (currentCheckpoint) { spawnX = currentCheckpoint.x; spawnY = currentCheckpoint.y - 10; } player.respawn(spawnX, spawnY); game.addChild(player); } // --- Death/Respawn --- function killPlayer() { if (player.dead) return; player.dead = true; deaths += 1; deathsTxt.setText('Deaths: ' + deaths); LK.effects.flashScreen(0xff2222, 400); LK.setTimeout(function () { spawnPlayer(); }, 400); } // --- Win Condition --- function checkWin() { if (player.y < levelEndY) { LK.showYouWin(); } } // --- Collision Helpers --- function rectsIntersect(a, b) { return a.x - a.width / 2 < b.x + b.width / 2 && a.x + a.width / 2 > b.x - b.width / 2 && a.y - a.height < b.y && a.y > b.y - b.height; } // --- Tablet Controller (Virtual Joystick) --- // Controller state var controllerActive = false; var controllerStartX = 0; var controllerStartY = 0; var controllerCurX = 0; var controllerCurY = 0; var controllerRadius = 180; // px, joystick max distance var controllerBase = null; var controllerStick = null; var controllerCenterX = 0; var controllerCenterY = 0; var controllerDirX = 0; var controllerDirY = 0; var controllerJumpQueued = false; // Place controller in bottom left, safe from menu (not in top left 100x100) controllerCenterX = 220; controllerCenterY = 2732 - 220; // Draw controller base and stick function createControllerGraphics() { if (controllerBase) controllerBase.destroy(); if (controllerStick) controllerStick.destroy(); // Use shapes for base and stick controllerBase = LK.getAsset('platform', { width: controllerRadius * 2, height: controllerRadius * 2, color: 0x444444, anchorX: 0.5, anchorY: 0.5, x: controllerCenterX, y: controllerCenterY, alpha: 0.18 }); controllerStick = LK.getAsset('player', { width: 100, height: 100, color: 0xffffff, anchorX: 0.5, anchorY: 0.5, x: controllerCenterX, y: controllerCenterY, alpha: 0.45 }); LK.gui.bottomLeft.addChild(controllerBase); LK.gui.bottomLeft.addChild(controllerStick); } createControllerGraphics(); // Helper: get distance and angle from center function getControllerInput(x, y) { var dx = x - controllerCenterX; var dy = y - controllerCenterY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > controllerRadius) { dx = dx * controllerRadius / dist; dy = dy * controllerRadius / dist; dist = controllerRadius; } return { dx: dx, dy: dy, dist: dist }; } // Touch down: activate controller if in left-bottom quarter, else jump if in right-bottom game.down = function (x, y, obj) { // Only activate controller if touch is in left-bottom quarter (not in top left 100x100) if (x < 2048 / 2 && y > 2732 - 500 && y > 100) { controllerActive = true; controllerStartX = x; controllerStartY = y; controllerCurX = x; controllerCurY = y; var input = getControllerInput(x, y); controllerStick.x = controllerCenterX + input.dx; controllerStick.y = controllerCenterY + input.dy; controllerDirX = input.dx / controllerRadius; controllerDirY = input.dy / controllerRadius; controllerJumpQueued = false; } else if (x > 2048 / 2 && y > 2732 - 500) { // Right-bottom: jump controllerJumpQueued = true; } }; game.move = function (x, y, obj) { if (controllerActive) { controllerCurX = x; controllerCurY = y; var input = getControllerInput(x, y); controllerStick.x = controllerCenterX + input.dx; controllerStick.y = controllerCenterY + input.dy; controllerDirX = input.dx / controllerRadius; controllerDirY = input.dy / controllerRadius; } }; game.up = function (x, y, obj) { controllerActive = false; controllerStick.x = controllerCenterX; controllerStick.y = controllerCenterY; controllerDirX = 0; controllerDirY = 0; controllerJumpQueued = false; }; // --- END Tablet Controller --- // --- Physics Constants --- var GRAVITY = 2.2; var MOVE_SPEED = 18; var JUMP_VEL = -48; var MAX_FALL = 60; // --- Game Update Loop --- game.update = function () { if (!player || player.dead) return; // Horizontal movement (tablet controller) if (controllerDirX < -0.2) { player.vx = -MOVE_SPEED * Math.min(1, Math.abs(controllerDirX)); } else if (controllerDirX > 0.2) { player.vx = MOVE_SPEED * Math.min(1, Math.abs(controllerDirX)); } else { player.vx = 0; } // Jump (tablet controller) if ((controllerJumpQueued || controllerActive && controllerDirY < -0.5) && player.onGround) { player.vy = JUMP_VEL; player.onGround = false; controllerJumpQueued = false; } // Gravity player.vy += GRAVITY; if (player.vy > MAX_FALL) player.vy = MAX_FALL; // Save old position var oldX = player.x, oldY = player.y; // Move X player.x += player.vx; // Collide with platforms (X axis) for (var i = 0; i < platforms.length; ++i) { var plat = platforms[i]; if (rectsIntersect(player, plat)) { if (player.vx > 0) { player.x = plat.x - plat.width / 2 - player.width / 2; } else if (player.vx < 0) { player.x = plat.x + plat.width / 2 + player.width / 2; } player.vx = 0; } } // Move Y player.y += player.vy; player.onGround = false; // Collide with platforms (Y axis) for (var i = 0; i < platforms.length; ++i) { var plat = platforms[i]; if (rectsIntersect(player, plat)) { if (player.vy > 0) { player.y = plat.y - plat.height / 2; player.onGround = true; } else if (player.vy < 0) { player.y = plat.y + plat.height / 2 + player.height; } player.vy = 0; } } // Collide with spikes for (var i = 0; i < spikes.length; ++i) { var spike = spikes[i]; if (rectsIntersect(player, spike)) { killPlayer(); return; } } // Collide with checkpoints for (var i = 0; i < checkpoints.length; ++i) { var cp = checkpoints[i]; if (!cp.activated && rectsIntersect(player, cp)) { cp.activate(); currentCheckpoint = cp; } } // Out of bounds (fall) if (player.y > 2800) { killPlayer(); return; } // Win checkWin(); }; // --- Build Level and Start --- buildLevel(); spawnPlayer(); deaths = 0; deathsTxt.setText('Deaths: 0');
===================================================================
--- original.js
+++ change.js
@@ -103,16 +103,16 @@
/****
* Game Code
****/
+// --- Asset Initialization ---
+// Tween plugin for platform/character movement and effects
+// --- Level Data (MVP: 1 level, hardcoded) ---
/*
Level is an array of objects:
{type: 'platform'|'spike'|'checkpoint', x, y, [w], [h], [moveAxis], [moveFrom], [moveTo], [moveDuration]}
All positions are in game coordinates.
*/
-// --- Level Data (MVP: 1 level, hardcoded) ---
-// Tween plugin for platform/character movement and effects
-// --- Asset Initialization ---
var levelData = [
// Floor
{
type: 'platform',