diff --git a/8ia8dlk7l5.js b/8ia8dlk7l5.js new file mode 100644 index 0000000..bd7ef4c --- /dev/null +++ b/8ia8dlk7l5.js @@ -0,0 +1,1711 @@ +if (data.entity === this.parentEntity) { + console.log('my entity loaded'); +} + +/** + * Custom Code Components + */ +this.ccBeforeRender = GameLib.EntityManager.Instance.findComponentById('r8wkd1wwip'); +this.ccKeyDown = GameLib.EntityManager.Instance.findComponentById('airpllbqpu'); +this.ccTouchStart = GameLib.EntityManager.Instance.findComponentById('dwln7lp0w9'); +this.ccTouchEnd = GameLib.EntityManager.Instance.findComponentById('cgw7pwx0jg'); + +/** + * Images + */ +this.image_0 = GameLib.EntityManager.Instance.findComponentById('l8cs0ftjfu'); +this.image_1 = GameLib.EntityManager.Instance.findComponentById('nxx7ywvjua'); +this.image_2 = GameLib.EntityManager.Instance.findComponentById('skuw2a1auy'); +this.image_3 = GameLib.EntityManager.Instance.findComponentById('egq1q2p0jv'); +this.image_4 = GameLib.EntityManager.Instance.findComponentById('nw49tomo2g'); +this.image_5 = GameLib.EntityManager.Instance.findComponentById('5j8ht73i3y'); +this.image_6 = GameLib.EntityManager.Instance.findComponentById('a9wz0y7ukl'); +this.image_grid = GameLib.EntityManager.Instance.findComponentById('qy233xuf15'); +this.image_glow = GameLib.EntityManager.Instance.findComponentById('j374jz2dlp'); +this.image_flames_small = GameLib.EntityManager.Instance.findComponentById('o4tvl5tvk6'); + +/** + * Scene + */ +this.scene = GameLib.EntityManager.Instance.findComponentById('t551yp2uw2'); + +/** + * Materials + */ +this.gridMaterial = GameLib.EntityManager.Instance.findComponentById('ajx545c2rv'); + +/** + * Score + */ +this.scoreCanvas = GameLib.EntityManager.Instance.findComponentById('ke0mqfoxev'); +this.scoreTexture = GameLib.EntityManager.Instance.findComponentById('6k8p84kkgz'); + +/** + * Animations + */ +this.animation = GameLib.EntityManager.Instance.findComponentById('73b6zgwi6g'); + +/** + * Lights + */ +this.burnLight = GameLib.EntityManager.Instance.findComponentById('bprzyzukkr'); + +/** + * Textures + */ +this.textureDisplacement = GameLib.EntityManager.Instance.findComponentById('dwooesyl8u'); + +/** + * Initial Game Settings + * @type {number} + */ +this.score = 0; +this.level = 1; +this.rows = 0; +this.speed = 1; + +this.grid = []; + +this.gameOver = false; + +GameLib.CustomCode.TETRIS_BLOCK_I = 0; +GameLib.CustomCode.TETRIS_BLOCK_L = 1; +GameLib.CustomCode.TETRIS_BLOCK_L2 = 2; +GameLib.CustomCode.TETRIS_BLOCK_Z = 3; +GameLib.CustomCode.TETRIS_BLOCK_Z2 = 4; +GameLib.CustomCode.TETRIS_BLOCK_T = 5; +GameLib.CustomCode.TETRIS_BLOCK_O = 6; +GameLib.CustomCode.TETRIS_BLOCK_MAX = 7; + +GameLib.CustomCode.TETRIS_GRID_WIDTH = 11; +GameLib.CustomCode.TETRIS_GRID_HEIGHT = 24; +GameLib.CustomCode.TETRIS_GRID_HEADSPACE = 4; + +GameLib.CustomCode.TETRIS_GRID_NOT_TAKEN = 0; +GameLib.CustomCode.TETRIS_GRID_TAKEN = 1; +GameLib.CustomCode.TETRIS_GRID_DISAPPEARING = 2; + +GameLib.CustomCode.prototype.visualizeGrid = function (color) { + + if (this.starsMesh) { + this.scene.instance.remove(this.starsMesh); + } + + this.starsGeometry = new THREE.Geometry(); + + for (var y = 0; y < this.grid.length; y++) { + for (var x = 0; x < this.grid[y].length; x++) { + if (this.grid[y][x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN) { + this.starsGeometry.vertices.push( + new THREE.Vector3( + x, + y, + 5 + ) + ); + } + } + } + + var starsMaterial = new THREE.PointsMaterial({color: color, size: 0.1}); + + this.starsMesh = new THREE.Points(this.starsGeometry, starsMaterial); + + this.scene.instance.add(this.starsMesh); + +}.bind(this) + +GameLib.CustomCode.prototype.startAnimation = function (index) { + + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + + var bacon = this.tile_bacon_disappearing.clone(); + + bacon.visible = true; + bacon.updateInstance('visible'); + + bacon.position.x = x; + bacon.position.y = index; + bacon.position.z = 2; + bacon.updateInstance('position'); + + this.grid[index][x].baconDisappearing = bacon; + + this.baconMaterials.push( + this.grid[index][x].mesh.materials[0] + ); + } + + var glow = this.tile_glow.clone(); + + glow.visible = true; + glow.updateInstance('visible'); + + glow.position.y = index; + glow.position.x = (GameLib.CustomCode.TETRIS_GRID_WIDTH / 2) - 0.5; + glow.position.z = 4; + glow.updateInstance('position'); + + var flames = this.tile_flames_small.clone(); + + flames.visible = true; + flames.updateInstance('visible'); + + flames.position.y = index + 0.5; + flames.position.x = (GameLib.CustomCode.TETRIS_GRID_WIDTH / 2) - 0.5; + flames.position.z = 5; + flames.updateInstance('position'); + + var animationObject = { + rowNumber: index, + glow: glow, + flames: flames, + flamesArray: [], + time: 0 + } + + animationObject.subscription = GameLib.Event.Subscribe( + GameLib.Event.BEFORE_RENDER, + function (__animationObject) { + return function (data) { + __animationObject.time += data.delta * 4; + + this.burnLight.intensity = 2 * Math.sin(__animationObject.time); + this.burnLight.updateInstance('intensity'); + + this.tile_glowMaterial.opacity = Math.sin(__animationObject.time); + this.tile_glowMaterial.updateInstance('opacity'); + + if (__animationObject.time < (Math.PI / 2)) { + + this.baconMaterials.map( + function (material) { + material.displacementScale = -1 * Math.sin(__animationObject.time); + material.updateInstance('displacementScale'); + } + ); + + } + + if (__animationObject.time > Math.PI) { + + __animationObject.subscription.remove(); + + /** + * Done with animation + */ + this.burnLight.intensity = 0; + this.burnLight.updateInstance('intensity'); + + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: __animationObject.glow + } + ); + + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: __animationObject.flames + } + ); + + /** + * Remove any additional flames + */ + __animationObject.flamesArray.map( + function (flame) { + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: flame + } + ); + } + ); + + /** + * Remove the meshes and the baconDisappearing objects + */ + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + + if (!this.grid[__animationObject.rowNumber][x].mesh) { + throw new Error('mesh should exist but does not'); + } + + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: this.grid[__animationObject.rowNumber][x].mesh + } + ); + + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: this.grid[__animationObject.rowNumber][x].baconDisappearing + } + ); + + } + + /** + * Add a new row to the top of the grid + */ + this.grid.splice(__animationObject.rowNumber, 1); + + var row = []; + + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + row.push( + { + value: GameLib.CustomCode.TETRIS_GRID_NOT_TAKEN, + mesh: null + } + ) + } + + this.grid.push(row); + + /** + * Now - drop all blocks above the current index down one row + */ + for (var y = __animationObject.rowNumber; y < GameLib.CustomCode.TETRIS_GRID_HEIGHT - 1; y++) { + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + + if (this.grid[y][x].mesh) { + this.grid[y][x].mesh.position.y = y; + this.grid[y][x].mesh.updateInstance('position'); + } + + if (this.grid[y][x].baconDisappearing) { + this.grid[y][x].baconDisappearing.position.y = y; + this.grid[y][x].baconDisappearing.updateInstance('position'); + } + } + } + + /** + * Find any animation objects with a line number greater than our current line number, decrease it + */ + this.animationObjects.map( + function (animationObject) { + if (animationObject.rowNumber > __animationObject.rowNumber) { + animationObject.rowNumber -= 1; + } + } + ) + + var objectIndex = this.animationObjects.indexOf(__animationObject); + + /** + * Remove ourselves from the animation objects + */ + this.animationObjects.splice(objectIndex, 1); + + /** + * Restore our bacon materials if we have no more animation objects + */ + if (this.animationObjects.length === 0) { + + this.baconMaterials.map( + function (material) { + material.displacementScale = 0; + material.updateInstance('displacementScale'); + } + ); + + this.baconMaterials = []; + } + + } + + }.bind(this) + }.bind(this)(animationObject) + ); + + this.animationObjects.push(animationObject); +}.bind(this) + +GameLib.CustomCode.prototype.removeLines = function () { + + var indices = []; + + for (var y = 0; y < GameLib.CustomCode.TETRIS_GRID_HEIGHT; y++) { + + var line = true; + + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + if ( + this.grid[y][x].value === GameLib.CustomCode.TETRIS_GRID_NOT_TAKEN || + this.grid[y][x].value === GameLib.CustomCode.TETRIS_GRID_DISAPPEARING + ) { + line = false; + } + } + + if (line) { + indices.push(y); + } + } + + var multiplier = 1; + + if (indices.length === 4) { + multiplier = 10000; + } + + if (indices.length === 3) { + multiplier = 1000; + } + + if (indices.length === 2) { + multiplier = 100; + } + + if (indices.length === 1) { + multiplier = 10; + } + + this.score += (multiplier * this.level); + + this.rows += indices.length; + + this.level = Math.floor(this.rows / 5) + 1; + + if (this.level === 1) { + this.speed = 1; + } + + if (this.level === 2) { + this.speed = 0.9; + } + + if (this.level === 3) { + this.speed = 0.85; + } + + if (this.level === 4) { + this.speed = 0.8; + } + + if (this.level === 5) { + this.speed = 0.75; + } + + if (this.level === 6) { + this.speed = 0.7; + } + + if (this.level === 7) { + this.speed = 0.65; + } + + if (this.level === 8) { + this.speed = 0.6; + } + + if (this.level === 9) { + this.speed = 0.55; + } + + if (this.level === 10) { + this.speed = 0.5; + } + + if (this.level === 11) { + this.speed = 0.45; + } + + if (this.level === 12) { + this.speed = 0.4; + } + + if (this.level === 13) { + this.speed = 0.35; + } + + if (this.level === 14) { + this.speed = 0.3; + } + + if (this.level === 15) { + this.speed = 0.25; + } + + if (this.level === 16) { + this.speed = 0.2; + } + + if (this.level >= 17) { + this.speed = 0.18; + } + + this.drawStatus(); + + this.animationsDone = []; + + indices.map( + function (index) { + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + this.grid[index][x].value = GameLib.CustomCode.TETRIS_GRID_DISAPPEARING; + } + this.startAnimation(index); + }.bind(this) + ); + +}.bind(this); + + +GameLib.CustomCode.prototype.drawStatus = function () { + var context = this.scoreCanvas.instance.getContext('2d'); + + context.textBaseline = "middle"; + + context.clearRect(0, 0, this.scoreCanvas.width, this.scoreCanvas.height); + + context.fillStyle = "rgba(58, 36, 25, 0.7)"; + context.fillRect(12, 30, 485, 178); + + context.lineWidth = 8; + + context.strokeStyle = '#eeb999'; + context.strokeRect(12, 30, 485, 178); + + context.beginPath(); + context.moveTo(11, 68); + context.lineTo(498, 68); + context.stroke(); + + context.beginPath(); + context.moveTo(172, 30); + context.lineTo(172, 208); + context.stroke(); + + context.beginPath(); + context.moveTo(172, 135); + context.lineTo(498, 135); + context.stroke(); + + context.beginPath(); + context.moveTo(172, 172); + context.lineTo(498, 172); + context.stroke(); + + /** + * Write text + */ + context.fillStyle = '#eeb999'; + context.font = '20pt BkBold'; + context.fillText('NEXT TILES', 23, 52); + + context.fillText('SCORE', 182, 52); + + context.fillText('LEVEL', 182, 156); + + context.fillText('ROWS', 182, 193); + + context.fillStyle = '#eeb999'; + + context.font = '50pt BkBold'; + + var str = this.score.toString(); + var pad = "0000000"; + var ans = pad.substring(0, pad.length - str.length) + str; + + context.fillText(ans, 225, 110); + + str = this.level.toString(); + pad = "000"; + ans = pad.substring(0, pad.length - str.length) + str; + + context.font = '20pt BkBold'; + context.fillText(ans, 435, 156); + + str = this.rows.toString(); + pad = "000"; + ans = pad.substring(0, pad.length - str.length) + str; + + context.font = '20pt BkBold'; + context.fillText(ans, 435, 193); + + this.scoreTexture.instance.needsUpdate = true; +}.bind(this) + +GameLib.CustomCode.prototype.getBlockGridPositions = function (block) { + + var object = new THREE.Mesh(); + + object.position.x = block.center.position.x; + object.position.y = block.center.position.y; + object.position.z = block.center.position.z; + object.rotation.x = block.center.rotation.x; + object.rotation.y = block.center.rotation.y; + object.rotation.z = block.center.rotation.z; + + var children = block.meshes.map( + function (mesh) { + var child = new THREE.Mesh(); + child.position.x = mesh.position.x; + child.position.y = mesh.position.y; + child.position.z = mesh.position.z; + object.add(child); + child.mesh = mesh; + return child; + } + ); + + object.updateMatrixWorld(); + + var positions = children.map( + function (child) { + + var vector = new THREE.Vector3(); + + vector.setFromMatrixPosition(child.matrixWorld); + + var x = vector.x; + var y = vector.y; + + x = Math.round(x); + y = Math.round(y); + + return { + x: x, + y: y, + mesh: child.mesh + } + } + ); + + return positions; + +}.bind(this); + +GameLib.CustomCode.prototype.drawGrid = function () { + + var geometry = new THREE.PlaneBufferGeometry(); + + var mesh = new THREE.Mesh( + geometry, + this.gridMaterial.instance + ); + + for (var y = 0; y < (GameLib.CustomCode.TETRIS_GRID_HEIGHT - GameLib.CustomCode.TETRIS_GRID_HEADSPACE); y++) { + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + + var clone = mesh.clone(); + + clone.position.x = x; + clone.position.y = y; + clone.position.z = 2; + + this.scene.instance.add(clone); + } + } + + geometry = new THREE.Geometry(); + + geometry.vertices.push( + new THREE.Vector3( + -0.5, + GameLib.CustomCode.TETRIS_GRID_HEIGHT - GameLib.CustomCode.TETRIS_GRID_HEADSPACE - 0.5, + 5 + ), + new THREE.Vector3( + -0.5, + -0.5, + 5 + ), + new THREE.Vector3( + GameLib.CustomCode.TETRIS_GRID_WIDTH - 0.5, + -0.5, + 5 + ), + new THREE.Vector3( + GameLib.CustomCode.TETRIS_GRID_WIDTH - 0.5, + GameLib.CustomCode.TETRIS_GRID_HEIGHT - GameLib.CustomCode.TETRIS_GRID_HEADSPACE - 0.5, + 5 + ) + ); + + this.scene.instance.add( + new THREE.Line( + geometry, + new THREE.LineBasicMaterial( + { + linewidth: 3, + color: 0x612d1a + } + ) + ) + ); + + +}.bind(this) + +GameLib.CustomCode.prototype.checkBoundaries = function (block) { + + /** + * collisions are true only for out of bounds indexes, and if the current block is taken + */ + var gridPositions = this.getBlockGridPositions(block); + + var leftHit = false; + var rightHit = false; + var bottomHit = false; + var topHit = false; + var collision = false; + var bottomDisappearing = false; + + gridPositions.map( + function (position) { + + /** + * Check grid boundaries + */ + if (position.x === 0) { + leftHit = true; + } + + if (position.x === (GameLib.CustomCode.TETRIS_GRID_WIDTH - 1)) { + rightHit = true; + } + + if (position.y === 0) { + bottomHit = true; + } + + if (position.y === (GameLib.CustomCode.TETRIS_GRID_HEIGHT - 1)) { + topHit = true; + } + + /** + * Check outside of bounds + */ + if (position.x < 0) { + collision = true; + } + + if (position.x >= GameLib.CustomCode.TETRIS_GRID_WIDTH) { + collision = true; + } + + if (position.y < 0) { + collision = true; + } + + if (position.y >= GameLib.CustomCode.TETRIS_GRID_HEIGHT) { + collision = true; + } + + /** + * We want to see if the block to the right is taken, but we cannot + * be sure x+1 is inside bounds + */ + if ( + ((position.x + 1) < GameLib.CustomCode.TETRIS_GRID_WIDTH) && + ((position.x + 1) >= 0) + ) { + /** + * But we cannot be sure y is inside bounds + */ + if (position.y < GameLib.CustomCode.TETRIS_GRID_HEIGHT && position.y >= 0) { + if (this.grid[position.y][position.x + 1].value === GameLib.CustomCode.TETRIS_GRID_TAKEN) { + /** + * Ok - we found a block to the right - its over + */ + rightHit = true; + } + } + } + + + /** + * We want to see if the block to the left is taken, but we cannot be sure x - 1 is inside bounds + */ + if ( + ((position.x) > 0) && + ((position.x - 1) >= 0) && + ((position.x - 1) < GameLib.CustomCode.TETRIS_GRID_WIDTH) + ) { + + /** + * But we cannot be sure y is inside bounds + */ + if (position.y < GameLib.CustomCode.TETRIS_GRID_HEIGHT && position.y >= 0) { + if (this.grid[position.y][position.x - 1].value === GameLib.CustomCode.TETRIS_GRID_TAKEN) { + /** + * We found a block to the left - its over also + */ + leftHit = true; + } + } + } + + /** + * Now we want to see if the block above is taken, we cannot be sure y+1 is inside bounds + */ + if ( + ((position.y + 1) < GameLib.CustomCode.TETRIS_GRID_HEIGHT) && + ((position.y + 1) >= 0) + ) { + /** + * We cannot be sure, position.x is inside bounds + */ + if (position.x < GameLib.CustomCode.TETRIS_GRID_WIDTH && position.x >= 0) { + + if (this.grid[position.y + 1][position.x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN) { + /** + * Ok - this block is at the top + */ + topHit = true; + } + } + } + + /** + * Now we want to see if the block below is taken, we cannot be sure y-1 is inside bounds + */ + if ( + ((position.y) > 0) && + ((position.y - 1) >= 0) && + ((position.y - 1) < GameLib.CustomCode.TETRIS_GRID_HEIGHT) + ) { + /** + * We cannot be sure, position.x is inside bounds + */ + if (position.x < GameLib.CustomCode.TETRIS_GRID_WIDTH && position.x >= 0) { + if (this.grid[position.y - 1][position.x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN) { + /** + * Ok - this block hit bottom + */ + bottomHit = true; + } + + if (this.grid[position.y - 1][position.x].value === GameLib.CustomCode.TETRIS_GRID_DISAPPEARING) { + bottomDisappearing = true; + } + } + } + + /** + * Now we want to see if the block is inside another block, + * we cannot be sure, x and y is inside bounds + */ + if ( + (position.x < GameLib.CustomCode.TETRIS_GRID_WIDTH && position.x >= 0) && + (position.y < GameLib.CustomCode.TETRIS_GRID_HEIGHT && position.y >= 0) + ) { + if (this.grid[position.y][position.x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN) { + collision = true; + } + } + }.bind(this) + ); + + return { + left: leftHit, + top: topHit, + right: rightHit, + bottom: bottomHit, + bottomDisappearing: bottomDisappearing, + collision: collision + } + +}.bind(this) + +GameLib.CustomCode.prototype.rotateBlock = function (clockwise) { + + if (this.gameOver) { + return; + } + + if (clockwise) { + var targetRotation = this.block.center.rotation.z - Math.PI / 2; + } else { + var targetRotation = this.block.center.rotation.z + Math.PI / 2; + } + + var rotationBackup = { + instance : this.block.center.instance.rotation.z, + object : this.block.center.rotation.z + } + + this.block.center.rotation.z = targetRotation; + this.block.center.updateInstance('rotation'); + + var boundaries = this.checkBoundaries(this.block); + + if (boundaries.collision) { + + /** + * There's a collision, restore the instance rotation + */ + this.block.center.instance.rotation.z = rotationBackup.instance; + + /** + * And also the object rotation + */ + this.block.center.rotation.z = rotationBackup.object; + + } else { + + /** + * Restore our instance rotation + */ + this.block.center.instance.rotation.z = rotationBackup.instance; + + /** + * Update our object to the new rotation + */ + this.block.center.rotation.z = targetRotation; + } + +}.bind(this); + +GameLib.CustomCode.prototype.moveBlock = function (block, direction, units, collisionCheck) { + + if (GameLib.Utils.UndefinedOrNull(block)) { + block = this.block; + } + + if (!units) { + units = 1; + } + + var boundaries = null; + var moved = false; + + if (collisionCheck) { + boundaries = this.checkBoundaries(block); + } + + if (boundaries && boundaries.collision) { + return moved; + } + + if (direction.left) { + + if (boundaries && boundaries.left) { + //Do nothing + } else { + block.center.position.x -= units; + moved = true; + } + } + + if (direction.right) { + + if (boundaries && boundaries.right) { + //Do nothing + } else { + block.center.position.x += units; + moved = true; + } + } + + if (direction.down) { + + if (boundaries && boundaries.bottom) { + //Do nothing + } else if (boundaries && boundaries.bottomDisappearing) { + /** + * Set moved to 'null' instead of 'false' - null indicates to called we should wait - while still being 'false' + */ + moved = null; + } else { + block.center.position.y -= units; + moved = true; + } + } + + if (direction.up) { + + if (boundaries && boundaries.top) { + //Do nothing + } else { + block.center.position.y += units; + moved = true; + } + } + + return moved; +}.bind(this); + +GameLib.CustomCode.prototype.spawnBlock = function () { + + var blockType = Math.floor(Math.random() * 7); + + var mesh0 = null; + var mesh1 = null; + var mesh2 = null; + var mesh3 = null; + + var offsetX = 0; + var offsetY = 0; + + var tinyPositionX = 0; + var tinyPositionY = 0; + + var nextPositionX = 0; + var nextPositionY = 0; + + var center = this.tile_center.clone(); + + center.visible = true; + center.updateInstance('visible'); + + center.position.y = 0; + center.position.x = 0; + center.position.z = 3.5; + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_I) { + + mesh0 = this.tile_4.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.x -= 1; + + mesh1 = this.tile_5.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + mesh1.position.x -= 2; + + mesh2 = this.tile_6.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + mesh2.position.x += 0; + + mesh3 = this.tile_2.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.x += 1; + + offsetX = 0.5; + offsetY = 1; + + tinyPositionX = 1.32; + tinyPositionY = 16.7; + + nextPositionX = 2.12; + nextPositionY = 15.5; + } + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_L) { + mesh0 = this.tile_6.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.x += 1; + mesh0.position.y += 1; + + mesh1 = this.tile_4.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + mesh1.position.x += 1; + + mesh2 = this.tile_6.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + mesh2.position.x += 0; + + mesh3 = this.tile_2.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.x -= 1; + + offsetX = 0.5; + offsetY = 2; + + tinyPositionX = 1.00; + tinyPositionY = 16.65; + + nextPositionX = 1.78; + nextPositionY = 15.3; + } + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_L2) { + mesh0 = this.tile_6.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.x -= 1; + mesh0.position.y += 1; + + mesh1 = this.tile_4.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + mesh1.position.x += 1; + + mesh2 = this.tile_6.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + mesh2.position.x += 0; + + mesh3 = this.tile_2.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.x -= 1; + + offsetX = 0.5; + offsetY = 2; + + tinyPositionX = 1.00; + tinyPositionY = 16.65; + + nextPositionX = 1.78; + nextPositionY = 15.3; + } + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_Z) { + mesh0 = this.tile_3.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.y += 1; + + mesh1 = this.tile_4.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + mesh1.position.x -= 1; + mesh1.position.y += 1; + + mesh2 = this.tile_2.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + + mesh3 = this.tile_1.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.x += 1; + + offsetX = 0.5; + offsetY = 2; + + tinyPositionX = 1.00; + tinyPositionY = 16.65; + + nextPositionX = 1.78; + nextPositionY = 15.3; + } + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_Z2) { + + mesh0 = this.tile_3.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.y += 1; + + mesh1 = this.tile_4.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + mesh1.position.x += 1; + mesh1.position.y += 1; + + mesh2 = this.tile_2.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + + mesh3 = this.tile_1.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.x -= 1; + + offsetX = 0.5; + offsetY = 2; + + tinyPositionX = 1.00; + tinyPositionY = 16.65; + + nextPositionX = 1.78; + nextPositionY = 15.3; + } + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_T) { + mesh0 = this.tile_6.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.y -= 1; + + mesh1 = this.tile_5.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + + mesh2 = this.tile_4.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + mesh2.position.x -= 1; + + mesh3 = this.tile_2.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.x += 1; + + offsetX = 0.5; + offsetY = 1; + + tinyPositionX = 1.00; + tinyPositionY = 17; + + nextPositionX = 1.78; + nextPositionY = 16; + } + + if (blockType === GameLib.CustomCode.TETRIS_BLOCK_O) { + mesh0 = this.tile_3.clone(); + mesh0.position.setFrom(center.position); + mesh0.position.z = -0.1; + mesh0.position.y += 0.5; + mesh0.position.x += 0.5; + + mesh1 = this.tile_0.clone(); + mesh1.position.setFrom(center.position); + mesh1.position.z = -0.1; + mesh1.position.y += 0.5; + mesh1.position.x -= 0.5; + + mesh2 = this.tile_5.clone(); + mesh2.position.setFrom(center.position); + mesh2.position.z = -0.1; + mesh2.position.y -= 0.5; + mesh2.position.x -= 0.5; + + mesh3 = this.tile_2.clone(); + mesh3.position.setFrom(center.position); + mesh3.position.z = -0.1; + mesh3.position.y -= 0.5; + mesh3.position.x += 0.5; + + offsetX = 0; + offsetY = 1.5; + + tinyPositionX = 1.00; + tinyPositionY = 16.85; + + nextPositionX = 1.78; + nextPositionY = 15.65; + } + + mesh0.visible = true; + mesh0.updateInstance('visible'); + mesh1.visible = true; + mesh1.updateInstance('visible'); + mesh2.visible = true; + mesh2.updateInstance('visible'); + mesh3.visible = true; + mesh3.updateInstance('visible'); + + mesh0.parentMesh = center; + mesh0.updateInstance('parentMesh'); + + mesh1.parentMesh = center; + mesh1.updateInstance('parentMesh'); + + mesh2.parentMesh = center; + mesh2.updateInstance('parentMesh'); + + mesh3.parentMesh = center; + mesh3.updateInstance('parentMesh'); + + center.updateInstance('position'); + + mesh0.updateInstance('position'); + mesh1.updateInstance('position'); + mesh2.updateInstance('position'); + mesh3.updateInstance('position'); + + var block = { + type: blockType, + offset: { + x: offsetX, + y: offsetY + }, + tinyPosition: { + x: tinyPositionX, + y: tinyPositionY + }, + nextPosition: { + x: nextPositionX, + y: nextPositionY + }, + meshes: [ + mesh0, + mesh1, + mesh2, + mesh3 + ], + angle: center.rotation.z, + center: center + }; + + return block; + +}.bind(this) + +GameLib.CustomCode.prototype.spawnTinyBlock = function () { + + var block = this.spawnBlock(); + + /** + * Set the scale for the blocks + */ + block.center.scale.x = 0.333; + block.center.scale.y = 0.333; + block.center.scale.z = 0.333; + block.center.updateInstance('scale'); + + /** + * move tiny block a bit up - then a bit right + */ + block.center.position.x = block.tinyPosition.x; + block.center.position.y = block.tinyPosition.y; + block.center.position.z = 0.4; + block.center.updateInstance('position'); + + return block; +}.bind(this) + +GameLib.CustomCode.prototype.spawnNextBlock = function () { + + if (!this.tinyBlock) { + this.tinyBlock = this.spawnTinyBlock(); + } + + var block = this.tinyBlock; + + block.center.scale.x = 0.666; + block.center.scale.y = 0.666; + block.center.scale.z = 0.666; + block.center.updateInstance('scale'); + + block.center.position.x = block.nextPosition.x; + block.center.position.y = block.nextPosition.y; + block.center.position.z = 0.4; + block.center.updateInstance('position'); + + this.tinyBlock = this.spawnTinyBlock(); + + return block; +}.bind(this) + +GameLib.CustomCode.prototype.spawnBigBlock = function () { + + if (!this.nextBlock) { + this.nextBlock = this.spawnNextBlock(); + } + + var block = this.nextBlock; + + block.center.scale.x = 1; + block.center.scale.y = 1; + block.center.scale.z = 1; + block.center.updateInstance('scale'); + + block.center.position.x = 0; + block.center.position.y = 0; + block.center.position.z = 2.5; + this.moveBlock(block, {up: true}, (GameLib.CustomCode.TETRIS_GRID_HEIGHT - GameLib.CustomCode.TETRIS_GRID_HEADSPACE), false); + this.moveBlock(block, {right: true}, GameLib.CustomCode.TETRIS_GRID_WIDTH / 2, false); + this.moveBlock(block, {left: true}, block.offset.x, false); + this.moveBlock(block, {down: true}, block.offset.y, false); + block.center.updateInstance('position'); + + this.nextBlock = this.spawnNextBlock(); + + return block; +}.bind(this) + +GameLib.CustomCode.prototype.getNextBlock = function () { + + this.block = this.spawnBigBlock(); + + GameLib.Event.Emit( + GameLib.Event.COMPONENT_REGISTER, + { + component: this.block.center + } + ); + + this.animation.meshes.push(this.block.center); + +}.bind(this); + +/** + * This code executes when the 'bottom' has been reached (the block is stopping) + */ +GameLib.CustomCode.prototype.stopBlock = function() { + + var gridPositions = this.getBlockGridPositions(this.block); + + gridPositions.map( + + function (position) { + + /** + * If there already is a mesh - remove it - + */ + var block = this.grid[position.y][position.x]; + + if (block.mesh) { + this.scene.removeObject(block.mesh); + } + if (block.baconDisappearing) { + this.scene.removeObject(block.baconDisappearing); + } + + block = { + value : GameLib.CustomCode.TETRIS_GRID_TAKEN, + mesh : position.mesh, + baconDisappearing : null + } + + this.grid[position.y][position.x] = block; + + }.bind(this) + + ); + + /** + * We apply our current rotation and position to the instance + */ + this.block.center.updateInstance('position'); + this.block.center.updateInstance('rotation'); + + /** + * Now we unlink the meshes from the controlling center block + */ + this.block.meshes.map( + function (mesh) { + + mesh.parentMesh = null; + mesh.updateInstance('parentMesh'); + + mesh.position.z = 2.5; + mesh.updateInstance('position'); + + }.bind(this) + ); + + /** + * We remove the controlling block + */ + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: this.block.center + } + ); + + /** + * We remove any lines + */ + this.removeLines(); + + //this.visualizeGrid(0xff0000); + + /** + * Check if the game is over + */ + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + if ( + this.grid[19][x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN || + this.grid[20][x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN || + this.grid[21][x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN || + this.grid[22][x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN || + this.grid[23][x].value === GameLib.CustomCode.TETRIS_GRID_TAKEN + ) { + this.gameOver = true; + } + } + + if (this.gameOver) { + + /** + * End the game if game over + */ + GameLib.Event.Emit( + GameLib.Event.GAME_OVER, + { + score: this.score, + level: this.level, + rows: this.rows + } + ); + + } else { + + /** + * Otherwise continue + */ + this.getNextBlock(); + } + +}.bind(this); + +/** + * Clears the grid + */ +GameLib.CustomCode.prototype.clearGrid = function() { + + /** + * Remove all stale components (if any) + */ + if (this.grid instanceof Array) { + this.grid.map( + function(row) { + row.map( + function(block){ + if (block.mesh) { + this.scene.removeObject(block.mesh); + } + if (block.baconDisappearing) { + this.scene.removeObject(block.baconDisappearing); + } + }.bind(this) + ) + }.bind(this) + ) + } + + /** + * Initialize the grid + */ + this.grid = []; + for (var y = 0; y < GameLib.CustomCode.TETRIS_GRID_HEIGHT; y++) { + this.grid[y] = []; + for (var x = 0; x < GameLib.CustomCode.TETRIS_GRID_WIDTH; x++) { + this.grid[y][x] = { + value : GameLib.CustomCode.TETRIS_GRID_NOT_TAKEN, + mesh : null, + baconDisappearing : null + }; + } + } + +}.bind(this) + +GameLib.CustomCode.prototype.createTile = function(tileName, imageName, displace) { + + var apiMaterial; + + if (imageName) { + if (displace) { + apiMaterial = new GameLib.D3.API.Material.Phong( + null, + null, + null, + null, + null, + null, + null, + null, + this.textureDisplacement, + null, + null, + null, + null, + null, + null, + null, + null, + new GameLib.D3.API.Texture.Image( + null, + this[imageName] + ) + ) + } else { + apiMaterial = new GameLib.D3.API.Material.Phong( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + new GameLib.D3.API.Texture.Image( + null, + this[imageName] + ) + ) + } + } else { + apiMaterial = new GameLib.D3.API.Material.Phong(); + } + + this[tileName] = new GameLib.D3.Mesh( + this.graphics, + new GameLib.D3.API.Mesh( + null, + null, + null, + null, + new GameLib.D3.API.Geometry.Buffer.Plane( + null, + 1, + 1, + 10, + 10 + ), + [ + apiMaterial + ], + null, + this.scene + ) + ) + + this[tileName].visible = false; + this[tileName].updateInstance('visible'); + + /** + * Remove this tile from the 'meshes' so it is treated like a clone and doesn't get stored + */ + this[tileName].parentScene.addClone(this[tileName]); + +}.bind(this); + +GameLib.Event.Subscribe( + GameLib.Event.CUSTOM_GAME_START, + + function () { + + this.animationObjects = []; + + this.baconMaterials = []; + + this.score = 0; + this.level = 1; + this.rows = 0; + this.speed = 1; + + /** + * Draw our new status + */ + this.drawStatus(); + + /** + * Ensure the grid is cleared + */ + this.clearGrid(); + + + if (this.block && this.block.center) { + + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: this.block.center + } + ); + } + + if (this.block && this.block.meshes) { + this.block.meshes.map( + function (mesh) { + GameLib.Event.Emit( + GameLib.Event.REMOVE_COMPONENT, + { + component: mesh + } + ); + }.bind(this) + ); + } + + + this.getNextBlock(); + + /** + * Set the game parameters + */ + this.ccBeforeRender.entityLoaded = null; + this.ccBeforeRender.initialized = false; + + /** + * Link the classes + */ + this.ccBeforeRender.entityLoaded = this; + this.ccKeyDown.entityLoaded = this; + this.ccTouchStart.entityLoaded = this; + this.ccTouchEnd.entityLoaded = this; + + /** + * Allow the game to proceed + * @type {boolean} + */ + this.gameOver = false; + + console.log('game start complete'); + + }.bind(this) +); + +GameLib.Event.Emit( + GameLib.Event.GET_RUNTIME, + {}, + function(runtime) { + + this.graphics = runtime.graphics; + + this.createTile('tile_0', 'image_0', true); + this.createTile('tile_1', 'image_1', true); + this.createTile('tile_2', 'image_2', true); + this.createTile('tile_3', 'image_3', true); + this.createTile('tile_4', 'image_4', true); + this.createTile('tile_5', 'image_5', true); + this.createTile('tile_6', 'image_6', true); + + this.createTile('tile_grid', 'image_grid'); + + this.createTile('tile_flames_small', 'image_flames_small'); + + this.tile_flames_small.materials[0].transparent = true; + this.tile_flames_small.materials[0].updateInstance('transparent'); + + this.tile_flames_small.geometry.width = '11'; + this.tile_flames_small.geometry.height = '11'; + this.tile_flames_small.geometry.updateInstance('width'); + + this.createTile('tile_glow', 'image_glow'); + + this.tile_glow.materials[0].transparent = true; + this.tile_glow.materials[0].updateInstance('transparent'); + + this.tile_glow.geometry.width = '12'; + this.tile_glow.geometry.height = '12'; + this.tile_glow.geometry.updateInstance('width'); + + this.tile_glowMaterial = this.tile_glow.materials[0]; + + this.createTile('tile_center'); + + this.tile_center.materials[0].transparent = true; + this.tile_center.materials[0].updateInstance('transparent'); + + this.tile_center.materials[0].opacity = 0; + this.tile_center.materials[0].updateInstance('opacity'); + + this.tile_center.useQuaternion = false; + + this.createTile('tile_bacon_disappearing'); + + this.tile_bacon_disappearing.materials[0].color.fromHex('#3e1d1d'); + this.tile_bacon_disappearing.materials[0].updateInstance('color'); + + this.drawGrid(); + this.drawStatus(); + + GameLib.Event.Emit(GameLib.Event.GAME_LOADED); + + }.bind(this) +) +//@ sourceURL=entityLoaded.js \ No newline at end of file