User prompt
Create a new BlockBreakParticle class which duplicates all the logic in the BlockSparkParticle, however instead of a shapeBox assets, randomize between the blockX1-4 assets
Code edit (1 edits merged)
Please save this source code
User prompt
Replace the: "game.addChild(LK.getAsset('shapeBox', { width: game.width, height: LIGHT_LEVEL, tint: 0x000000 }));" with a black tinted glow class instance with 5 layers, a 10 rangeX, and maintaining the 0,0 anchor
User prompt
re-revert the lockSymbol to a basic asset and tint it 0xFF4D00
Code edit (2 edits merged)
Please save this source code
User prompt
when completing the fadeout of the locksymbol, destroy it and reset the lockSymbol variable
Code edit (1 edits merged)
Please save this source code
User prompt
go back to using a bordersymbol for the lockSymbol
User prompt
reduce the scalex and scaley of the locksymbol by the inverse of the self.scalex and y
User prompt
Replace the lockSymbol BorderedSymbol class with simple asset of the same id
Code edit (1 edits merged)
Please save this source code
User prompt
rotate the lockSymbol to the opposite of self.rotation
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: lockSymbol is not defined' in or related to this line: 'tween(lockSymbol, {' Line Number: 930
User prompt
Before creating a new lockSymbol, check if one exists and destroy it
Code edit (1 edits merged)
Please save this source code
User prompt
In the rotate function for blockblank, lastly, attach a new BorderedSymbol with an iconLock asset. After a 500ms delay this should fade out over 500ms ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/tween.v1
User prompt
when clicking on a blockblank and it's not cracked, attach a new BorderedSymbol with an iconLock asset. After a 500ms delay this should fade out over 500ms ↪💡 Consider importing and using the following plugins: @upit/tween.v1, @upit/tween.v1
User prompt
randomize the BlockSparkParticle shapeBox rotation between 0 and pi
Code edit (1 edits merged)
Please save this source code
User prompt
BlockSparkParticles should also be randomly offset from their origin between 0 and 50 distance along their angle
User prompt
BlockSparkParticles should also be randomly offset from their origin between 0 and 50 distance along their angle
Code edit (1 edits merged)
Please save this source code
User prompt
BlockSparkParticles should be affected by a tiny bit of gravity and also have a 0.5 alpha instead of 0.25
Code edit (6 edits merged)
Please save this source code
/****
* 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 BorderedText('+1', {
anchorX: 0.5,
anchorY: 0.5,
size: 100
}));
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 + Math.random() * LIGHT_GROW_VARIANCE,
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;
if (Math.random() < 0.0025) {
self.parent.particleContainer.addChild(new LavaParticle({
x: self.x + Math.random() * LAVA_SLICE_WIDTH - LAVA_SLICE_WIDTH / 2,
y: self.y,
scale: 1 + Math.random() * 0.5 // Random scale between 1 and 1.5
}));
}
};
return self;
});
var LavaParticle = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
// Attach a glow asset with specified properties
self.rotation = Math.random() * Math.PI; // Random rotation between 0 and pi
self.attachAsset('shapeBox', {
anchorX: 0.5,
anchorY: 0.5,
width: 20,
height: 20,
tint: 0xFF4D00,
alpha: 0.5
});
// Attach a smaller shapeBox with black tint and 0.5 alpha
self.attachAsset('shapeBox', {
anchorX: 0.5,
anchorY: 0.5,
width: 10,
height: 10,
tint: 0x000000,
alpha: 0.25
});
// Set initial random velocities increased by a factor of 10
self.vx = (1 - 2 * Math.random()) * 10; // Random x velocity between 10 and -10
self.vy = (1 - 0.5 * Math.random()) * -8; // Random y velocity between -8 and -4
// Update function to apply gravity and movement
self.update = function () {
self.vy += 0.1; // Gravity effect
self.vx *= 0.975;
self.x += self.vx;
self.y += self.vy;
// Destroy the particle if it goes below the game height
if (self.y > LAVA_BOB_HEIGHT) {
self.callDestroy();
}
};
return self;
});
var Lava = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
self.particleContainer = self.addChild(new Container());
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 config = {
* x : Number || 0, // See: ConfigContainer
* y : Number || 0, // See: ConfigContainer
* rotation : Number || 0, // See: ConfigContainer
* anchorX : Number || 0,
* anchorY : Number || 1,
* size : Number || TEXT_DEFAULT_SIZE,
* font : String || TEXT_DEFAULT_FONT,
* fill : String || TEXT_DEFAULT_FILL,
* border : String || TEXT_DEFAULT_BORDER,
* }
**/
var BorderedText = ConfigContainer.expand(function (text, config) {
var self = ConfigContainer.call(this, config);
config = config || {};
var anchorX = config.anchorX !== undefined ? config.anchorX : 0;
var anchorY = config.anchorY !== undefined ? config.anchorY : 1;
var size = config.size !== undefined ? config.size : TEXT_DEFAULT_SIZE;
var font = config.font !== undefined ? config.font : TEXT_DEFAULT_FONT;
var textFill = config.fill !== undefined ? config.fill : TEXT_DEFAULT_FILL;
var borderFill = config.border !== undefined ? config.border : TEXT_DEFAULT_BORDER;
var mainAsset;
var textAssets = [];
;
self.setText = setText;
self.setFill = setFill;
;
function setText(newText) {
for (var i = 0; i < textAssets.length; i++) {
textAssets[i].setText(newText);
}
}
function setFill(newFill) {
textFill = newFill;
mainAsset.fill = newFill;
}
function buildTextAssets(newText) {
for (var i = 0; i < TEXT_OFFSETS.length; i++) {
var main = i === TEXT_OFFSETS.length - 1;
var textAsset = textAssets[i];
if (textAsset) {
textAsset.destroy();
}
textAsset = self.addChild(new Text2(newText, {
fill: main ? textFill : borderFill,
font: font,
size: size
}));
textAsset.anchor = {
x: anchorX,
y: anchorY
}; // NOTE: Cannot be set in config
textAsset.x = TEXT_OFFSETS[i][0] * TEXT_BORDER_WEIGHT; // NOTE: Cannot be set in config
textAsset.y = TEXT_OFFSETS[i][1] * TEXT_BORDER_WEIGHT; // NOTE: Cannot be set in config
textAssets[i] = textAsset;
}
mainAsset = textAssets[TEXT_OFFSETS.length - 1];
}
;
buildTextAssets(text);
return self;
});
/**
* var config = {
* x : Number || 0, // See: ConfigContainer
* y : Number || 0, // See: ConfigContainer
* rotation : Number || 0, // See: ConfigContainer
* anchorX : Number || .5,
* anchorY : Number || .5,
* scale : Number || undefined,
* scaleX : Number || scale,
* scaleY : Number || scale,
* width : Number || undefined, // Auto-calculated if left undefined and height is set
* height : Number || undefined, // Auto-calculated if left undefined and width is set
* tint : String || 0xFFFFFF, // Not tinted by default
* border : String || TEXT_DEFAULT_BORDER,
* }
**/
var BorderedSymbol = ConfigContainer.expand(function (symbol, config) {
var self = ConfigContainer.call(this, config);
config = config || {};
var width = config.width !== undefined ? config.width : undefined;
var height = config.height !== undefined ? config.height : undefined;
var scale = config.scale !== undefined ? config.scale : undefined;
var scaleX = config.scaleX !== undefined ? config.scaleX : scale;
var scaleY = config.scaleY !== undefined ? config.scaleX : scale;
var anchorX = config.anchorX !== undefined ? config.anchorX : .5;
var anchorY = config.anchorY !== undefined ? config.anchorY : .5;
var symbolTint = config.tint !== undefined ? config.tint : 0xFFFFFF;
var borderTint = config.border !== undefined ? config.border : TEXT_DEFAULT_BORDER;
var mainSymbol;
var symbolAssets = [];
;
self.setSymbol = buildSymbolAssets;
self.setTint = setTint;
;
function setTint(newTint) {
// NOTE: Tinting is currently broken (cannot use string)
// mainSymbol.tint = newTint;
// symbolConfig.tint = newTint;
}
function buildSymbolAssets(newSymbol) {
for (var i = 0; i < TEXT_OFFSETS.length; i++) {
var main = i === TEXT_OFFSETS.length - 1;
var symbolAsset = symbolAssets[i];
if (symbolAsset) {
symbolAsset.destroy();
}
symbolAsset = self.attachAsset(newSymbol, {
// tint: main ? symbolTint : borderTint,
tint: main ? 0xFFFFFF : 0x000000,
// NOTE: Tinting is currently broken (cannot use string)
x: TEXT_OFFSETS[i][0] * TEXT_BORDER_WEIGHT,
y: TEXT_OFFSETS[i][1] * TEXT_BORDER_WEIGHT,
anchorX: anchorX,
anchorY: anchorY
});
if (width !== undefined && height === undefined) {
height = symbolAsset.height * (width / symbolAsset.width);
} else if (height !== undefined && width === undefined) {
width = symbolAsset.width * (height / symbolAsset.height);
}
symbolAsset.width = width;
symbolAsset.height = height;
if (scaleX !== undefined && scaleY !== undefined) {
symbolAsset.scale.set(scaleX, scaleY);
}
symbolAssets[i] = symbolAsset;
}
mainSymbol = symbolAssets[TEXT_OFFSETS.length - 1];
}
;
buildSymbolAssets(symbol);
return self;
});
var Border = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var radius = 70;
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;
}
var borderGear = self.attachAsset('borderGear', {
width: 2 * radius,
height: 2 * radius,
anchorX: 0.5,
anchorY: 0.5,
y: LIGHT_LEVEL,
rotation: Math.random() * Math.PI * 2 // Initialize with random rotation
});
var borderLevel = self.attachAsset('borderLevel', {
anchorX: 0.15,
anchorY: 0.85,
y: LIGHT_LEVEL,
rotation: Math.PI / 4 // 45 degree rotation
});
self.update = function () {
borderGear.rotation += rowSpeed / radius;
};
return self;
});
var BlockSparkParticle = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var shapeBox = self.attachAsset('shapeBox', {
width: 10,
height: 10,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.25
});
// Set initial random direction and speed
var angle = Math.random() * 2 * Math.PI;
self.vx = Math.cos(angle) * 10;
self.vy = Math.sin(angle) * 10;
// Update function to move the particle
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
// Tween to fade out the particle
tween(self, {
alpha: 0
}, {
duration: 350,
onFinish: function onFinish() {
self.callDestroy();
}
});
return self;
});
var BlockRow = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var blockClasses = generateBlockClasses(config.index);
self.index = 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 > LIGHT_LEVEL - BLOCK_SIZE * BLOCK_SCALE / 2) {
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 BlockLitParticle = ConfigContainer.expand(function (config) {
var self = ConfigContainer.call(this, config);
var shapeBox = self.attachAsset('particleBlockLit', {
scaleX: 1.0,
scaleY: 1.0,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.1
});
tween(shapeBox, {
scaleX: 2.0,
scaleY: 2.0,
alpha: 0.0
}, {
duration: 350,
easing: tween.linear,
onFinish: function onFinish() {
self.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.y = Math.max(0, Math.sin(LK.ticks / 60 + self.index) * 10);
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) {
LK.setScore(LK.getScore() + 1);
scoreText.setText(LK.getScore());
game.addChild(new BlockLitParticle({
// Create a BlockLitParticle
x: self.x + self.parent.x,
y: self.y + self.parent.y,
scale: BLOCK_SCALE
}));
game.addChild(new PointText({
x: self.x + self.parent.x,
y: self.y + self.parent.y
}));
}
lightSources += 1;
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.lit) {
lightSources -= 1;
if (lightSources === 0) {
LK.showGameOver("Your light is extinguished");
}
}
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
});
// Create BlockSparkParticles
if (self.parent) {
for (var i = 0; i < 2 * crackLevel; i++) {
game.addChild(new BlockSparkParticle({
x: self.x + self.parent.x,
y: self.y + self.parent.y
}));
}
}
} else {
var blockClass = randomizeBlockClass({
index: self.row.index,
blanks: ROW_SPAN // Prevent spawning blocks
});
var newBlock = self.parent.addChild(new blockClass({
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;
}
if (!self.disabled) {
newBlock.onSettle();
}
self.callDestroy();
}
}
};
if (Math.random() < BLOCK_CRACK_CHANCE) {
self.rotate(true);
}
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Math constants / pre-calculations
var MATH_HALF_ROOT_3 = Math.sqrt(3) / 2; // Required by: TEXT_OFFSETS, BorderedText, BorderedSymbol, SymbolText
;
// Text settings
var TEXT_OFFSETS = [[0, 1], [MATH_HALF_ROOT_3, 0.5], [MATH_HALF_ROOT_3, -0.5], [0, -1], [-MATH_HALF_ROOT_3, -0.5], [-MATH_HALF_ROOT_3, 0.5], [0, 0]]; // Required by: BorderedText, BorderedSymbol, SymbolText
var TEXT_BORDER_WEIGHT = 8; // Required by: BorderedText, BorderedSymbol, SymbolText
var TEXT_DEFAULT_BORDER = '#000000'; // Required by: BorderedText, BorderedSymbol, SymbolText
var TEXT_DEFAULT_FILL = '#FFFFFF'; // Required by: BorderedText, SymbolText
var TEXT_DEFAULT_FONT = 'Arial'; // Required by: BorderedText, SymbolText
var TEXT_DEFAULT_SIZE = 50; // Required by: BorderedText, SymbolText
;
// Other settings
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 = 800;
var LIGHT_GROW_SPEED = 4500;
var LIGHT_GROW_VARIANCE = 1000;
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.04;
var ROW_SPEED_INCREASE_MIN = 0.01;
var ROW_SPEED_INCREASE_FACTOR = 0.9;
var COMPLIMENTS = {
up: 'down',
right: 'left',
down: 'up',
left: 'right'
};
var lightSources = 0;
var rowSpeed = ROW_SPEED_BASE;
var rowSpeedIncrease = ROW_SPEED_INCREASE;
var scoreText = new BorderedText('0', {
size: 100,
anchorX: 0.5,
anchorY: 0
});
LK.gui.top.addChild(scoreText);
var rowSpeedText = LK.gui.topRight.addChild(new Text2((rowSpeed * 60).toFixed(1), {
size: 50,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 5
}));
rowSpeedText.anchor.set(1.0, -0.5);
var speedIcon = LK.gui.topRight.addChild(LK.getAsset('iconGear', {
anchorX: 0.5,
anchorY: 0.5,
x: rowSpeedText.x - rowSpeedText.width - 40,
y: rowSpeedText.height
}));
var iconRotate = LK.gui.topRight.addChild(new BorderedSymbol('iconRotate', {
anchorX: 0.2,
anchorY: 1.0,
x: speedIcon.x,
y: speedIcon.y
}));
var lightManager = game.addChild(new Container());
game.addChild(LK.getAsset('shapeBox', {
width: game.width,
height: LIGHT_LEVEL,
tint: 0x000000
}));
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({
x: game.width / 2,
width: game.width,
height: 200,
anchorX: 0.5,
anchorY: 0,
rangeY: 200,
tint: 0x000000,
alpha: 2.0
}));
var iconLight = game.addChild(LK.getAsset('iconLight', {
x: game.width / 2,
y: 125,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4D00
}));
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,
blanks: 0,
xs: 0
};
switch (index) {
case 0:
return [BlockBlank, BlockBlank, BlockBlank, BlockX, BlockBlank, BlockBlank, BlockBlank];
case 1:
settings.blanks = ROW_SPAN;
settings.xs = 1;
return [BlockBlank, BlockBlank, randomizeBlockClass(settings), BlockX, randomizeBlockClass(settings), BlockBlank, BlockBlank];
case 2:
settings.blanks = ROW_SPAN;
settings.xs = 1;
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;
rowSpeedText.setText((rowSpeed * 60).toFixed(1));
rowSpeedIncrease = Math.max(ROW_SPEED_INCREASE_MIN, rowSpeedIncrease * ROW_SPEED_INCREASE_FACTOR);
}
function randomizeBlockClass(settings) {
var classes = [{
blockClass: BlockBlank,
chance: Math.max(0, 1.5 - 0.5 * (settings.blanks || 0))
}, {
blockClass: BlockT,
chance: 1
}, {
blockClass: BlockX,
chance: Math.max(0, 1 - 1 * (settings.xs || 0))
}, {
blockClass: BlockLine,
chance: 1
}, {
blockClass: BlockL,
chance: 1
}];
var totalChance = classes.reduce(function (sum, item) {
return sum + item.chance;
}, 0);
var randomValue = Math.random() * totalChance;
var accumulatedChance = 0;
var blockClass = BlockBlank;
for (var i = 0; i < classes.length; i++) {
accumulatedChance += classes[i].chance;
if (randomValue < accumulatedChance) {
blockClass = classes[i].blockClass;
break;
}
}
switch (blockClass) {
case BlockBlank:
settings.blanks = (settings.blanks || 0) + 1;
break;
case BlockX:
settings.xs = (settings.xs || 0) + 1;
break;
}
return blockClass;
}