//Student Name: Robert Szocs //
//Student ID: 20722375 //
const CLOCKTICK = 100; // Speed of run: Step every n milliseconds.
const MAXSTEPS = 1000; // Length of run: Maximum length of run in steps.
const SCREENSHOT_STEP = 50;
function World() {//------------Word Start-------------
var powerUps = []; // Array to store active power-ups
var powerUpDuration = 5000; // Duration of power-up in milliseconds (5 seconds)
var freezeActive = false; // Flag to track if freeze power-up is active
var clearRowActive = false; // Flag to track if clear row power-up is active
var timeLimit = 60000; // Time limit in milliseconds (60 seconds)
var remainingTime = timeLimit;
var timerInterval;
const POWER_UP_FREEZE = 0;
const POWER_UP_CLEAR_ROW = 1;
const gridsize = 150; // length of each side
const noSquares = 10; // size of square in pixels
const MAXPOS = gridsize * noSquares; // length of one side in pixels
const MAX = 135;
const SKYCOLOR = 0x000000; // a number, not a string
const startRadiusConst = MAXPOS*0.2 ; // distance from centre to start the camera at
const maxRadiusConst = MAXPOS * 3 ; // maximum distance from camera we will render things
var grid;
var floor;
var player;
var playerX =5;
var playerZ =0;
var playerY =0;
var occupied = false;
var difficulty = 1;
var noCubes = 5 + difficulty;
var cubeHeight = difficulty;
var floorSpacesLeft;
var collided = false;
//----------------------Grid Start-------------------------
function random(lowerLimit, upperLimit){
return Math.floor(Math.random() * upperLimit) + lowerLimit;
}
//----------------------Grid Start-------------------------
function initGrid(){
grid = new THREE.GridHelper(gridsize,noSquares);//create the 2d grid on the floor.
threeworld.scene.add(grid);
grid = new Array(noSquares);
for (var x = 0; x < noSquares ; x++){//create a 3d array to store which spaces are occupied by cubes.
grid[x] = new Array(noSquares);
for (var z = 0; z < noSquares ; z++){
grid[x][z] = new Array(noSquares);
for(var y=-1; y<noSquares; y++){
grid[x][z][y] = occupied;// start by setting them all to be unoccupied.
}
}
}
floor = new Array(noSquares);//Store each cube for the floor.
for(var fx=0; fx<noSquares; fx++){
floor[fx] = new Array(noSquares);
for(var fz=0; fz<noSquares; fz++){
floor[fx][fz] = false;
}
}
}
//----------------------Grid End-------------------------
//----------------------Cube Manipulation Start-------------------------
function drawCube(size, height, x, z) {
var side = size * 2;
var geometry = new THREE.BoxGeometry(side, side * height, side);
var material = new THREE.MeshStandardMaterial({
color: 0xFFA500, // Orange color
emissive: 0xFFA500, // Emissive color also set to orange
});
var cube = new THREE.Mesh(geometry, material);
cube.position.y = (gridsize / noSquares) + ((height - 1) * size);
cube.position.z = (gridsize - size) - (side * z);
cube.position.x = (gridsize - size) - (side * x);
threeworld.scene.add(cube);
return cube;
}
function drawPlayerCube(size, height, x, z) {
var material = new THREE.MeshStandardMaterial({
color: 0x0000FF, // Blue color
emissive: 0x0000FF, // Emissive color also set to blue
});
var cube = drawCube(size, height, x, z);
cube.material = material;
threeworld.scene.add(cube);
player = cube;
}
function randomCube(y,height){//randomise the position of each cube.
var size = 15;
if(height >= 10){
height = random(1,10);
}
var x = random(0,10);
var z = random(0,10);
var cube = drawCube(size,height,x,z);
cube.position.y = cube.position.y + (y*30);
grid[x][z][y] = cube;
}
function spawnPowerUp(x, z, y) {
var size = 15;
var geometry = new THREE.BoxGeometry(size, size, size);
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // Green color for power-ups
var cube = new THREE.Mesh(geometry, material);
cube.position.y = cube.position.y + (y * 30);
cube.position.z = (gridsize - size) - (size * z);
cube.position.x = (gridsize - size) - (size * x);
threeworld.scene.add(cube);
powerUps.push({ cube: cube, type: randomPowerUpType() });
}
function spawnCube(y, cubeNo,cubeHeight){//spawn in cubes.
for(var i=0; i<cubeNo; i++)
randomCube(y,cubeHeight);
}
function move(){//moves all falling cubes down and if they hit the floor, change their color.
for (var x = 0; x < noSquares ; x++){
for (var z = 0; z < noSquares ; z++){
for(var y=-1; y<noSquares; y++){
if(grid[x][z][-1] != occupied){
grid[x][z][-1].material = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true});
floor[x][z] = true;
}
if((grid[x][z][y] != occupied) && (y>=0)){
grid[x][z][y].position.y = grid[x][z][y].position.y - 30;
grid[x][z][y-1] = grid[x][z][y];
grid[x][z][y] = occupied;
}
}
}
}
}
function isFloorFull(){//returns the number of squares on the floor left to fill.
var fullFloor = noSquares*noSquares;
for(var x=0; x<noSquares; x++){
for(var z=0; z<noSquares; z++){
if(floor[x][z] === true){
fullFloor--;
}
}
}
return fullFloor;
}
//----------------------Cube Manipulation End-------------------------
//--------------Controls start-----------------
function handleKeyDown (event){
var code = event.keyCode;
if (code == 37){ // left
if(player.position.x <= -MAX){
//console.log("x: "+player.position.x) ;
}else{
playerX--;
spawnCube(4,noCubes,cubeHeight);
move();
moveSound();
player.position.x = player.position.x -30;
}
}
if (code == 38){ // right == up (based on inital camera position)
if(player.position.z <= -MAX){
//console.log("z: "+player.position.z) ;
}else{
playerZ++;
spawnCube(4,noCubes,cubeHeight);
move();
moveSound();
player.position.z = player.position.z -30;
}
}
if (code == 39){ // up == right (based on inital camera position)
if(player.position.x >= MAX){
//console.log("x: "+player.position.x) ;
}else{
playerX++;
spawnCube(4,noCubes,cubeHeight);
move();
moveSound();
player.position.x = player.position.x +30;
}
}
if (code == 40){ // back
if(player.position.z >= MAX){
// console.log("z: "+player.position.z) ;
}else{
playerZ--;
spawnCube(4,noCubes,cubeHeight);
move();
moveSound();
player.position.z = player.position.z +30;
}
}
}
//--------------Controls End-----------------
function gameOver(){//When the game ends, remove instructions and say if they won/lost.
var s = "<h2> </h2>";
$("#user_span1").html( s );
var text = "";
$("#user_span3").text( text );
if(collided === true){
var s = "<font color=red><center> <h1> You Lose! </h1> </center></font>";
$("#user_span1").html( s );
}else{
var s = "<font color=green><center> <h1> You Win! </h1> </center></font>";
$("#user_span1").html( s );
}
for (var x = 0; x < noSquares ; x++){
for (var z = 0; z < noSquares ; z++){
for(var y=0; y<noSquares; y++){
threeworld.scene.remove(grid[x][z][y]);// remove all cubes in the air.
}
}
}
threeworld.scene.remove(player);//remove the player from the scene so they dont try to keep playing.
}
function initInstructions(){//display instructions
var s = "<center> <strong>Instructions:</strong>Use arrow keys to move, each time you move so do the falling blocks... don't get hit!<hr><strong>Aim:</strong> to fill the floor with boxes. </center>";
$("#user_span1").html( s );
}
function printDetails() {
floorSpaceLeft = isFloorFull();
text = "Floor Spaces Left: " + floorSpaceLeft + " | Time Left: " + Math.floor(remainingTime / 1000) + "s";
$("#user_span3").text(text);
}
//----------------------Running Functions Start-------------------------
this.endCondition;
this.newRun = function()
{
this.endCondition = false;
if ( true )
{
threeworld.init3d ( startRadiusConst,maxRadiusConst, SKYCOLOR );//init 3d world
document.addEventListener( 'keydown', handleKeyDown );//add arrow key listeners
initMusic();//start music.
initGrid();//init the grids
initInstructions();//display instructions.
drawPlayerCube(15,1,playerX,playerZ);//Draw the player cube.
}
// Start the timer
timerInterval = setInterval(function() {
remainingTime -= 1000; // Reduce by 1 second
if (remainingTime <= 0) {
clearInterval(timerInterval);
gameOver();
}
}, 1000);
};
this.getState = function()
{
state = true;
return ( state ); // State format defined by this World.
};
this.nextStep = function()
{
var action = 4;
if ( true ){
printDetails();
if(grid[playerX][playerZ][playerY] != occupied){//if a falling cube && the player are in the same space, end the game
collided = true;
this.endCondition = true;
}
}
if(isFloorFull() === 0){//if the floor is full, end the game.
this.endCondition = true;
}
};
this.endRun = function()
{
if(true){
if(this.endCondition===true){
if((isFloorFull() === 0) || (collided == true)){
gameOver();
}
}
}
};
this.getScore = function()
{
return (isFloorFull());
};
//----------------------Running Functions End-------------------------
}//------------World End-------------
function initMusic(){//init the background music
var x="<audio id=gameSound src=/uploads/oneilf27/dark-techno-city.mp3 autoplay >";
$("#user_span6").html( x );
}
function moveSound(){
x = "</audio><audio id=moveSound src=/uploads/oneilf27/beepmult.mp3 autoplay > </audio>";
$("#user_span5").html( x );
}