Code edit (3 edits merged)
Please save this source code
User prompt
create a new, fullwidth, 10 height shapebox at the lightlevel
User prompt
create a fullwidth, 10 height shapebox at the lightlevel
Code edit (11 edits merged)
Please save this source code
User prompt
add a shapeBox after the lightManager. The shape should be full width, have a height of LIGHT_LEVEL and tinted black
Code edit (1 edits merged)
Please save this source code
User prompt
attach a iconLight asset at the top of the screen, with an orange tint
Code edit (1 edits merged)
Please save this source code
User prompt
add a variance of LIGHT_GROW_VARIANCE to the LIGHT_GROW_SPEED
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'seetings is not defined' in or related to this line: 'settings.xs = (seetings.xs || 0) + 1;' Line Number: 823
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: blockClass is not a constructor' in or related to this line: 'var newBlock = self.parent.addChild(new blockClass({' Line Number: 637
Code edit (1 edits merged)
Please save this source code
User prompt
in the randomizeBlockClass function, the classes array should be an array of objects, with blockClass:
Code edit (6 edits merged)
Please save this source code
User prompt
remove the unused score variable
User prompt
use LK.getscore and LK.setscore instead of using the score variable
User prompt
Create a lightSources = 0 global variable. Whenever a block becomes lit, increment the value. In the block's onDestroy function, decrement lightSources if the block is lit and call game over with the message "Your light is extinguished" if lightSources is zero
Code edit (1 edits merged)
Please save this source code
User prompt
At the same position as the borderGear asset, create a borderLevel asset with a 45 degree rotation
Code edit (3 edits merged)
Please save this source code
User prompt
the borderGear should begin with a random rotation
Code edit (1 edits merged)
Please save this source code
User prompt
move all borderGear class functionality into the border class and delete the borderGear class
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BlockManager = Container.expand(function () { var self = Container.call(this); var blockRows = []; var index = 0; for (var i = 0; i < ROW_COUNT; i++) { addRow({ x: game.width / 2, y: LAVA_LINE - i * (BLOCK_SIZE * BLOCK_SCALE + BLOCK_MARGIN), index: index++ }); } blockRows[0].blocks[Math.floor(ROW_SPAN / 2)].onLit(true); self.update = function () { if (blockRows[0].y > game.height) { popRow(); } }; function addRow(settings) { var prevRow = blockRows[blockRows.length - 1]; var newRow = self.addChild(new BlockRow(settings)); blockRows.push(newRow); if (prevRow) { newRow.setDown(prevRow); prevRow.setUp(newRow); } } function popRow() { blockRows.shift().callDestroy(); blockRows[0].blocks.forEach(function (block) { if (block) { block.downBlock = undefined; } }); addRow({ x: game.width / 2, y: blockRows[blockRows.length - 1].y - BLOCK_SIZE * BLOCK_SCALE - BLOCK_MARGIN, index: index++, disabled: true }); adjustRowSpeed(); } return self; }); var ConfigContainer = Container.expand(function (config) { var self = Container.call(this); config = config || {}; self.destroyed = false; self.tags = {}; self.x = config.x || 0; self.y = config.y || 0; self.rotation = config.rotation || 0; self.alpha = config.alpha !== undefined ? config.alpha : 1.0; if (config.scale !== undefined || config.scaleX !== undefined || config.scaleY !== undefined) { var scaleX = config.scaleX !== undefined ? config.scaleX : config.scale !== undefined ? config.scale : 1; var scaleY = config.scaleY !== undefined ? config.scaleY : config.scale !== undefined ? config.scale : 1; self.scale.set(scaleX, scaleY); } self.callDestroy = function () { if (!self.destroyed) { self.destroyed = true; self.onDestroy(); self.destroy(); } }; self.onDestroy = function () {}; return self; }); var PointText = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var text = self.addChild(new Text2("+1", { fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4, size: 120 })); text.anchor = { x: 0.5, y: 0.5 }; // NOTE: Cannot be set in config tween(self, { y: self.y - 50 }, { duration: 2000 }); LK.setTimeout(function () { tween(self, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { self.callDestroy(); } }); }, 1000); return self; }); var Light = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var lightShape = self.attachAsset('shapeEllipse', { y: -LIGHT_OFFSET, width: BLOCK_SIZE - 2 * LIGHT_OFFSET, height: BLOCK_SIZE - 2 * LIGHT_OFFSET, anchorX: 0.5, anchorY: 1, scaleX: 0, scaleY: 0 }); tween(lightShape, { scaleX: 1, scaleY: 1 }, { duration: LIGHT_GROW_SPEED, onFinish: function onFinish() { if (self.parent) { config.callback(); } } }); return self; }); var LavaSlice = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); self.attachAsset('lava' + config.index, { anchorX: 0.5, anchorY: 0, width: LAVA_SLICE_WIDTH, tint: 0xFFA500 }); self.attachAsset('shapeBox', { width: LAVA_SLICE_WIDTH, height: 10, anchorX: 0.5, anchorY: 0, tint: 0xFF4D00 }); self.addChild(new Glow({ anchorX: 0.5, anchorY: 0.75, height: 20, rangeY: 150, width: 3 * LAVA_SLICE_WIDTH, alpha: 0.35, tint: 0xFF4D00 })); self.update = function () { self.y = Math.sin(LK.ticks * LAVA_BOB_PERIOD + config.index * LAVA_BOB_OFFSET) * LAVA_BOB_HEIGHT; }; return self; }); var Lava = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var position = Math.round((-0.5 - LAVA_SLICE_COUNT / 2) * LAVA_SLICE_WIDTH); for (var i = 1; i <= LAVA_SLICE_COUNT; i++) { var lavaSlice = self.addChild(new LavaSlice({ x: position += LAVA_SLICE_WIDTH, index: i })); } return self; }); var Glow = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var layers = Math.max(2, config.layers || 10); var layerAlpha = 1 / layers; var widthStep = (config.rangeX || 0) * layerAlpha; var heightStep = (config.rangeY || 0) * layerAlpha; for (var i = 0; i < layers; i++) { self.attachAsset(config.asset || 'shapeBox', { width: config.width + widthStep * i, height: config.height + heightStep * i, anchorX: config.anchorX, anchorY: config.anchorY, tint: config.tint, alpha: i === 0 && config.solid ? 1 : layerAlpha }); } return self; }); var Border = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var radius = 50; var borderGear = self.attachAsset('borderGear', { width: 2 * radius, height: 2 * radius, anchorX: 0.5, anchorY: 0.5, y: LIGHT_LEVEL }); self.update = function () { borderGear.rotation += rowSpeed / radius; }; var totalHeight = 0; var borderAssets = ['border1', 'border2']; while (totalHeight < game.height) { var randomAsset = borderAssets[Math.floor(Math.random() * borderAssets.length)]; var borderSegment = self.attachAsset(randomAsset, { anchorX: 0.5, anchorY: 0, y: totalHeight }); totalHeight += borderSegment.height; } return self; }); var BlockRow = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); var blockClasses = generateBlockClasses(config.index); self.disabled = !!config.disabled; self.blocks = []; for (var i = 0; i < ROW_SPAN; i++) { var blockClass = blockClasses[i]; self.blocks[i] = self.addChild(new blockClass({ x: (0.5 + i - ROW_SPAN / 2) * (BLOCK_SIZE * BLOCK_SCALE + BLOCK_MARGIN), scale: BLOCK_SCALE, disabled: self.disabled, index: i, row: self })); } for (var i = 0; i < ROW_SPAN; i++) { var block = self.blocks[i]; if (i > 0) { block.leftBlock = self.blocks[i - 1]; } if (i < ROW_SPAN - 1) { block.rightBlock = self.blocks[i + 1]; } } self.update = function () { self.y += rowSpeed; if (self.disabled && self.y > BLOCK_SIZE) { self.disabled = false; self.blocks.forEach(function (block) { block.disabled = false; }); self.blocks.forEach(function (block) { if (!block.isRotating) { block.onSettle(); } }); } }; self.setUp = function (upRow) { for (var i = 0; i < ROW_SPAN; i++) { var selfBlock = self.blocks[i]; var upBlock = upRow.blocks[i]; upBlock.downBlock = selfBlock; selfBlock.upBlock = upBlock; } }; self.setDown = function (downRow) { for (var i = 0; i < ROW_SPAN; i++) { var selfBlock = self.blocks[i]; var downBlock = downRow.blocks[i]; downBlock.upBlock = selfBlock; selfBlock.downBlock = downBlock; } }; self.onDestroy = function () { self.blocks.forEach(function (block) { block.callDestroy(); }); }; return self; }); var Block = ConfigContainer.expand(function (config) { var self = ConfigContainer.call(this, config); self.isRotating = false; self.disabled = config.disabled; self.row = config.row; self.index = config.index; self.orientation = config.orientation !== undefined ? config.orientation : Math.floor(4 * Math.random()); self.upPath = false; self.rightPath = false; self.downPath = false; self.leftPath = false; self.upBlock; self.rightBlock; self.downBlock; self.leftBlock; self.attachAsset('shapeBox', { width: BLOCK_SIZE, height: BLOCK_SIZE, anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.lightContainer = lightManager.addChild(new ConfigContainer({ scale: BLOCK_SCALE })); self.blockContainer = self.addChild(new ConfigContainer({ rotation: self.orientation * Math.PI / 2 })); self.rotate = function () { if (!self.lit && !self.isRotating) { self.isRotating = true; self.lightContainer.removeChildren(); tween(self.blockContainer, { rotation: self.blockContainer.rotation + Math.PI / 2 }, { duration: BLOCK_ROTATE_SPEED, onFinish: function onFinish() { if (!self.destroyed) { self.isRotating = false; self.orientation = (self.orientation + 1) % 4; self.onSettle(); } } }); } }; self.update = function () { if (self.parent && !self.destroyed) { self.lightContainer.x = self.x + self.parent.x; self.lightContainer.y = self.y + self.parent.y; } }; self.down = function () { self.rotate(); tween(self.scale, { x: 0.9 * BLOCK_SCALE, y: 0.9 * BLOCK_SCALE }, { duration: BLOCK_ROTATE_SPEED / 2, onFinish: function onFinish() { tween(self.scale, { x: BLOCK_SCALE, y: BLOCK_SCALE }, { duration: BLOCK_ROTATE_SPEED / 2 }); } }); }; self.onLit = function (pointless) { if (!self.lit && !self.destroyed && (self.upPath || self.downPath || self.leftPath || self.rightPath)) { self.lit = true; self.lightContainer.removeChildren(); self.lightContainer.attachAsset('shapeEllipse', { width: BLOCK_SIZE - 2 * LIGHT_OFFSET, height: BLOCK_SIZE - 2 * LIGHT_OFFSET, anchorX: 0.5, anchorY: 0.5 }); if (self.upPath && (!self.upBlock || !self.upBlock.lit || !self.upBlock.downPath)) { makeGlow(0, -BLOCK_SIZE / 2 - BLOCK_MARGIN / 4); } if (self.rightPath && (!self.rightBlock || !self.rightBlock.lit || !self.rightBlock.leftPath)) { makeGlow(BLOCK_SIZE / 2 + BLOCK_MARGIN / 4, 0); } if (self.downPath && (!self.downBlock || !self.downBlock.lit || !self.downBlock.upPath)) { makeGlow(0, BLOCK_SIZE / 2 + BLOCK_MARGIN / 4); } if (self.leftPath && (!self.leftBlock || !self.leftBlock.lit || !self.leftBlock.rightPath)) { makeGlow(-BLOCK_SIZE / 2 - BLOCK_MARGIN / 4, 0); } if (!pointless) { score += 1; scoreText.setText(score); game.addChild(new PointText({ x: self.x + self.parent.x, y: self.y + self.parent.y })); } self.onSettle(); } }; self.onSettle = function () { self.updatePaths(); if (!self.disabled) { var litRotationFactor = self.lit ? 0 : 1; var litPositionFactor = self.lit ? 1 : -1; [{ direction: 'up', rotation: 0, y: 1 }, { direction: 'right', rotation: 0.5, x: -1 }, { direction: 'down', rotation: 1, y: -1 }, { direction: 'left', rotation: 1.5, x: 1 }].forEach(function (item) { if (self[item.direction + 'Path']) { var block = self[item.direction + 'Block']; if (block && !block.disabled && block.lit !== self.lit && block[COMPLIMENTS[item.direction] + 'Path']) { (self.lit ? block : self).lightContainer.addChild(new Light({ x: (item.x || 0) * litPositionFactor * BLOCK_HALFSIZE, y: (item.y || 0) * litPositionFactor * BLOCK_HALFSIZE, rotation: Math.PI * (item.rotation + litRotationFactor), callback: self.lit ? block.onLit : self.onLit })); } } }); } }; self.updatePaths = function () {}; function makeGlow(x, y) { var glow = self.lightContainer.addChild(new Glow({ x: x, y: y, width: LIGHT_SPILL_SIZE, height: LIGHT_SPILL_SIZE, anchorX: 0.5, anchorY: 0.5, rangeX: 20, rangeY: 20, layers: 4, solid: true, tint: 0xFFFFFF, alpha: 0 })); tween(glow, { alpha: 1 }, { duration: 250 }); } self.onDestroy = function () { if (self.lightContainer) { self.lightContainer.destroy(); } }; return self; }); var BlockX = Block.expand(function (config) { var self = Block.call(this, config); var shiftY = 2; self.upPath = true; self.rightPath = true; self.downPath = true; self.leftPath = true; self.blockContainer.attachAsset('blockX1', { x: -BLOCK_HALFSIZE, y: -BLOCK_HALFSIZE + shiftY, anchorX: 0, anchorY: 0 }); self.blockContainer.attachAsset('blockX2', { x: BLOCK_HALFSIZE, y: -BLOCK_HALFSIZE + shiftY, anchorX: 1, anchorY: 0 }); self.blockContainer.attachAsset('blockX3', { x: -BLOCK_HALFSIZE, y: BLOCK_HALFSIZE + shiftY, anchorX: 0, anchorY: 1 }); self.blockContainer.attachAsset('blockX4', { x: BLOCK_HALFSIZE, y: BLOCK_HALFSIZE + shiftY, anchorX: 1, anchorY: 1 }); return self; }); var BlockT = Block.expand(function (config) { var self = Block.call(this, config); self.blockContainer.attachAsset('blockT1', { x: -BLOCK_HALFSIZE, y: -BLOCK_HALFSIZE, anchorX: 0, anchorY: 0 }); self.blockContainer.attachAsset('blockT2', { x: BLOCK_HALFSIZE, y: -BLOCK_HALFSIZE, anchorX: 1, anchorY: 0 }); self.blockContainer.attachAsset('blockT3', { y: BLOCK_HALFSIZE, anchorX: 0.5, anchorY: 1 }); self.updatePaths = function () { self.downPath = self.orientation !== 0; self.leftPath = self.orientation !== 1; self.upPath = self.orientation !== 2; self.rightPath = self.orientation !== 3; }; self.updatePaths(); return self; }); var BlockLine = Block.expand(function (config) { var self = Block.call(this, config); self.blockContainer.attachAsset('blockLine1', { x: -BLOCK_HALFSIZE, anchorX: 0, anchorY: 0.5, height: BLOCK_SIZE }); self.blockContainer.attachAsset('blockLine2', { x: BLOCK_HALFSIZE, anchorX: 1, anchorY: 0.5, height: BLOCK_SIZE }); self.updatePaths = function () { var vertical = !(self.orientation % 2); self.upPath = vertical; self.downPath = vertical; self.leftPath = !vertical; self.rightPath = !vertical; }; self.updatePaths(); return self; }); var BlockL = Block.expand(function (config) { var self = Block.call(this, config); self.blockContainer.attachAsset('blockL1', { anchorX: 0.5, anchorY: 0.5, height: BLOCK_SIZE }); self.blockContainer.attachAsset('blockL2', { x: -BLOCK_HALFSIZE, y: BLOCK_HALFSIZE, anchorX: 0, anchorY: 1 }); self.updatePaths = function () { self.leftPath = self.orientation === 0 || self.orientation === 1; self.upPath = self.orientation === 1 || self.orientation === 2; self.rightPath = self.orientation === 2 || self.orientation === 3; self.downPath = self.orientation === 3 || self.orientation === 0; }; self.updatePaths(); return self; }); var BlockBlank = Block.expand(function (config) { var self = Block.call(this, config); var crackAsset; var crackLevel = 0; var blockBlankAssets = ['blockBlank1', 'blockBlank2', 'blockBlank3']; var randomAsset = blockBlankAssets[Math.floor(Math.random() * blockBlankAssets.length)]; self.blockContainer.attachAsset(randomAsset, { anchorX: 0.5, anchorY: 0.5, width: BLOCK_SIZE, height: BLOCK_SIZE }); self.rotate = function (force) { if (force || crackLevel > 0) { if (++crackLevel <= 4) { if (crackAsset) { crackAsset.destroy(); } crackAsset = self.blockContainer.attachAsset('crack' + crackLevel, { anchorX: 0.5, anchorY: 0.5, rotation: crackLevel === 1 ? Math.random() * Math.PI * 2 : 0 // Random rotation if crackLevel is 1 }); } else { var newBlockClass = randomizeBlockClass(); if (self.parent) { var newBlock = self.parent.addChild(new newBlockClass({ x: self.x, y: self.y, scale: BLOCK_SCALE, index: self.index, row: self.row })); self.row.blocks[self.index] = newBlock; // Update block references if (self.upBlock) { self.upBlock.downBlock = newBlock; newBlock.upBlock = self.upBlock; } if (self.downBlock) { self.downBlock.upBlock = newBlock; newBlock.downBlock = self.downBlock; } if (self.leftBlock) { self.leftBlock.rightBlock = newBlock; newBlock.leftBlock = self.leftBlock; } if (self.rightBlock) { self.rightBlock.leftBlock = newBlock; newBlock.rightBlock = self.rightBlock; } } self.callDestroy(); } } }; if (Math.random() < BLOCK_CRACK_CHANCE) { self.rotate(true); } return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ var LAVA_LINE = game.height - 200; var LAVA_SLICE_COUNT = 18; var LAVA_SLICE_WIDTH = 128; var LAVA_BOB_HEIGHT = 10; var LAVA_BOB_OFFSET = Math.PI / 5; var LAVA_BOB_PERIOD = Math.PI / 60; var BLOCK_SCALE = 2.5; var BLOCK_SIZE = 100; var BLOCK_MARGIN = 20; var BLOCK_HALFSIZE = BLOCK_SIZE * 0.5; var BLOCK_CRACK_CHANCE = 0.3; var BLOCK_ROTATE_SPEED = 100; var LIGHT_LEVEL = 500; var LIGHT_GROW_SPEED = 5000; var LIGHT_SPILL_SIZE = 35; var LIGHT_OFFSET = 5; var ROW_SPAN = 7; var ROW_COUNT = 11; var ROW_SPEED_BASE = 0.2; var ROW_SPEED_INCREASE = 0.02; var ROW_SPEED_INCREASE_MIN = 0.005; var ROW_SPEED_INCREASE_FACTOR = 0.95; var COMPLIMENTS = { up: 'down', right: 'left', down: 'up', left: 'right' }; var rowSpeed = ROW_SPEED_BASE; var score = 0; var rowSpeedIncrease = ROW_SPEED_INCREASE; var scoreText = new Text2('0', { size: 100, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 10 }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var lightManager = game.addChild(new Container()); var blockManager = game.addChild(new BlockManager()); var leftBorder = game.addChild(new Border({ x: 30 })); var rightBorder = game.addChild(new Border({ x: game.width - 30, scaleX: -1 })); var lava = game.addChild(new Lava({ x: game.width / 2, y: LAVA_LINE })); game.addChild(new Glow({ anchorX: 0.5, anchorY: 0, x: game.width / 2, y: 0, width: game.width, height: 200, rangeY: 200, tint: 0x000000, alpha: 2.0 })); function shuffle(array) { var currentIndex = array.length; while (currentIndex != 0) { var randomIndex = Math.floor(Math.random() * currentIndex); currentIndex--; var ref = [array[randomIndex], array[currentIndex]]; array[currentIndex] = ref[0]; array[randomIndex] = ref[1]; } return array; } function generateBlockClasses(index) { var settings = { index: index }; switch (index) { case 0: return [BlockBlank, BlockBlank, BlockBlank, BlockX, BlockBlank, BlockBlank, BlockBlank]; case 1: settings.blanks = ROW_SPAN; // Prevent additional blanks return [BlockBlank, BlockBlank, randomizeBlockClass(settings), BlockX, randomizeBlockClass(settings), BlockBlank, BlockBlank]; case 2: return [BlockBlank, randomizeBlockClass(settings), randomizeBlockClass(settings), BlockX, randomizeBlockClass(settings), randomizeBlockClass(settings), BlockBlank]; default: var blockClasses = []; for (var i = 0; i < ROW_SPAN; i++) { blockClasses[i] = randomizeBlockClass(settings); } return shuffle(blockClasses); } } function adjustRowSpeed() { rowSpeed += rowSpeedIncrease; rowSpeedIncrease = Math.max(ROW_SPEED_INCREASE_MIN, rowSpeedIncrease * ROW_SPEED_INCREASE_FACTOR); } function randomizeBlockClass(settings) { var classes = [BlockBlank, BlockT, BlockX, BlockLine, BlockL]; return classes[Math.floor(Math.random() * classes.length)]; }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BlockManager = Container.expand(function () {
var self = Container.call(this);
var blockRows = [];
var index = 0;
for (var i = 0; i < ROW_COUNT; i++) {
addRow({
x: game.width / 2,
y: LAVA_LINE - i * (BLOCK_SIZE * BLOCK_SCALE + BLOCK_MARGIN),
index: index++
});
}
blockRows[0].blocks[Math.floor(ROW_SPAN / 2)].onLit(true);
self.update = function () {
if (blockRows[0].y > game.height) {
popRow();
}
};
function addRow(settings) {
var prevRow = blockRows[blockRows.length - 1];
var newRow = self.addChild(new BlockRow(settings));
blockRows.push(newRow);
if (prevRow) {
newRow.setDown(prevRow);
prevRow.setUp(newRow);
}
}
function popRow() {
blockRows.shift().callDestroy();
blockRows[0].blocks.forEach(function (block) {
if (block) {
block.downBlock = undefined;
}
});
addRow({
x: game.width / 2,
y: blockRows[blockRows.length - 1].y - BLOCK_SIZE * BLOCK_SCALE - BLOCK_MARGIN,
index: index++,
disabled: true
});
adjustRowSpeed();
}
return self;
});
var ConfigContainer = Container.expand(function (config) {
var self = Container.call(this);
config = config || {};
self.destroyed = false;
self.tags = {};
self.x = config.x || 0;
self.y = config.y || 0;
self.rotation = config.rotation || 0;
self.alpha = config.alpha !== undefined ? config.alpha : 1.0;
if (config.scale !== undefined || config.scaleX !== undefined || config.scaleY !== undefined) {
var scaleX = config.scaleX !== undefined ? config.scaleX : config.scale !== undefined ? config.scale : 1;
var scaleY = config.scaleY !== undefined ? config.scaleY : config.scale !== undefined ? config.scale : 1;
self.scale.set(scaleX, scaleY);
}
self.callDestroy = function () {
if (!self.destroyed) {
self.destroyed = true;
self.onDestroy();
self.destroy();
}
};
self.onDestroy = function () {};
return self;
});
var PointText = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var text = self.addChild(new Text2("+1", {
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4,
size: 120
}));
text.anchor = {
x: 0.5,
y: 0.5
}; // NOTE: Cannot be set in config
tween(self, {
y: self.y - 50
}, {
duration: 2000
});
LK.setTimeout(function () {
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.callDestroy();
}
});
}, 1000);
return self;
});
var Light = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var lightShape = self.attachAsset('shapeEllipse', {
y: -LIGHT_OFFSET,
width: BLOCK_SIZE - 2 * LIGHT_OFFSET,
height: BLOCK_SIZE - 2 * LIGHT_OFFSET,
anchorX: 0.5,
anchorY: 1,
scaleX: 0,
scaleY: 0
});
tween(lightShape, {
scaleX: 1,
scaleY: 1
}, {
duration: LIGHT_GROW_SPEED,
onFinish: function onFinish() {
if (self.parent) {
config.callback();
}
}
});
return self;
});
var LavaSlice = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
self.attachAsset('lava' + config.index, {
anchorX: 0.5,
anchorY: 0,
width: LAVA_SLICE_WIDTH,
tint: 0xFFA500
});
self.attachAsset('shapeBox', {
width: LAVA_SLICE_WIDTH,
height: 10,
anchorX: 0.5,
anchorY: 0,
tint: 0xFF4D00
});
self.addChild(new Glow({
anchorX: 0.5,
anchorY: 0.75,
height: 20,
rangeY: 150,
width: 3 * LAVA_SLICE_WIDTH,
alpha: 0.35,
tint: 0xFF4D00
}));
self.update = function () {
self.y = Math.sin(LK.ticks * LAVA_BOB_PERIOD + config.index * LAVA_BOB_OFFSET) * LAVA_BOB_HEIGHT;
};
return self;
});
var Lava = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var position = Math.round((-0.5 - LAVA_SLICE_COUNT / 2) * LAVA_SLICE_WIDTH);
for (var i = 1; i <= LAVA_SLICE_COUNT; i++) {
var lavaSlice = self.addChild(new LavaSlice({
x: position += LAVA_SLICE_WIDTH,
index: i
}));
}
return self;
});
var Glow = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var layers = Math.max(2, config.layers || 10);
var layerAlpha = 1 / layers;
var widthStep = (config.rangeX || 0) * layerAlpha;
var heightStep = (config.rangeY || 0) * layerAlpha;
for (var i = 0; i < layers; i++) {
self.attachAsset(config.asset || 'shapeBox', {
width: config.width + widthStep * i,
height: config.height + heightStep * i,
anchorX: config.anchorX,
anchorY: config.anchorY,
tint: config.tint,
alpha: i === 0 && config.solid ? 1 : layerAlpha
});
}
return self;
});
var Border = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var radius = 50;
var borderGear = self.attachAsset('borderGear', {
width: 2 * radius,
height: 2 * radius,
anchorX: 0.5,
anchorY: 0.5,
y: LIGHT_LEVEL
});
self.update = function () {
borderGear.rotation += rowSpeed / radius;
};
var totalHeight = 0;
var borderAssets = ['border1', 'border2'];
while (totalHeight < game.height) {
var randomAsset = borderAssets[Math.floor(Math.random() * borderAssets.length)];
var borderSegment = self.attachAsset(randomAsset, {
anchorX: 0.5,
anchorY: 0,
y: totalHeight
});
totalHeight += borderSegment.height;
}
return self;
});
var BlockRow = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var blockClasses = generateBlockClasses(config.index);
self.disabled = !!config.disabled;
self.blocks = [];
for (var i = 0; i < ROW_SPAN; i++) {
var blockClass = blockClasses[i];
self.blocks[i] = self.addChild(new blockClass({
x: (0.5 + i - ROW_SPAN / 2) * (BLOCK_SIZE * BLOCK_SCALE + BLOCK_MARGIN),
scale: BLOCK_SCALE,
disabled: self.disabled,
index: i,
row: self
}));
}
for (var i = 0; i < ROW_SPAN; i++) {
var block = self.blocks[i];
if (i > 0) {
block.leftBlock = self.blocks[i - 1];
}
if (i < ROW_SPAN - 1) {
block.rightBlock = self.blocks[i + 1];
}
}
self.update = function () {
self.y += rowSpeed;
if (self.disabled && self.y > BLOCK_SIZE) {
self.disabled = false;
self.blocks.forEach(function (block) {
block.disabled = false;
});
self.blocks.forEach(function (block) {
if (!block.isRotating) {
block.onSettle();
}
});
}
};
self.setUp = function (upRow) {
for (var i = 0; i < ROW_SPAN; i++) {
var selfBlock = self.blocks[i];
var upBlock = upRow.blocks[i];
upBlock.downBlock = selfBlock;
selfBlock.upBlock = upBlock;
}
};
self.setDown = function (downRow) {
for (var i = 0; i < ROW_SPAN; i++) {
var selfBlock = self.blocks[i];
var downBlock = downRow.blocks[i];
downBlock.upBlock = selfBlock;
selfBlock.downBlock = downBlock;
}
};
self.onDestroy = function () {
self.blocks.forEach(function (block) {
block.callDestroy();
});
};
return self;
});
var Block = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
self.isRotating = false;
self.disabled = config.disabled;
self.row = config.row;
self.index = config.index;
self.orientation = config.orientation !== undefined ? config.orientation : Math.floor(4 * Math.random());
self.upPath = false;
self.rightPath = false;
self.downPath = false;
self.leftPath = false;
self.upBlock;
self.rightBlock;
self.downBlock;
self.leftBlock;
self.attachAsset('shapeBox', {
width: BLOCK_SIZE,
height: BLOCK_SIZE,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.lightContainer = lightManager.addChild(new ConfigContainer({
scale: BLOCK_SCALE
}));
self.blockContainer = self.addChild(new ConfigContainer({
rotation: self.orientation * Math.PI / 2
}));
self.rotate = function () {
if (!self.lit && !self.isRotating) {
self.isRotating = true;
self.lightContainer.removeChildren();
tween(self.blockContainer, {
rotation: self.blockContainer.rotation + Math.PI / 2
}, {
duration: BLOCK_ROTATE_SPEED,
onFinish: function onFinish() {
if (!self.destroyed) {
self.isRotating = false;
self.orientation = (self.orientation + 1) % 4;
self.onSettle();
}
}
});
}
};
self.update = function () {
if (self.parent && !self.destroyed) {
self.lightContainer.x = self.x + self.parent.x;
self.lightContainer.y = self.y + self.parent.y;
}
};
self.down = function () {
self.rotate();
tween(self.scale, {
x: 0.9 * BLOCK_SCALE,
y: 0.9 * BLOCK_SCALE
}, {
duration: BLOCK_ROTATE_SPEED / 2,
onFinish: function onFinish() {
tween(self.scale, {
x: BLOCK_SCALE,
y: BLOCK_SCALE
}, {
duration: BLOCK_ROTATE_SPEED / 2
});
}
});
};
self.onLit = function (pointless) {
if (!self.lit && !self.destroyed && (self.upPath || self.downPath || self.leftPath || self.rightPath)) {
self.lit = true;
self.lightContainer.removeChildren();
self.lightContainer.attachAsset('shapeEllipse', {
width: BLOCK_SIZE - 2 * LIGHT_OFFSET,
height: BLOCK_SIZE - 2 * LIGHT_OFFSET,
anchorX: 0.5,
anchorY: 0.5
});
if (self.upPath && (!self.upBlock || !self.upBlock.lit || !self.upBlock.downPath)) {
makeGlow(0, -BLOCK_SIZE / 2 - BLOCK_MARGIN / 4);
}
if (self.rightPath && (!self.rightBlock || !self.rightBlock.lit || !self.rightBlock.leftPath)) {
makeGlow(BLOCK_SIZE / 2 + BLOCK_MARGIN / 4, 0);
}
if (self.downPath && (!self.downBlock || !self.downBlock.lit || !self.downBlock.upPath)) {
makeGlow(0, BLOCK_SIZE / 2 + BLOCK_MARGIN / 4);
}
if (self.leftPath && (!self.leftBlock || !self.leftBlock.lit || !self.leftBlock.rightPath)) {
makeGlow(-BLOCK_SIZE / 2 - BLOCK_MARGIN / 4, 0);
}
if (!pointless) {
score += 1;
scoreText.setText(score);
game.addChild(new PointText({
x: self.x + self.parent.x,
y: self.y + self.parent.y
}));
}
self.onSettle();
}
};
self.onSettle = function () {
self.updatePaths();
if (!self.disabled) {
var litRotationFactor = self.lit ? 0 : 1;
var litPositionFactor = self.lit ? 1 : -1;
[{
direction: 'up',
rotation: 0,
y: 1
}, {
direction: 'right',
rotation: 0.5,
x: -1
}, {
direction: 'down',
rotation: 1,
y: -1
}, {
direction: 'left',
rotation: 1.5,
x: 1
}].forEach(function (item) {
if (self[item.direction + 'Path']) {
var block = self[item.direction + 'Block'];
if (block && !block.disabled && block.lit !== self.lit && block[COMPLIMENTS[item.direction] + 'Path']) {
(self.lit ? block : self).lightContainer.addChild(new Light({
x: (item.x || 0) * litPositionFactor * BLOCK_HALFSIZE,
y: (item.y || 0) * litPositionFactor * BLOCK_HALFSIZE,
rotation: Math.PI * (item.rotation + litRotationFactor),
callback: self.lit ? block.onLit : self.onLit
}));
}
}
});
}
};
self.updatePaths = function () {};
function makeGlow(x, y) {
var glow = self.lightContainer.addChild(new Glow({
x: x,
y: y,
width: LIGHT_SPILL_SIZE,
height: LIGHT_SPILL_SIZE,
anchorX: 0.5,
anchorY: 0.5,
rangeX: 20,
rangeY: 20,
layers: 4,
solid: true,
tint: 0xFFFFFF,
alpha: 0
}));
tween(glow, {
alpha: 1
}, {
duration: 250
});
}
self.onDestroy = function () {
if (self.lightContainer) {
self.lightContainer.destroy();
}
};
return self;
});
var BlockX = Block.expand(function (config) {
var self = Block.call(this, config);
var shiftY = 2;
self.upPath = true;
self.rightPath = true;
self.downPath = true;
self.leftPath = true;
self.blockContainer.attachAsset('blockX1', {
x: -BLOCK_HALFSIZE,
y: -BLOCK_HALFSIZE + shiftY,
anchorX: 0,
anchorY: 0
});
self.blockContainer.attachAsset('blockX2', {
x: BLOCK_HALFSIZE,
y: -BLOCK_HALFSIZE + shiftY,
anchorX: 1,
anchorY: 0
});
self.blockContainer.attachAsset('blockX3', {
x: -BLOCK_HALFSIZE,
y: BLOCK_HALFSIZE + shiftY,
anchorX: 0,
anchorY: 1
});
self.blockContainer.attachAsset('blockX4', {
x: BLOCK_HALFSIZE,
y: BLOCK_HALFSIZE + shiftY,
anchorX: 1,
anchorY: 1
});
return self;
});
var BlockT = Block.expand(function (config) {
var self = Block.call(this, config);
self.blockContainer.attachAsset('blockT1', {
x: -BLOCK_HALFSIZE,
y: -BLOCK_HALFSIZE,
anchorX: 0,
anchorY: 0
});
self.blockContainer.attachAsset('blockT2', {
x: BLOCK_HALFSIZE,
y: -BLOCK_HALFSIZE,
anchorX: 1,
anchorY: 0
});
self.blockContainer.attachAsset('blockT3', {
y: BLOCK_HALFSIZE,
anchorX: 0.5,
anchorY: 1
});
self.updatePaths = function () {
self.downPath = self.orientation !== 0;
self.leftPath = self.orientation !== 1;
self.upPath = self.orientation !== 2;
self.rightPath = self.orientation !== 3;
};
self.updatePaths();
return self;
});
var BlockLine = Block.expand(function (config) {
var self = Block.call(this, config);
self.blockContainer.attachAsset('blockLine1', {
x: -BLOCK_HALFSIZE,
anchorX: 0,
anchorY: 0.5,
height: BLOCK_SIZE
});
self.blockContainer.attachAsset('blockLine2', {
x: BLOCK_HALFSIZE,
anchorX: 1,
anchorY: 0.5,
height: BLOCK_SIZE
});
self.updatePaths = function () {
var vertical = !(self.orientation % 2);
self.upPath = vertical;
self.downPath = vertical;
self.leftPath = !vertical;
self.rightPath = !vertical;
};
self.updatePaths();
return self;
});
var BlockL = Block.expand(function (config) {
var self = Block.call(this, config);
self.blockContainer.attachAsset('blockL1', {
anchorX: 0.5,
anchorY: 0.5,
height: BLOCK_SIZE
});
self.blockContainer.attachAsset('blockL2', {
x: -BLOCK_HALFSIZE,
y: BLOCK_HALFSIZE,
anchorX: 0,
anchorY: 1
});
self.updatePaths = function () {
self.leftPath = self.orientation === 0 || self.orientation === 1;
self.upPath = self.orientation === 1 || self.orientation === 2;
self.rightPath = self.orientation === 2 || self.orientation === 3;
self.downPath = self.orientation === 3 || self.orientation === 0;
};
self.updatePaths();
return self;
});
var BlockBlank = Block.expand(function (config) {
var self = Block.call(this, config);
var crackAsset;
var crackLevel = 0;
var blockBlankAssets = ['blockBlank1', 'blockBlank2', 'blockBlank3'];
var randomAsset = blockBlankAssets[Math.floor(Math.random() * blockBlankAssets.length)];
self.blockContainer.attachAsset(randomAsset, {
anchorX: 0.5,
anchorY: 0.5,
width: BLOCK_SIZE,
height: BLOCK_SIZE
});
self.rotate = function (force) {
if (force || crackLevel > 0) {
if (++crackLevel <= 4) {
if (crackAsset) {
crackAsset.destroy();
}
crackAsset = self.blockContainer.attachAsset('crack' + crackLevel, {
anchorX: 0.5,
anchorY: 0.5,
rotation: crackLevel === 1 ? Math.random() * Math.PI * 2 : 0 // Random rotation if crackLevel is 1
});
} else {
var newBlockClass = randomizeBlockClass();
if (self.parent) {
var newBlock = self.parent.addChild(new newBlockClass({
x: self.x,
y: self.y,
scale: BLOCK_SCALE,
index: self.index,
row: self.row
}));
self.row.blocks[self.index] = newBlock;
// Update block references
if (self.upBlock) {
self.upBlock.downBlock = newBlock;
newBlock.upBlock = self.upBlock;
}
if (self.downBlock) {
self.downBlock.upBlock = newBlock;
newBlock.downBlock = self.downBlock;
}
if (self.leftBlock) {
self.leftBlock.rightBlock = newBlock;
newBlock.leftBlock = self.leftBlock;
}
if (self.rightBlock) {
self.rightBlock.leftBlock = newBlock;
newBlock.rightBlock = self.rightBlock;
}
}
self.callDestroy();
}
}
};
if (Math.random() < BLOCK_CRACK_CHANCE) {
self.rotate(true);
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var LAVA_LINE = game.height - 200;
var LAVA_SLICE_COUNT = 18;
var LAVA_SLICE_WIDTH = 128;
var LAVA_BOB_HEIGHT = 10;
var LAVA_BOB_OFFSET = Math.PI / 5;
var LAVA_BOB_PERIOD = Math.PI / 60;
var BLOCK_SCALE = 2.5;
var BLOCK_SIZE = 100;
var BLOCK_MARGIN = 20;
var BLOCK_HALFSIZE = BLOCK_SIZE * 0.5;
var BLOCK_CRACK_CHANCE = 0.3;
var BLOCK_ROTATE_SPEED = 100;
var LIGHT_LEVEL = 500;
var LIGHT_GROW_SPEED = 5000;
var LIGHT_SPILL_SIZE = 35;
var LIGHT_OFFSET = 5;
var ROW_SPAN = 7;
var ROW_COUNT = 11;
var ROW_SPEED_BASE = 0.2;
var ROW_SPEED_INCREASE = 0.02;
var ROW_SPEED_INCREASE_MIN = 0.005;
var ROW_SPEED_INCREASE_FACTOR = 0.95;
var COMPLIMENTS = {
up: 'down',
right: 'left',
down: 'up',
left: 'right'
};
var rowSpeed = ROW_SPEED_BASE;
var score = 0;
var rowSpeedIncrease = ROW_SPEED_INCREASE;
var scoreText = new Text2('0', {
size: 100,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 10
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var lightManager = game.addChild(new Container());
var blockManager = game.addChild(new BlockManager());
var leftBorder = game.addChild(new Border({
x: 30
}));
var rightBorder = game.addChild(new Border({
x: game.width - 30,
scaleX: -1
}));
var lava = game.addChild(new Lava({
x: game.width / 2,
y: LAVA_LINE
}));
game.addChild(new Glow({
anchorX: 0.5,
anchorY: 0,
x: game.width / 2,
y: 0,
width: game.width,
height: 200,
rangeY: 200,
tint: 0x000000,
alpha: 2.0
}));
function shuffle(array) {
var currentIndex = array.length;
while (currentIndex != 0) {
var randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
var ref = [array[randomIndex], array[currentIndex]];
array[currentIndex] = ref[0];
array[randomIndex] = ref[1];
}
return array;
}
function generateBlockClasses(index) {
var settings = {
index: index
};
switch (index) {
case 0:
return [BlockBlank, BlockBlank, BlockBlank, BlockX, BlockBlank, BlockBlank, BlockBlank];
case 1:
settings.blanks = ROW_SPAN; // Prevent additional blanks
return [BlockBlank, BlockBlank, randomizeBlockClass(settings), BlockX, randomizeBlockClass(settings), BlockBlank, BlockBlank];
case 2:
return [BlockBlank, randomizeBlockClass(settings), randomizeBlockClass(settings), BlockX, randomizeBlockClass(settings), randomizeBlockClass(settings), BlockBlank];
default:
var blockClasses = [];
for (var i = 0; i < ROW_SPAN; i++) {
blockClasses[i] = randomizeBlockClass(settings);
}
return shuffle(blockClasses);
}
}
function adjustRowSpeed() {
rowSpeed += rowSpeedIncrease;
rowSpeedIncrease = Math.max(ROW_SPEED_INCREASE_MIN, rowSpeedIncrease * ROW_SPEED_INCREASE_FACTOR);
}
function randomizeBlockClass(settings) {
var classes = [BlockBlank, BlockT, BlockX, BlockLine, BlockL];
return classes[Math.floor(Math.random() * classes.length)];
}
background
Music
light
Sound effect
rotate
Sound effect
error
Sound effect
crack
Sound effect
break
Sound effect
flow
Sound effect
bubble1
Sound effect
bubble2
Sound effect
bubble3
Sound effect
bubble4
Sound effect
bubble5
Sound effect
gong
Sound effect