if (data.entity === this.parentEntity) { console.log('my entity loaded'); } /** * Custom Code Components */ this.ccBeforeRender = R3.EntityManager.Instance.findComponentById('o4c478xpx3'); this.ccKeyDown = R3.EntityManager.Instance.findComponentById('dgscoensvf'); this.ccTouchStart = R3.EntityManager.Instance.findComponentById('xjaoh824ff'); this.ccTouchEnd = R3.EntityManager.Instance.findComponentById('ohqwmnjfgf'); /** * Images */ this.image_0 = R3.EntityManager.Instance.findComponentById('gvrik6h4yd'); this.image_1 = R3.EntityManager.Instance.findComponentById('ssdlmrpv9j'); this.image_2 = R3.EntityManager.Instance.findComponentById('zdg2qpu35c'); this.image_3 = R3.EntityManager.Instance.findComponentById('pjy42fg69n'); this.image_4 = R3.EntityManager.Instance.findComponentById('5t3olr10pw'); this.image_5 = R3.EntityManager.Instance.findComponentById('qrh0foyins'); this.image_6 = R3.EntityManager.Instance.findComponentById('0bjbsj4sss'); this.image_grid = R3.EntityManager.Instance.findComponentById('7yji3yzct9'); this.image_glow = R3.EntityManager.Instance.findComponentById('aei9gfkjb6'); this.image_flames_small = R3.EntityManager.Instance.findComponentById('vp4zkbx7yr'); /** * Scene */ this.scene = R3.EntityManager.Instance.findComponentById('i1ac678a5d'); /** * Materials */ this.gridMaterial = R3.EntityManager.Instance.findComponentById('1tp9zqjo6s'); /** * Score */ this.scoreCanvas = R3.EntityManager.Instance.findComponentById('85d0jk6dhx'); this.scoreTexture = R3.EntityManager.Instance.findComponentById('kva68t4dm8'); /** * Animations */ this.animation = R3.EntityManager.Instance.findComponentById('tnlwgvf12x'); /** * Lights */ this.burnLight = R3.EntityManager.Instance.findComponentById('q13y5xwv6c'); /** * Textures */ this.textureDisplacement = R3.EntityManager.Instance.findComponentById('b0du0xqeeu'); /** * Initial Game Settings * @type {number} */ this.score = 0; this.level = 1; this.rows = 0; this.speed = 1; this.grid = []; this.gameOver = false; R3.CustomCode.TETRIS_BLOCK_I = 0; R3.CustomCode.TETRIS_BLOCK_L = 1; R3.CustomCode.TETRIS_BLOCK_L2 = 2; R3.CustomCode.TETRIS_BLOCK_Z = 3; R3.CustomCode.TETRIS_BLOCK_Z2 = 4; R3.CustomCode.TETRIS_BLOCK_T = 5; R3.CustomCode.TETRIS_BLOCK_O = 6; R3.CustomCode.TETRIS_BLOCK_MAX = 7; R3.CustomCode.TETRIS_GRID_WIDTH = 11; R3.CustomCode.TETRIS_GRID_HEIGHT = 24; R3.CustomCode.TETRIS_GRID_HEADSPACE = 4; R3.CustomCode.TETRIS_GRID_NOT_TAKEN = 0; R3.CustomCode.TETRIS_GRID_TAKEN = 1; R3.CustomCode.TETRIS_GRID_DISAPPEARING = 2; R3.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 === R3.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) R3.CustomCode.prototype.startAnimation = function (index) { for (var x = 0; x < R3.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 = (R3.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 = (R3.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 = R3.Event.Subscribe( R3.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'); R3.Event.Emit( R3.Event.REMOVE_COMPONENT, { component: __animationObject.glow } ); R3.Event.Emit( R3.Event.REMOVE_COMPONENT, { component: __animationObject.flames } ); /** * Remove any additional flames */ __animationObject.flamesArray.map( function (flame) { R3.Event.Emit( R3.Event.REMOVE_COMPONENT, { component: flame } ); } ); /** * Remove the meshes and the baconDisappearing objects */ for (var x = 0; x < R3.CustomCode.TETRIS_GRID_WIDTH; x++) { if (!this.grid[__animationObject.rowNumber][x].mesh) { throw new Error('mesh should exist but does not'); } R3.Event.Emit( R3.Event.REMOVE_COMPONENT, { component: this.grid[__animationObject.rowNumber][x].mesh } ); R3.Event.Emit( R3.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 < R3.CustomCode.TETRIS_GRID_WIDTH; x++) { row.push( { value: R3.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 < R3.CustomCode.TETRIS_GRID_HEIGHT - 1; y++) { for (var x = 0; x < R3.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) R3.CustomCode.prototype.removeLines = function () { var indices = []; for (var y = 0; y < R3.CustomCode.TETRIS_GRID_HEIGHT; y++) { var line = true; for (var x = 0; x < R3.CustomCode.TETRIS_GRID_WIDTH; x++) { if ( this.grid[y][x].value === R3.CustomCode.TETRIS_GRID_NOT_TAKEN || this.grid[y][x].value === R3.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 < R3.CustomCode.TETRIS_GRID_WIDTH; x++) { this.grid[index][x].value = R3.CustomCode.TETRIS_GRID_DISAPPEARING; } this.startAnimation(index); }.bind(this) ); }.bind(this); R3.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) R3.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); R3.CustomCode.prototype.drawGrid = function () { var geometry = new THREE.PlaneBufferGeometry(); var mesh = new THREE.Mesh( geometry, this.gridMaterial.instance ); for (var y = 0; y < (R3.CustomCode.TETRIS_GRID_HEIGHT - R3.CustomCode.TETRIS_GRID_HEADSPACE); y++) { for (var x = 0; x < R3.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, R3.CustomCode.TETRIS_GRID_HEIGHT - R3.CustomCode.TETRIS_GRID_HEADSPACE - 0.5, 5 ), new THREE.Vector3( -0.5, -0.5, 5 ), new THREE.Vector3( R3.CustomCode.TETRIS_GRID_WIDTH - 0.5, -0.5, 5 ), new THREE.Vector3( R3.CustomCode.TETRIS_GRID_WIDTH - 0.5, R3.CustomCode.TETRIS_GRID_HEIGHT - R3.CustomCode.TETRIS_GRID_HEADSPACE - 0.5, 5 ) ); this.scene.instance.add( new THREE.Line( geometry, new THREE.LineBasicMaterial( { linewidth: 3, color: 0x612d1a } ) ) ); }.bind(this) R3.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 === (R3.CustomCode.TETRIS_GRID_WIDTH - 1)) { rightHit = true; } if (position.y === 0) { bottomHit = true; } if (position.y === (R3.CustomCode.TETRIS_GRID_HEIGHT - 1)) { topHit = true; } /** * Check outside of bounds */ if (position.x < 0) { collision = true; } if (position.x >= R3.CustomCode.TETRIS_GRID_WIDTH) { collision = true; } if (position.y < 0) { collision = true; } if (position.y >= R3.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) < R3.CustomCode.TETRIS_GRID_WIDTH) && ((position.x + 1) >= 0) ) { /** * But we cannot be sure y is inside bounds */ if (position.y < R3.CustomCode.TETRIS_GRID_HEIGHT && position.y >= 0) { if (this.grid[position.y][position.x + 1].value === R3.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) < R3.CustomCode.TETRIS_GRID_WIDTH) ) { /** * But we cannot be sure y is inside bounds */ if (position.y < R3.CustomCode.TETRIS_GRID_HEIGHT && position.y >= 0) { if (this.grid[position.y][position.x - 1].value === R3.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) < R3.CustomCode.TETRIS_GRID_HEIGHT) && ((position.y + 1) >= 0) ) { /** * We cannot be sure, position.x is inside bounds */ if (position.x < R3.CustomCode.TETRIS_GRID_WIDTH && position.x >= 0) { if (this.grid[position.y + 1][position.x].value === R3.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) < R3.CustomCode.TETRIS_GRID_HEIGHT) ) { /** * We cannot be sure, position.x is inside bounds */ if (position.x < R3.CustomCode.TETRIS_GRID_WIDTH && position.x >= 0) { if (this.grid[position.y - 1][position.x].value === R3.CustomCode.TETRIS_GRID_TAKEN) { /** * Ok - this block hit bottom */ bottomHit = true; } if (this.grid[position.y - 1][position.x].value === R3.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 < R3.CustomCode.TETRIS_GRID_WIDTH && position.x >= 0) && (position.y < R3.CustomCode.TETRIS_GRID_HEIGHT && position.y >= 0) ) { if (this.grid[position.y][position.x].value === R3.CustomCode.TETRIS_GRID_TAKEN) { collision = true; } } }.bind(this) ); return { left: leftHit, top: topHit, right: rightHit, bottom: bottomHit, bottomDisappearing: bottomDisappearing, collision: collision } }.bind(this) R3.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); R3.CustomCode.prototype.moveBlock = function (block, direction, units, collisionCheck) { if (R3.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); R3.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 === R3.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 === R3.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 === R3.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 === R3.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 === R3.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 === R3.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 === R3.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) R3.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) R3.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) R3.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}, (R3.CustomCode.TETRIS_GRID_HEIGHT - R3.CustomCode.TETRIS_GRID_HEADSPACE), false); this.moveBlock(block, {right: true}, R3.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) R3.CustomCode.prototype.getNextBlock = function () { this.block = this.spawnBigBlock(); R3.Event.Emit( R3.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) */ R3.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 : R3.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 */ R3.Event.Emit( R3.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 < R3.CustomCode.TETRIS_GRID_WIDTH; x++) { if ( this.grid[19][x].value === R3.CustomCode.TETRIS_GRID_TAKEN || this.grid[20][x].value === R3.CustomCode.TETRIS_GRID_TAKEN || this.grid[21][x].value === R3.CustomCode.TETRIS_GRID_TAKEN || this.grid[22][x].value === R3.CustomCode.TETRIS_GRID_TAKEN || this.grid[23][x].value === R3.CustomCode.TETRIS_GRID_TAKEN ) { this.gameOver = true; } } if (this.gameOver) { /** * End the game if game over */ R3.Event.Emit( R3.Event.GAME_OVER, { score: this.score, level: this.level, rows: this.rows } ); } else { /** * Otherwise continue */ this.getNextBlock(); } }.bind(this); /** * Clears the grid */ R3.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 < R3.CustomCode.TETRIS_GRID_HEIGHT; y++) { this.grid[y] = []; for (var x = 0; x < R3.CustomCode.TETRIS_GRID_WIDTH; x++) { this.grid[y][x] = { value : R3.CustomCode.TETRIS_GRID_NOT_TAKEN, mesh : null, baconDisappearing : null }; } } }.bind(this) R3.CustomCode.prototype.createTile = function(tileName, imageName, displace) { var apiMaterial; if (imageName) { if (displace) { apiMaterial = new R3.D3.API.Material.Phong( null, null, null, null, null, null, null, null, this.textureDisplacement, null, null, null, null, null, null, null, null, new R3.D3.API.Texture.Image( null, this[imageName] ) ) } else { apiMaterial = new R3.D3.API.Material.Phong( null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, new R3.D3.API.Texture.Image( null, this[imageName] ) ) } } else { apiMaterial = new R3.D3.API.Material.Phong(); } this[tileName] = new R3.D3.Mesh( this.graphics, new R3.D3.API.Mesh( null, new R3.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); R3.Event.Subscribe( R3.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) { R3.Event.Emit( R3.Event.REMOVE_COMPONENT, { component: this.block.center } ); } if (this.block && this.block.meshes) { this.block.meshes.map( function (mesh) { R3.Event.Emit( R3.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) ); R3.Event.Emit( R3.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(); R3.Event.Emit(R3.Event.WINDOW_RESIZE, R3.Utils.GetWindowSize()); R3.Event.Emit(R3.Event.GAME_LOADED); }.bind(this) ) //@ sourceURL=entityLoaded.js