/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Enemy class (moves left/right)
var Enemy = Container.expand(function () {
var self = Container.call(this);
var en = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 2;
self.direction = Math.random() < 0.5 ? 1 : -1;
self.range = 300 + Math.random() * 200;
self.originX = 0;
self.update = function () {
self.x += self.speed * self.direction;
if (Math.abs(self.x - self.originX) > self.range) {
self.direction *= -1;
}
};
return self;
});
// Football class (follows player or can be dropped)
var Football = Container.expand(function () {
var self = Container.call(this);
var fb = self.attachAsset('football', {
anchorX: 0.5,
anchorY: 0.5
});
self.carried = true;
self.vx = 0;
self.vy = 0;
self.update = function () {
if (!self.carried) {
// Gravity
self.vy += 2.5;
self.x += self.vx;
self.y += self.vy;
// Collide with platforms
for (var i = 0; i < platforms.length; ++i) {
var p = platforms[i];
if (self.intersects(p) && self.vy > 0) {
self.y = p.y - p.height / 2 - self.height / 2;
self.vy = 0;
}
}
// Clamp to ground
if (self.y > 2732 - 40) {
self.y = 2732 - 40;
self.vy = 0;
}
}
};
return self;
});
// Goal class
var Goal = Container.expand(function () {
var self = Container.call(this);
var g = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Hazard class
var Hazard = Container.expand(function () {
var self = Container.call(this);
var hz = self.attachAsset('hazard', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Platform class
var Platform = Container.expand(function () {
var self = Container.call(this);
var plat = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var pl = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.vx = 0;
self.vy = 0;
self.onGround = false;
self.carrying = true;
self.update = function () {
// Apply gravity
self.vy += 3.5;
// Move
self.x += self.vx;
self.y += self.vy;
// Clamp to world bounds
if (self.x < self.width / 2) self.x = self.width / 2;
if (self.x > 2048 - self.width / 2) self.x = 2048 - self.width / 2;
if (self.y > 2732 - 40) {
self.y = 2732 - 40;
self.vy = 0;
self.onGround = true;
}
// Collide with platforms
self.onGround = false;
for (var i = 0; i < platforms.length; ++i) {
var p = platforms[i];
if (self.intersects(p) && self.vy > 0) {
self.y = p.y - p.height / 2 - self.height / 2;
self.vy = 0;
self.onGround = true;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222244
});
/****
* Game Code
****/
// Football (ellipse), Player (box), Enemy (box), Platform (box), Goal (box), Hazard (box)
// Level data (platforms, hazards, enemies)
var level = 1;
if (storage.level) level = storage.level;
var platforms = [];
var hazards = [];
var enemies = [];
var player = null;
var football = null;
var goal = null;
var dragging = false;
var dragStartX = 0;
var dragStartY = 0;
var moveDir = 0; // -1 left, 1 right, 0 none
var jumpQueued = false;
var infoText = null;
var levelText = null;
var carryingBall = true;
var canPickupBall = false;
var lastGoalIntersect = false;
var lastEnemyIntersect = false;
var lastHazardIntersect = false;
var lastFootballIntersect = false;
var lastFootballGoalIntersect = false;
var lastFootballHazardIntersect = false;
var lastFootballEnemyIntersect = false;
// GUI: Level display
levelText = new Text2('Level ' + level, {
size: 90,
fill: '#fff'
});
levelText.anchor.set(0.5, 0);
LK.gui.top.addChild(levelText);
// GUI: Info text
infoText = new Text2('', {
size: 70,
fill: '#fff'
});
infoText.anchor.set(0.5, 0);
LK.gui.bottom.addChild(infoText);
// Helper: Reset level
function setupLevel() {
// Clear old
for (var i = 0; i < platforms.length; ++i) platforms[i].destroy();
for (var i = 0; i < hazards.length; ++i) hazards[i].destroy();
for (var i = 0; i < enemies.length; ++i) enemies[i].destroy();
if (player) player.destroy();
if (football) football.destroy();
if (goal) goal.destroy();
platforms = [];
hazards = [];
enemies = [];
player = null;
football = null;
goal = null;
carryingBall = true;
canPickupBall = false;
lastGoalIntersect = false;
lastEnemyIntersect = false;
lastHazardIntersect = false;
lastFootballIntersect = false;
lastFootballGoalIntersect = false;
lastFootballHazardIntersect = false;
lastFootballEnemyIntersect = false;
// Level layout
// Start platform
var plat = new Platform();
plat.x = 200;
plat.y = 2500;
game.addChild(plat);
platforms.push(plat);
// Middle platforms
var platCount = 4 + level;
for (var i = 0; i < platCount; ++i) {
var p = new Platform();
p.x = 400 + i * 350 + Math.random() * 80;
p.y = 2500 - i * 350 + Math.random() * 60;
game.addChild(p);
platforms.push(p);
// Hazards
if (level > 1 && Math.random() < 0.4) {
var hz = new Hazard();
hz.x = p.x + (Math.random() < 0.5 ? -1 : 1) * 100;
hz.y = p.y - 40;
game.addChild(hz);
hazards.push(hz);
}
// Enemies
if (level > 1 && Math.random() < 0.5) {
var en = new Enemy();
en.x = p.x;
en.y = p.y - 100;
en.originX = en.x;
game.addChild(en);
enemies.push(en);
}
}
// Goal
goal = new Goal();
goal.x = platforms[platforms.length - 1].x + 300;
goal.y = platforms[platforms.length - 1].y - 60;
game.addChild(goal);
// Player
player = new Player();
player.x = plat.x;
player.y = plat.y - 120;
game.addChild(player);
// Football
football = new Football();
football.x = player.x;
football.y = player.y - 100;
football.carried = true;
game.addChild(football);
// GUI
levelText.setText('Level ' + level);
infoText.setText('Drag to move, tap to jump');
}
// Touch controls
game.down = function (x, y, obj) {
// If tap below half screen, jump
if (y > 2732 / 2) {
jumpQueued = true;
return;
}
// Else, drag to move
dragging = true;
dragStartX = x;
dragStartY = y;
moveDir = 0;
};
game.move = function (x, y, obj) {
if (dragging) {
var dx = x - dragStartX;
if (Math.abs(dx) > 30) {
moveDir = dx > 0 ? 1 : -1;
} else {
moveDir = 0;
}
}
};
game.up = function (x, y, obj) {
dragging = false;
moveDir = 0;
};
// Main update loop
game.update = function () {
// Player movement
if (moveDir !== 0) {
player.vx = 14 * moveDir;
} else {
player.vx *= 0.7;
if (Math.abs(player.vx) < 1) player.vx = 0;
}
// Jump
if (jumpQueued && player.onGround) {
player.vy = -55 - 4 * level;
jumpQueued = false;
}
jumpQueued = false;
// Update player, football, enemies
player.update();
football.update();
for (var i = 0; i < enemies.length; ++i) enemies[i].update();
// Carry football
if (football.carried) {
football.x = player.x;
football.y = player.y - player.height / 2 - football.height / 2 + 20;
football.vx = 0;
football.vy = 0;
}
// Football pickup
var footballNear = player.intersects(football);
if (!football.carried && footballNear && !carryingBall) {
carryingBall = true;
football.carried = true;
infoText.setText('Ball picked up!');
tween(infoText, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
infoText.setText('');
infoText.alpha = 1;
}
});
}
// Football drop on enemy/hazard
var hitEnemy = false;
for (var i = 0; i < enemies.length; ++i) {
if (player.intersects(enemies[i]) && football.carried) hitEnemy = true;
}
var hitHazard = false;
for (var i = 0; i < hazards.length; ++i) {
if (player.intersects(hazards[i]) && football.carried) hitHazard = true;
}
if ((hitEnemy || hitHazard) && football.carried) {
football.carried = false;
carryingBall = false;
football.vx = player.vx * 0.7;
football.vy = -20;
infoText.setText('You dropped the ball!');
tween(infoText, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
infoText.setText('');
infoText.alpha = 1;
}
});
LK.effects.flashObject(player, 0xff0000, 600);
}
// Football collides with hazard/enemy: reset to start
var fbHitHazard = false;
for (var i = 0; i < hazards.length; ++i) {
if (football.intersects(hazards[i]) && !football.carried) fbHitHazard = true;
}
var fbHitEnemy = false;
for (var i = 0; i < enemies.length; ++i) {
if (football.intersects(enemies[i]) && !football.carried) fbHitEnemy = true;
}
if ((fbHitHazard || fbHitEnemy) && !football.carried) {
// Reset football to start
football.x = platforms[0].x;
football.y = platforms[0].y - 100;
football.vx = 0;
football.vy = 0;
infoText.setText('Ball reset!');
tween(infoText, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
infoText.setText('');
infoText.alpha = 1;
}
});
}
// Win condition: player+football at goal
var atGoal = player.intersects(goal);
var fbAtGoal = football.intersects(goal);
if (atGoal && football.carried && fbAtGoal) {
// Next level
infoText.setText('Touchdown! Next level...');
tween(infoText, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
infoText.setText('');
infoText.alpha = 1;
}
});
level += 1;
storage.level = level;
LK.setTimeout(setupLevel, 1200);
return;
}
// Lose condition: player falls off
if (player.y > 2732 - 10) {
LK.effects.flashScreen(0xff0000, 1000);
infoText.setText('You fell! Try again.');
tween(infoText, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
infoText.setText('');
infoText.alpha = 1;
}
});
LK.setTimeout(setupLevel, 1200);
return;
}
// Lose condition: football lost off screen
if (football.y > 2732 - 10) {
infoText.setText('Ball lost! Try again.');
tween(infoText, {
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
infoText.setText('');
infoText.alpha = 1;
}
});
LK.setTimeout(setupLevel, 1200);
return;
}
};
// Start first level
setupLevel(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,429 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+// Enemy class (moves left/right)
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var en = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 3 + Math.random() * 2;
+ self.direction = Math.random() < 0.5 ? 1 : -1;
+ self.range = 300 + Math.random() * 200;
+ self.originX = 0;
+ self.update = function () {
+ self.x += self.speed * self.direction;
+ if (Math.abs(self.x - self.originX) > self.range) {
+ self.direction *= -1;
+ }
+ };
+ return self;
+});
+// Football class (follows player or can be dropped)
+var Football = Container.expand(function () {
+ var self = Container.call(this);
+ var fb = self.attachAsset('football', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.carried = true;
+ self.vx = 0;
+ self.vy = 0;
+ self.update = function () {
+ if (!self.carried) {
+ // Gravity
+ self.vy += 2.5;
+ self.x += self.vx;
+ self.y += self.vy;
+ // Collide with platforms
+ for (var i = 0; i < platforms.length; ++i) {
+ var p = platforms[i];
+ if (self.intersects(p) && self.vy > 0) {
+ self.y = p.y - p.height / 2 - self.height / 2;
+ self.vy = 0;
+ }
+ }
+ // Clamp to ground
+ if (self.y > 2732 - 40) {
+ self.y = 2732 - 40;
+ self.vy = 0;
+ }
+ }
+ };
+ return self;
+});
+// Goal class
+var Goal = Container.expand(function () {
+ var self = Container.call(this);
+ var g = self.attachAsset('goal', {
+ anchorX: 0.5,
+ anchorY: 1
+ });
+ return self;
+});
+// Hazard class
+var Hazard = Container.expand(function () {
+ var self = Container.call(this);
+ var hz = self.attachAsset('hazard', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Platform class
+var Platform = Container.expand(function () {
+ var self = Container.call(this);
+ var plat = self.attachAsset('platform', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ return self;
+});
+// Player class
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var pl = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.onGround = false;
+ self.carrying = true;
+ self.update = function () {
+ // Apply gravity
+ self.vy += 3.5;
+ // Move
+ self.x += self.vx;
+ self.y += self.vy;
+ // Clamp to world bounds
+ if (self.x < self.width / 2) self.x = self.width / 2;
+ if (self.x > 2048 - self.width / 2) self.x = 2048 - self.width / 2;
+ if (self.y > 2732 - 40) {
+ self.y = 2732 - 40;
+ self.vy = 0;
+ self.onGround = true;
+ }
+ // Collide with platforms
+ self.onGround = false;
+ for (var i = 0; i < platforms.length; ++i) {
+ var p = platforms[i];
+ if (self.intersects(p) && self.vy > 0) {
+ self.y = p.y - p.height / 2 - self.height / 2;
+ self.vy = 0;
+ self.onGround = true;
+ }
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222244
+});
+
+/****
+* Game Code
+****/
+// Football (ellipse), Player (box), Enemy (box), Platform (box), Goal (box), Hazard (box)
+// Level data (platforms, hazards, enemies)
+var level = 1;
+if (storage.level) level = storage.level;
+var platforms = [];
+var hazards = [];
+var enemies = [];
+var player = null;
+var football = null;
+var goal = null;
+var dragging = false;
+var dragStartX = 0;
+var dragStartY = 0;
+var moveDir = 0; // -1 left, 1 right, 0 none
+var jumpQueued = false;
+var infoText = null;
+var levelText = null;
+var carryingBall = true;
+var canPickupBall = false;
+var lastGoalIntersect = false;
+var lastEnemyIntersect = false;
+var lastHazardIntersect = false;
+var lastFootballIntersect = false;
+var lastFootballGoalIntersect = false;
+var lastFootballHazardIntersect = false;
+var lastFootballEnemyIntersect = false;
+// GUI: Level display
+levelText = new Text2('Level ' + level, {
+ size: 90,
+ fill: '#fff'
+});
+levelText.anchor.set(0.5, 0);
+LK.gui.top.addChild(levelText);
+// GUI: Info text
+infoText = new Text2('', {
+ size: 70,
+ fill: '#fff'
+});
+infoText.anchor.set(0.5, 0);
+LK.gui.bottom.addChild(infoText);
+// Helper: Reset level
+function setupLevel() {
+ // Clear old
+ for (var i = 0; i < platforms.length; ++i) platforms[i].destroy();
+ for (var i = 0; i < hazards.length; ++i) hazards[i].destroy();
+ for (var i = 0; i < enemies.length; ++i) enemies[i].destroy();
+ if (player) player.destroy();
+ if (football) football.destroy();
+ if (goal) goal.destroy();
+ platforms = [];
+ hazards = [];
+ enemies = [];
+ player = null;
+ football = null;
+ goal = null;
+ carryingBall = true;
+ canPickupBall = false;
+ lastGoalIntersect = false;
+ lastEnemyIntersect = false;
+ lastHazardIntersect = false;
+ lastFootballIntersect = false;
+ lastFootballGoalIntersect = false;
+ lastFootballHazardIntersect = false;
+ lastFootballEnemyIntersect = false;
+ // Level layout
+ // Start platform
+ var plat = new Platform();
+ plat.x = 200;
+ plat.y = 2500;
+ game.addChild(plat);
+ platforms.push(plat);
+ // Middle platforms
+ var platCount = 4 + level;
+ for (var i = 0; i < platCount; ++i) {
+ var p = new Platform();
+ p.x = 400 + i * 350 + Math.random() * 80;
+ p.y = 2500 - i * 350 + Math.random() * 60;
+ game.addChild(p);
+ platforms.push(p);
+ // Hazards
+ if (level > 1 && Math.random() < 0.4) {
+ var hz = new Hazard();
+ hz.x = p.x + (Math.random() < 0.5 ? -1 : 1) * 100;
+ hz.y = p.y - 40;
+ game.addChild(hz);
+ hazards.push(hz);
+ }
+ // Enemies
+ if (level > 1 && Math.random() < 0.5) {
+ var en = new Enemy();
+ en.x = p.x;
+ en.y = p.y - 100;
+ en.originX = en.x;
+ game.addChild(en);
+ enemies.push(en);
+ }
+ }
+ // Goal
+ goal = new Goal();
+ goal.x = platforms[platforms.length - 1].x + 300;
+ goal.y = platforms[platforms.length - 1].y - 60;
+ game.addChild(goal);
+ // Player
+ player = new Player();
+ player.x = plat.x;
+ player.y = plat.y - 120;
+ game.addChild(player);
+ // Football
+ football = new Football();
+ football.x = player.x;
+ football.y = player.y - 100;
+ football.carried = true;
+ game.addChild(football);
+ // GUI
+ levelText.setText('Level ' + level);
+ infoText.setText('Drag to move, tap to jump');
+}
+// Touch controls
+game.down = function (x, y, obj) {
+ // If tap below half screen, jump
+ if (y > 2732 / 2) {
+ jumpQueued = true;
+ return;
+ }
+ // Else, drag to move
+ dragging = true;
+ dragStartX = x;
+ dragStartY = y;
+ moveDir = 0;
+};
+game.move = function (x, y, obj) {
+ if (dragging) {
+ var dx = x - dragStartX;
+ if (Math.abs(dx) > 30) {
+ moveDir = dx > 0 ? 1 : -1;
+ } else {
+ moveDir = 0;
+ }
+ }
+};
+game.up = function (x, y, obj) {
+ dragging = false;
+ moveDir = 0;
+};
+// Main update loop
+game.update = function () {
+ // Player movement
+ if (moveDir !== 0) {
+ player.vx = 14 * moveDir;
+ } else {
+ player.vx *= 0.7;
+ if (Math.abs(player.vx) < 1) player.vx = 0;
+ }
+ // Jump
+ if (jumpQueued && player.onGround) {
+ player.vy = -55 - 4 * level;
+ jumpQueued = false;
+ }
+ jumpQueued = false;
+ // Update player, football, enemies
+ player.update();
+ football.update();
+ for (var i = 0; i < enemies.length; ++i) enemies[i].update();
+ // Carry football
+ if (football.carried) {
+ football.x = player.x;
+ football.y = player.y - player.height / 2 - football.height / 2 + 20;
+ football.vx = 0;
+ football.vy = 0;
+ }
+ // Football pickup
+ var footballNear = player.intersects(football);
+ if (!football.carried && footballNear && !carryingBall) {
+ carryingBall = true;
+ football.carried = true;
+ infoText.setText('Ball picked up!');
+ tween(infoText, {
+ alpha: 0
+ }, {
+ duration: 1200,
+ onFinish: function onFinish() {
+ infoText.setText('');
+ infoText.alpha = 1;
+ }
+ });
+ }
+ // Football drop on enemy/hazard
+ var hitEnemy = false;
+ for (var i = 0; i < enemies.length; ++i) {
+ if (player.intersects(enemies[i]) && football.carried) hitEnemy = true;
+ }
+ var hitHazard = false;
+ for (var i = 0; i < hazards.length; ++i) {
+ if (player.intersects(hazards[i]) && football.carried) hitHazard = true;
+ }
+ if ((hitEnemy || hitHazard) && football.carried) {
+ football.carried = false;
+ carryingBall = false;
+ football.vx = player.vx * 0.7;
+ football.vy = -20;
+ infoText.setText('You dropped the ball!');
+ tween(infoText, {
+ alpha: 0
+ }, {
+ duration: 1200,
+ onFinish: function onFinish() {
+ infoText.setText('');
+ infoText.alpha = 1;
+ }
+ });
+ LK.effects.flashObject(player, 0xff0000, 600);
+ }
+ // Football collides with hazard/enemy: reset to start
+ var fbHitHazard = false;
+ for (var i = 0; i < hazards.length; ++i) {
+ if (football.intersects(hazards[i]) && !football.carried) fbHitHazard = true;
+ }
+ var fbHitEnemy = false;
+ for (var i = 0; i < enemies.length; ++i) {
+ if (football.intersects(enemies[i]) && !football.carried) fbHitEnemy = true;
+ }
+ if ((fbHitHazard || fbHitEnemy) && !football.carried) {
+ // Reset football to start
+ football.x = platforms[0].x;
+ football.y = platforms[0].y - 100;
+ football.vx = 0;
+ football.vy = 0;
+ infoText.setText('Ball reset!');
+ tween(infoText, {
+ alpha: 0
+ }, {
+ duration: 1200,
+ onFinish: function onFinish() {
+ infoText.setText('');
+ infoText.alpha = 1;
+ }
+ });
+ }
+ // Win condition: player+football at goal
+ var atGoal = player.intersects(goal);
+ var fbAtGoal = football.intersects(goal);
+ if (atGoal && football.carried && fbAtGoal) {
+ // Next level
+ infoText.setText('Touchdown! Next level...');
+ tween(infoText, {
+ alpha: 0
+ }, {
+ duration: 1200,
+ onFinish: function onFinish() {
+ infoText.setText('');
+ infoText.alpha = 1;
+ }
+ });
+ level += 1;
+ storage.level = level;
+ LK.setTimeout(setupLevel, 1200);
+ return;
+ }
+ // Lose condition: player falls off
+ if (player.y > 2732 - 10) {
+ LK.effects.flashScreen(0xff0000, 1000);
+ infoText.setText('You fell! Try again.');
+ tween(infoText, {
+ alpha: 0
+ }, {
+ duration: 1200,
+ onFinish: function onFinish() {
+ infoText.setText('');
+ infoText.alpha = 1;
+ }
+ });
+ LK.setTimeout(setupLevel, 1200);
+ return;
+ }
+ // Lose condition: football lost off screen
+ if (football.y > 2732 - 10) {
+ infoText.setText('Ball lost! Try again.');
+ tween(infoText, {
+ alpha: 0
+ }, {
+ duration: 1200,
+ onFinish: function onFinish() {
+ infoText.setText('');
+ infoText.alpha = 1;
+ }
+ });
+ LK.setTimeout(setupLevel, 1200);
+ return;
+ }
+};
+// Start first level
+setupLevel();
\ No newline at end of file