User prompt
Send 10 Yu
User prompt
When witch take the yu, cancel speed power
User prompt
When witch take the broom witch can be fly
User prompt
Send broom every 30 second
User prompt
After speed enemies can move again in 10 seconds
User prompt
"When the witch picks up a speed boost, enemies should freeze for 10 seconds and then resume their actions. Only one speed boost should drop every 40 seconds."
User prompt
Add timer to spawn a random 1 shield every 30 seconds
User prompt
When witch take 100 moon send shield
User prompt
When witch take a speed pause all enemy 10 seconds
User prompt
When witch take 5 moon send one shield just one every 5 moon send 1 random shield but just one
User prompt
After all 25 point just send one shield
User prompt
No send one shield after every 25 per point
User prompt
Every 25 point send a shield
User prompt
Make enemies more slow
User prompt
When she takes the shield she send everywhere ıce orb
User prompt
During the game İf witch take 5 moon give life potion
User prompt
İf witch take 5 moon give life potion
User prompt
Add life point with potions
User prompt
When witch hits 3 time ıce orb make bats freeze 60 second
User prompt
Make bats more slow
User prompt
Born random moon when witch takes one of them
User prompt
When she takes the moon gains 5 point
User prompt
Make life scor 7
User prompt
When push the down button she can allow down
User prompt
When she jump the other platforms she can stay onthe ground of platform
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy: Bat
var Bat = Container.expand(function (x, y) {
var self = Container.call(this);
var bat = self.attachAsset('bat', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.vx = (Math.random() > 0.5 ? 1 : -1) * (2.5 + Math.random() * 2); // Slower bats
self.vy = (Math.random() > 0.5 ? 1 : -1) * 0.5; // Slower vertical movement
self.frozen = false;
self.frozenTimer = 0;
self.trapped = false;
self.trapTimer = 0;
self.update = function () {
// Pause logic for speed powerup
if (self.pausedBySpeed) {
return;
}
if (self.trapped) {
self.trapTimer--;
if (self.trapTimer <= 0) {
self.trapped = false;
self.alpha = 1;
}
return;
}
if (self.frozen) {
self.frozenTimer--;
if (self.frozenTimer <= 0) {
self.frozen = false;
bat.tint = 0x2a2a2a;
}
return;
}
self.x += self.vx;
self.y += self.vy;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
if (self.y < 200 || self.y > 2732 - 200) self.vy *= -1;
// Prevent bats from touching platforms: bounce off if intersecting
for (var i = 0; i < platforms.length; i++) {
var p = platforms[i];
if (self.intersects(p)) {
// Bounce bat away from platform
// Determine if bat is coming from above/below or left/right
var dx = self.x - p.x;
var dy = self.y - p.y;
if (Math.abs(dx) > Math.abs(dy)) {
// Bounce horizontally
self.vx *= -1;
// Move bat out of platform horizontally
if (dx > 0) {
self.x = p.x + p.width / 2 + 40;
} else {
self.x = p.x - p.width / 2 - 40;
}
} else {
// Bounce vertically
self.vy *= -1;
// Move bat out of platform vertically
if (dy > 0) {
self.y = p.y + p.height / 2 + 40;
} else {
self.y = p.y - p.height / 2 - 40;
}
}
}
}
};
// Freeze effect
self.freeze = function () {
self.frozen = true;
self.frozenTimer = 180;
bat.tint = 0x7fdfff;
};
// Trap effect
self.trap = function () {
self.trapped = true;
self.trapTimer = 90;
self.alpha = 0.4;
};
// Shatter (destroy)
self.shatter = function () {
LK.getSound('shatter').play();
self.destroy();
var idx = enemies.indexOf(self);
if (idx >= 0) enemies.splice(idx, 1);
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
};
return self;
});
// Power-up: Broom
var BroomPower = Container.expand(function (x, y) {
var self = Container.call(this);
var broom = self.attachAsset('Broom', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.type = 'broom';
self.vy = 7 + Math.random() * 3;
self.lastY = self.y;
self.update = function () {
self.lastY = self.y;
self.y += self.vy;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
// Bounce at vertical edges
if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
self.vy *= -1;
}
if (self.y < 200) self.y = 200;
if (self.y > 2732 - 200) self.y = 2732 - 200;
};
return self;
});
// Evanasense (player) class
var Evanasense = Container.expand(function () {
var self = Container.call(this);
// Body
var body = self.attachAsset('evana', {
anchorX: 0.5,
anchorY: 0.5
});
// Hat
var hat = self.attachAsset('evana_hat', {
anchorX: 0.5,
anchorY: 1.1,
y: -60
});
// Physics
self.vx = 0;
self.vy = 0;
self.lastY = 0;
self.isOnGround = false;
self.facing = 1; // 1: right, -1: left
self.canShoot = true;
self.shootCooldown = 0;
self.shielded = false;
self.speedBoost = 0;
self.fullMoon = false;
self.fullMoonTimer = 0;
self.canFly = false;
self.flyTimer = 0;
// For power-up visuals
self.shieldSprite = null;
// Freeze spell
self.castFreeze = function () {
if (!self.canShoot) return;
self.canShoot = false;
self.shootCooldown = 30; // 0.5s cooldown
var orb = new FreezeOrb(self.x, self.y - 60, self.facing);
game.addChild(orb);
freezeOrbs.push(orb);
LK.getSound('freeze').play();
};
// Trap spell (ice block, only in full moon mode)
self.castTrap = function () {
if (!self.fullMoon) return;
var trap = new IceBlock(self.x + 100 * self.facing, self.y - 40);
game.addChild(trap);
iceBlocks.push(trap);
LK.getSound('trap').play();
};
// Power-up: Shield
self.gainShield = function () {
self.shielded = true;
if (!self.shieldSprite) {
self.shieldSprite = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
}
self.shieldSprite.visible = true;
};
self.loseShield = function () {
self.shielded = false;
if (self.shieldSprite) self.shieldSprite.visible = false;
};
// Power-up: Speed
self.gainSpeed = function () {
self.speedBoost = 180;
LK.effects.flashObject(self, 0xffe066, 400);
};
// Power-up: Full Moon
self.activateFullMoon = function () {
self.fullMoon = true;
self.fullMoonTimer = 360; // 6 seconds
LK.effects.flashObject(self, 0xf6f1c7, 600);
};
// Update
self.update = function () {
// Flying logic
if (self.canFly) {
// While flying, allow free vertical movement with up/down, and reduce gravity
if (upPressed) {
self.vy = -18;
} else if (downPressed) {
self.vy = 18;
} else {
self.vy *= 0.7;
if (Math.abs(self.vy) < 1) self.vy = 0;
}
// Optional: add a little gravity so she floats down if not pressing up
self.vy += 0.5;
if (self.vy > 24) self.vy = 24;
if (self.vy < -24) self.vy = -24;
// Flying timer
if (typeof self.flyTimer === "undefined") self.flyTimer = 600;
self.flyTimer--;
if (self.flyTimer <= 0) {
self.canFly = false;
self.flyTimer = 0;
}
} else {
// Gravity
self.vy += 2.2;
if (self.vy > 40) self.vy = 40;
}
// --- Mario-style controls: set moveDir based on button state ---
if (leftPressed && !rightPressed) {
self.moveDir = -1;
} else if (rightPressed && !leftPressed) {
self.moveDir = 1;
} else {
self.moveDir = 0;
}
// --- Up/Down button logic (for future use, e.g. drop through platforms) ---
if (upPressed) {
// Reserved for future up action (e.g. climb ladder, etc)
}
if (downPressed) {
// Reserved for future down action (e.g. drop through platform)
}
// --- Fire button logic ---
if (firePressed && self.canShoot) {
self.castFreeze();
firePressed = false; // Only fire once per press
}
// Movement
var moveSpeed = 18 + (self.speedBoost > 0 ? 10 : 0);
if (self.moveDir) {
self.vx = moveSpeed * self.moveDir;
self.facing = self.moveDir;
} else {
self.vx *= 0.7;
if (Math.abs(self.vx) < 1) self.vx = 0;
}
// Apply position
self.lastY = self.y;
// --- Mario-style jump: allow jump if jumpPressed and isOnGround ---
if (jumpPressed && self.isOnGround) {
self.vy = -38;
self.isOnGround = false;
}
self.x += self.vx;
self.y += self.vy;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
// Clamp vertically and collide with all platforms
self.isOnGround = false;
var prevBottom = self.lastY + body.height / 2;
var currBottom = self.y + body.height / 2;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
var platTop = plat.y - plat.height / 2;
// Allow drop through platforms if downPressed, except for the floor (y >= 2732-60)
var isFloor = plat.y >= 2732 - 60;
if (self.vy > 0 && prevBottom <= platTop && currBottom >= platTop && self.x + body.width / 2 > plat.x - plat.width / 2 && self.x - body.width / 2 < plat.x + plat.width / 2 && (!downPressed || isFloor)) {
self.y = platTop - body.height / 2;
self.vy = 0;
self.isOnGround = true;
}
}
// Clamp to bottom of screen
if (self.y > 2732 - 60) {
self.y = 2732 - 60;
self.vy = 0;
self.isOnGround = true;
}
// Shooting cooldown
if (!self.canShoot) {
self.shootCooldown--;
if (self.shootCooldown <= 0) {
self.canShoot = true;
}
}
// Speed boost timer
if (self.speedBoost > 0) {
self.speedBoost--;
}
// Full moon timer
if (self.fullMoon) {
self.fullMoonTimer--;
if (self.fullMoonTimer <= 0) {
self.fullMoon = false;
}
}
};
return self;
});
// Freeze orb spell
var FreezeOrb = Container.expand(function (x, y, dir) {
var self = Container.call(this);
var orb = self.attachAsset('freeze_orb', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.vx = 32 * dir;
self.lifetime = 60;
self.update = function () {
self.x += self.vx;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
var idx = freezeOrbs.indexOf(self);
if (idx >= 0) freezeOrbs.splice(idx, 1);
}
};
return self;
});
// Enemy: Ghost
var Ghost = Container.expand(function (x, y) {
var self = Container.call(this);
var ghost = self.attachAsset('ghost', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.85
});
self.x = x;
self.y = y;
self.vx = (Math.random() > 0.5 ? 1 : -1) * (3 + Math.random() * 2); // Slower ghosts
self.vy = 0;
self.frozen = false;
self.frozenTimer = 0;
self.trapped = false;
self.trapTimer = 0;
self.update = function () {
// Pause logic for speed powerup
if (self.pausedBySpeed) {
return;
}
if (self.trapped) {
self.trapTimer--;
if (self.trapTimer <= 0) {
self.trapped = false;
self.alpha = 0.85;
}
return;
}
if (self.frozen) {
self.frozenTimer--;
if (self.frozenTimer <= 0) {
self.frozen = false;
ghost.tint = 0xcfd6e6;
}
return;
}
self.x += self.vx;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
};
// Freeze effect
self.freeze = function () {
self.frozen = true;
self.frozenTimer = 180;
ghost.tint = 0x7fdfff;
};
// Trap effect
self.trap = function () {
self.trapped = true;
self.trapTimer = 90;
self.alpha = 0.4;
};
// Shatter (destroy)
self.shatter = function () {
LK.getSound('shatter').play();
self.destroy();
var idx = enemies.indexOf(self);
if (idx >= 0) enemies.splice(idx, 1);
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
};
return self;
});
// Ice block trap (full moon mode)
var IceBlock = Container.expand(function (x, y) {
var self = Container.call(this);
var block = self.attachAsset('ice_block', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.85
});
self.x = x;
self.y = y;
self.lifetime = 120;
self.update = function () {
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
self.lifetime--;
if (self.lifetime <= 0) {
self.destroy();
var idx = iceBlocks.indexOf(self);
if (idx >= 0) iceBlocks.splice(idx, 1);
}
};
return self;
});
// Power-up: Lifepotion (adds a life)
var LifepotionPower = Container.expand(function (x, y) {
var self = Container.call(this);
var potion = self.attachAsset('Lifepotion', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.type = 'lifepotion';
self.vy = 7 + Math.random() * 3;
self.lastY = self.y;
self.update = function () {
self.lastY = self.y;
self.y += self.vy;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
// Bounce at vertical edges
if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
self.vy *= -1;
}
if (self.y < 200) self.y = 200;
if (self.y > 2732 - 200) self.y = 2732 - 200;
};
return self;
});
// Power-up: Moon (full moon mode)
var MoonPower = Container.expand(function (x, y) {
var self = Container.call(this);
var moon = self.attachAsset('moon', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.type = 'moon';
self.vx = 3 + Math.random() * 2; // Slower moon movement
self.lastX = self.x;
self.update = function () {
self.lastX = self.x;
self.x += self.vx;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
};
return self;
});
// Platform
var Platform = Container.expand(function (x, y, w) {
var self = Container.call(this);
var plat = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5,
width: w || 320
});
self.x = x;
self.y = y;
self.width = w || 320;
self.height = 40;
return self;
});
// Power-up: Shield
var ShieldPower = Container.expand(function (x, y) {
var self = Container.call(this);
var shield = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.type = 'shield';
self.update = function () {
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
};
return self;
});
// Power-up: Speed
var SpeedPower = Container.expand(function (x, y) {
var self = Container.call(this);
var speed = self.attachAsset('speed', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.type = 'speed';
self.vy = 7 + Math.random() * 3;
self.lastY = self.y;
self.update = function () {
self.lastY = self.y;
self.y += self.vy;
// Snow Bros style: wrap horizontally
if (self.x < 0) self.x = 2048;
if (self.x > 2048) self.x = 0;
// Bounce at vertical edges
if (self.lastY <= 200 && self.y > 200 || self.lastY >= 2732 - 200 && self.y < 2732 - 200) {
self.vy *= -1;
}
if (self.y < 200) self.y = 200;
if (self.y > 2732 - 200) self.y = 2732 - 200;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x18141e
});
/****
* Game Code
****/
// Add background image
// Game state
var bg = LK.getAsset('bg', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732,
x: 0,
y: 0
});
game.addChild(bg);
// Main character: Evanasense (witch)
// Witch body
// Witch hat
// Enemy: Ghost
// Enemy: Bat
// Platform
// Spell: Freeze orb
// Spell: Trap (ice block)
// Power-up: Moon
// Power-up: Shield
// Power-up: Speed
// Sound effects
// Music
// --- On-screen Mario-style controls ---
// Left button
var leftBtn = new Text2('◀', {
size: 180,
fill: 0xB8E6FF
});
leftBtn.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(leftBtn);
leftBtn.x = 220;
leftBtn.y = -220;
// Right button
var rightBtn = new Text2('▶', {
size: 180,
fill: 0xB8E6FF
});
rightBtn.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(rightBtn);
rightBtn.x = 500;
rightBtn.y = -220;
// Up button
var upBtn = new Text2('▲', {
size: 140,
fill: 0xB8E6FF
});
upBtn.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(upBtn);
upBtn.x = 360;
upBtn.y = -370;
// Down button
var downBtn = new Text2('▼', {
size: 140,
fill: 0xB8E6FF
});
downBtn.anchor.set(0.5, 0.5);
LK.gui.bottomLeft.addChild(downBtn);
downBtn.x = 360;
downBtn.y = -70;
// (Jump button removed)
var fireBtn = new Text2('🔥', {
size: 170,
fill: 0xF6F1C7
});
fireBtn.anchor.set(0.5, 0.5);
LK.gui.bottomRight.addChild(fireBtn);
fireBtn.x = -500;
fireBtn.y = -220;
// Control state
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
var jumpPressed = false;
var firePressed = false;
// Touch handlers for left button
leftBtn.down = function (x, y, obj) {
leftPressed = true;
};
leftBtn.up = function (x, y, obj) {
leftPressed = false;
};
// Touch handlers for right button
rightBtn.down = function (x, y, obj) {
rightPressed = true;
};
rightBtn.up = function (x, y, obj) {
rightPressed = false;
};
// Touch handlers for up button
upBtn.down = function (x, y, obj) {
upPressed = true;
jumpPressed = true;
};
upBtn.up = function (x, y, obj) {
upPressed = false;
jumpPressed = false;
};
// Touch handlers for down button
downBtn.down = function (x, y, obj) {
downPressed = true;
};
downBtn.up = function (x, y, obj) {
downPressed = false;
};
// Touch handlers for jump button
// Touch handlers for fire button
fireBtn.down = function (x, y, obj) {
firePressed = true;
};
fireBtn.up = function (x, y, obj) {
firePressed = false;
};
var player;
var platforms = [];
var enemies = [];
var freezeOrbs = [];
var iceBlocks = [];
var powerups = [];
var stage = 1;
var stageCleared = false;
var stageTimer = 0;
var dragNode = null;
var moveStartX = 0;
var moveDir = 0;
var scoreTxt;
// Add lives
var lives = 1;
var livesTxt = new Text2('Lives: ' + lives, {
size: 70,
fill: 0xF6F1C7
});
livesTxt.anchor.set(0, 0);
LK.gui.top.addChild(livesTxt);
// Place lives at top left, but not in the 100x100 reserved area
livesTxt.x = 120;
livesTxt.y = 20;
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: 0xF6F1C7
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Stage display
var stageTxt = new Text2('Stage 1', {
size: 70,
fill: 0xB8E6FF
});
stageTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(stageTxt);
stageTxt.y = 120;
// Helper: spawn platforms
function spawnPlatforms() {
// Clear old
for (var i = 0; i < platforms.length; i++) platforms[i].destroy();
platforms = [];
// Floor
var floor = new Platform(1024, 2732 - 40, 2048);
game.addChild(floor);
platforms.push(floor);
// Snow Bros style: 5-6 fixed rows, wide platforms, even spacing, classic arcade
var rows = 6;
var yStart = 2732 - 300;
var yStep = 320;
for (var i = 0; i < rows; i++) {
var y = yStart - i * yStep;
// Classic: alternate left/right gaps for each row
if (i % 2 === 0) {
// Full width platform
var plat = new Platform(1024, y, 1600);
game.addChild(plat);
platforms.push(plat);
} else {
// Two half platforms with a gap in the middle
var leftPlat = new Platform(512, y, 700);
var rightPlat = new Platform(1536, y, 700);
game.addChild(leftPlat);
game.addChild(rightPlat);
platforms.push(leftPlat);
platforms.push(rightPlat);
}
}
}
// Helper: spawn enemies
function spawnEnemies() {
for (var i = 0; i < enemies.length; i++) enemies[i].destroy();
enemies = [];
var ghostCount = 2 + Math.floor(stage / 2);
var batCount = 3 + Math.floor(stage / 2); // Increased number of bats for more slow bats
for (var i = 0; i < ghostCount; i++) {
var px = 200 + Math.random() * (2048 - 400);
var py = 400 + Math.random() * 1200;
var g = new Ghost(px, py);
game.addChild(g);
enemies.push(g);
}
for (var i = 0; i < batCount; i++) {
var px = 200 + Math.random() * (2048 - 400);
var py = 300 + Math.random() * 1000;
var b = new Bat(px, py);
game.addChild(b);
enemies.push(b);
}
}
// Helper: spawn powerups
function spawnPowerups() {
for (var i = 0; i < powerups.length; i++) powerups[i].destroy();
powerups = [];
// Always one moon per stage
var moon = new MoonPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(moon);
powerups.push(moon);
// 50% chance for shield
if (Math.random() < 0.5) {
var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(shield);
powerups.push(shield);
}
// 50% chance for speed
if (Math.random() < 0.5) {
var speed = new SpeedPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(speed);
powerups.push(speed);
}
// 40% chance for lifepotion
if (Math.random() < 0.4) {
var lifepotion = new LifepotionPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(lifepotion);
powerups.push(lifepotion);
}
}
// Start new stage
function startStage() {
stageCleared = false;
stageTimer = 0;
stageTxt.setText('Stage ' + stage);
LK.setScore(0);
scoreTxt.setText('0');
lives = 7;
livesTxt.setText('Lives: ' + lives);
spawnPlatforms();
spawnEnemies();
spawnPowerups();
// Place player
if (player) player.destroy();
player = new Evanasense();
player.x = 1024;
player.y = 2732 - 200;
game.addChild(player);
}
// Begin first stage
startStage();
// Timer to spawn a random shield every 30 seconds
if (typeof shieldTimerId === "undefined") {
var shieldTimerId = LK.setInterval(function () {
// Spawn a random shield at a random position
var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(shield);
powerups.push(shield);
}, 30000); // 30,000 ms = 30 seconds
}
// Timer to spawn a speed powerup every 40 seconds, only one at a time
if (typeof speedPowerTimerId === "undefined") {
var speedPowerTimerId = LK.setInterval(function () {
// Only spawn if there is no speed powerup currently on the field
var hasSpeed = false;
for (var i = 0; i < powerups.length; i++) {
if (powerups[i].type === 'speed') {
hasSpeed = true;
break;
}
}
if (!hasSpeed) {
var speed = new SpeedPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(speed);
powerups.push(speed);
}
}, 40000); // 40,000 ms = 40 seconds
}
// Timer to spawn a broom every 30 seconds
if (typeof broomTimerId === "undefined") {
var broomTimerId = LK.setInterval(function () {
// Spawn a broom powerup at a random position
var broom = new BroomPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(broom);
powerups.push(broom);
}, 30000); // 30,000 ms = 30 seconds
}
// Timer to send 10 Yu powerups, one every 3 seconds
if (typeof yuSendCount === "undefined") {
var yuSendCount = 0;
var yuSendTimerId = LK.setInterval(function () {
if (yuSendCount < 10) {
var yu = new Container();
var yuAsset = yu.attachAsset('Yu', {
anchorX: 0.5,
anchorY: 0.5
});
yu.x = 200 + Math.random() * (2048 - 400);
yu.y = 400 + Math.random() * 1200;
yu.type = 'yu';
game.addChild(yu);
powerups.push(yu);
yuSendCount++;
}
if (yuSendCount >= 10) {
LK.clearInterval(yuSendTimerId);
}
}, 3000); // 3,000 ms = 3 seconds
}
// Main update loop
game.update = function () {
// (Removed shield spawn every 25 points logic)
// --- Shield spawn every 25 points, only once per threshold ---
if (typeof lastShieldScore === "undefined") {
var lastShieldScore = 0;
}
var currentScore = LK.getScore();
if (currentScore > 0 && currentScore % 25 === 0 && lastShieldScore !== currentScore) {
// Only spawn one shield per threshold
var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(shield);
powerups.push(shield);
lastShieldScore = currentScore;
}
if (currentScore % 25 !== 0) {
// Reset so next threshold can trigger
lastShieldScore = 0;
}
// Update player
if (player) player.update();
// Track ice orb hits for bat freeze mechanic
if (typeof batFreezeHitCount === "undefined") {
var batFreezeHitCount = 0;
var batFreezeActive = false;
var batFreezeTimer = 0;
}
// Update freeze orbs
for (var i = freezeOrbs.length - 1; i >= 0; i--) {
var orb = freezeOrbs[i];
orb.update();
// Collide with enemies
for (var j = 0; j < enemies.length; j++) {
var e = enemies[j];
if (!e.frozen && !e.trapped && orb.intersects(e)) {
e.freeze();
// If enemy is a Bat, count the hit
if (e instanceof Bat) {
batFreezeHitCount++;
// When 3 hits, freeze all bats for 60 seconds (3600 frames)
if (batFreezeHitCount >= 3 && !batFreezeActive) {
batFreezeActive = true;
batFreezeTimer = 3600;
for (var k = 0; k < enemies.length; k++) {
if (enemies[k] instanceof Bat) {
enemies[k].frozen = true;
enemies[k].frozenTimer = 3600;
if (enemies[k].children && enemies[k].children.length > 0) {
enemies[k].children[0].tint = 0x7fdfff;
}
}
}
}
}
orb.destroy();
freezeOrbs.splice(i, 1);
break;
}
}
}
// Bat freeze global timer
if (batFreezeActive) {
batFreezeTimer--;
if (batFreezeTimer <= 0) {
batFreezeActive = false;
batFreezeHitCount = 0;
// Unfreeze all bats
for (var k = 0; k < enemies.length; k++) {
if (enemies[k] instanceof Bat) {
enemies[k].frozen = false;
enemies[k].frozenTimer = 0;
if (enemies[k].children && enemies[k].children.length > 0) {
enemies[k].children[0].tint = 0x2a2a2a;
}
}
}
}
}
// Update ice blocks
for (var i = iceBlocks.length - 1; i >= 0; i--) {
var block = iceBlocks[i];
block.update();
// Collide with enemies
for (var j = 0; j < enemies.length; j++) {
var e = enemies[j];
if (!e.trapped && block.intersects(e)) {
e.trap();
block.destroy();
iceBlocks.splice(i, 1);
break;
}
}
}
// Update enemies
if (typeof globalEnemyPauseTimer === "undefined") {
var globalEnemyPauseTimer = 0;
}
if (globalEnemyPauseTimer > 0) {
globalEnemyPauseTimer--;
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
// Only update if enemy is frozen/trapped (so shatter still works), but skip normal update
if (e.frozen || e.trapped) {
e.update();
}
// Keep pausedBySpeed flag set
e.pausedBySpeed = true;
// If frozen or trapped, can be shattered by touching again
if ((e.frozen || e.trapped) && player && player.intersects(e)) {
e.shatter();
}
// If not frozen/trapped, collision with player
if (!e.frozen && !e.trapped && player && player.intersects(e)) {
if (player.shielded) {
player.loseShield();
LK.getSound('hit').play();
LK.effects.flashObject(player, 0x8fffd6, 400);
} else {
lives--;
livesTxt.setText('Lives: ' + lives);
LK.effects.flashScreen(0x7e4a9c, 900);
if (lives <= 0) {
LK.showGameOver();
return;
} else {
// Respawn player at start position
player.x = 1024;
player.y = 2732 - 200;
player.vx = 0;
player.vy = 0;
player.loseShield();
}
}
}
}
// When timer ends, unpause all enemies
if (globalEnemyPauseTimer === 0) {
for (var i = 0; i < enemies.length; i++) {
enemies[i].pausedBySpeed = false;
}
}
} else {
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// If frozen or trapped, can be shattered by touching again
if ((e.frozen || e.trapped) && player && player.intersects(e)) {
e.shatter();
}
// If not frozen/trapped, collision with player
if (!e.frozen && !e.trapped && player && player.intersects(e)) {
if (player.shielded) {
player.loseShield();
LK.getSound('hit').play();
LK.effects.flashObject(player, 0x8fffd6, 400);
} else {
lives--;
livesTxt.setText('Lives: ' + lives);
LK.effects.flashScreen(0x7e4a9c, 900);
if (lives <= 0) {
LK.showGameOver();
return;
} else {
// Respawn player at start position
player.x = 1024;
player.y = 2732 - 200;
player.vx = 0;
player.vy = 0;
player.loseShield();
}
}
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
if (player && player.intersects(p)) {
if (typeof moonCollectCount === "undefined") {
var moonCollectCount = 0;
}
if (p.type === 'moon') {
moonCollectCount++;
player.activateFullMoon();
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
// Spawn a new moon at a random position
var moon = new MoonPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(moon);
powerups.push(moon);
// If 5 moons collected, spawn a random shield and reset counter
if (typeof lastMoonShieldGiven === "undefined") {
var lastMoonShieldGiven = 0;
}
if (moonCollectCount >= 5) {
moonCollectCount = 0;
// Only give one shield per 5 moons
if (lastMoonShieldGiven !== LK.getScore()) {
var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(shield);
powerups.push(shield);
lastMoonShieldGiven = LK.getScore();
}
}
// If 100 moons collected, spawn a shield (only once per 100 moons)
if (typeof lastHundredMoonShieldGiven === "undefined") {
var lastHundredMoonShieldGiven = 0;
}
if (moonCollectCountTotal === undefined) {
var moonCollectCountTotal = 0;
}
moonCollectCountTotal++;
if (moonCollectCountTotal > 0 && moonCollectCountTotal % 100 === 0 && lastHundredMoonShieldGiven !== moonCollectCountTotal) {
var shield = new ShieldPower(200 + Math.random() * (2048 - 400), 400 + Math.random() * 1200);
game.addChild(shield);
powerups.push(shield);
lastHundredMoonShieldGiven = moonCollectCountTotal;
}
} else if (p.type === 'shield') {
player.gainShield();
// Send ice orbs in all directions
var orbCount = 12;
for (var d = 0; d < orbCount; d++) {
var angle = 2 * Math.PI * d / orbCount;
var dirX = Math.cos(angle);
var orb = new FreezeOrb(player.x, player.y - 60, dirX);
// Give each orb a custom vx/vy for radial spread
orb.vx = 24 * Math.cos(angle);
orb.vy = 24 * Math.sin(angle);
// Override update to move in both x and y
(function (orb) {
var baseUpdate = orb.update;
orb.update = function () {
orb.x += orb.vx;
orb.y += orb.vy;
orb.lifetime--;
// Wrap horizontally
if (orb.x < 0) orb.x = 2048;
if (orb.x > 2048) orb.x = 0;
// Remove if out of bounds vertically
if (orb.y < 0 || orb.y > 2732 || orb.lifetime <= 0) {
orb.destroy();
var idx = freezeOrbs.indexOf(orb);
if (idx >= 0) freezeOrbs.splice(idx, 1);
return;
}
};
})(orb);
game.addChild(orb);
freezeOrbs.push(orb);
}
} else if (p.type === 'speed') {
player.gainSpeed();
player.speedBoost = 240; // Speed lasts 4 seconds (60fps*4)
// Only freeze all enemies for 10 seconds if not already frozen by speed
if (typeof globalEnemyPauseTimer === "undefined") {
var globalEnemyPauseTimer = 0;
}
if (globalEnemyPauseTimer <= 0) {
globalEnemyPauseTimer = 600; // 10 seconds at 60fps
for (var ep = 0; ep < enemies.length; ep++) {
enemies[ep].pausedBySpeed = true;
}
}
} else if (p.type === 'lifepotion') {
lives++;
livesTxt.setText('Lives: ' + lives);
LK.effects.flashObject(player, 0x8fffd6, 400);
} else if (p.type === 'broom') {
// Witch can now fly!
player.canFly = true;
player.flyTimer = 600; // 10 seconds of flying (adjust as needed)
LK.effects.flashObject(player, 0xb8e6ff, 600);
} else if (p.type === 'yu') {
// Cancel speed power when witch takes the yu
player.speedBoost = 0;
if (typeof globalEnemyPauseTimer !== "undefined") {
globalEnemyPauseTimer = 0;
for (var ep = 0; ep < enemies.length; ep++) {
enemies[ep].pausedBySpeed = false;
}
}
}
LK.getSound('powerup').play();
p.destroy();
powerups.splice(i, 1);
}
}
// Full moon: allow trap spell by tap with two fingers (simulate by double tap)
if (player && player.fullMoon && LK.ticks % 60 === 0) {
// For MVP, allow trap spell every second in full moon
player.castTrap();
}
// Stage clear
if (!stageCleared && enemies.length === 0) {
stageCleared = true;
stageTimer = 90;
LK.effects.flashScreen(0xb8e6ff, 600);
}
if (stageCleared) {
stageTimer--;
if (stageTimer <= 0) {
stage++;
if (stage % 5 === 0) {
// Boss stage MVP: just spawn more enemies
stageTxt.setText('Boss Stage!');
for (var i = 0; i < 3; i++) {
var px = 200 + Math.random() * (2048 - 400);
var py = 400 + Math.random() * 1200;
var g = new Ghost(px, py);
game.addChild(g);
enemies.push(g);
}
for (var i = 0; i < 2; i++) {
var px = 200 + Math.random() * (2048 - 400);
var py = 300 + Math.random() * 1000;
var b = new Bat(px, py);
game.addChild(b);
enemies.push(b);
}
stageCleared = false;
} else {
startStage();
}
}
}
};
// Play music
LK.playMusic('gothic_theme', {
fade: {
start: 0,
end: 1,
duration: 1200
}
}); ===================================================================
--- original.js
+++ change.js
@@ -545,10 +545,10 @@
/****
* Game Code
****/
-// Game state
// Add background image
+// Game state
var bg = LK.getAsset('bg', {
anchorX: 0,
anchorY: 0,
width: 2048,
@@ -836,8 +836,30 @@
game.addChild(broom);
powerups.push(broom);
}, 30000); // 30,000 ms = 30 seconds
}
+// Timer to send 10 Yu powerups, one every 3 seconds
+if (typeof yuSendCount === "undefined") {
+ var yuSendCount = 0;
+ var yuSendTimerId = LK.setInterval(function () {
+ if (yuSendCount < 10) {
+ var yu = new Container();
+ var yuAsset = yu.attachAsset('Yu', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ yu.x = 200 + Math.random() * (2048 - 400);
+ yu.y = 400 + Math.random() * 1200;
+ yu.type = 'yu';
+ game.addChild(yu);
+ powerups.push(yu);
+ yuSendCount++;
+ }
+ if (yuSendCount >= 10) {
+ LK.clearInterval(yuSendTimerId);
+ }
+ }, 3000); // 3,000 ms = 3 seconds
+}
// Main update loop
game.update = function () {
// (Removed shield spawn every 25 points logic)
// --- Shield spawn every 25 points, only once per threshold ---
Ghost. In-Game asset. 2d. High contrast. No shadows
One life potion. In-Game asset. 2d. High contrast. No shadows
Change
Witch boiler. In-Game asset. 2d. High contrast. No shadows
Diffrent colour
Broom. In-Game asset. 2d. High contrast. No shadows
Snake. In-Game asset. 2d. High contrast. No shadows
Add legs
Snowball. In-Game asset. 2d. High contrast. No shadows
Bat closed wings
Behind
Flying boss. In-Game asset. 2d. High contrast. No shadows
Fireball. In-Game asset. 2d. High contrast. No shadows
Moon. In-Game asset. 2d. High contrast. No shadows
Dark forrest. In-Game asset. 2d. High contrast. No shadows
Ice block. In-Game asset. 2d. High contrast. No shadows
Ice wall. In-Game asset. 2d. High contrast. No shadows
Portal. In-Game asset. 2d. High contrast. No shadows