// Cloned by Enhanced on 18 Jun 2018 from World "Revamped Space Pong" by SinfulSalad
// Please leave this clone trail here.
// Cloned by SinfulSalad on 12 Jun 2018 from World "Space Pong" by Igor Strelkov
// Please leave this clone trail here.
//-------------------------- TWEAKER'S BOX: ------------------------------------
AB.clockTick = 33; // speed of run - move things every n milliseconds
const gridsize = 101; // number of squares along side of world
const squaresize = 100; // size of square in pixels
const playersize = 1500; // size of player in pixels
const SPEED_MULTIPLIER = 1.3; //speed of the ball
const TIME_BEFORE_END = 120; //number of seconds before the time mode ends
const SCORE_NEEDED = 5; //number of points needed to win the score mode
//difficulty multiplicators for each difficulty :
//this multiplicator affect the speed of the enemy's paddle
//as well as how random the direction of it's shots is
const EASY_MODE = 1.1;
const MEDIUM_MODE = 1.5;
const HARD_MODE = 1.9;
//change the files in this array to change the background displayed by the program
const skyboxTexture = ["/uploads/starter/sky_pos_z.jpg",
"/uploads/starter/sky_neg_z.jpg",
"/uploads/starter/sky_pos_y.jpg",
"/uploads/starter/sky_neg_y.jpg",
"/uploads/starter/sky_pos_x.jpg",
"/uploads/starter/sky_neg_x.jpg"];
const SKYCOLOR = 0xffffcc; // a number, not a string
const BLANKCOLOR = SKYCOLOR ; // make objects this color until texture arrives (from asynchronous file read)
const MAXPOS = gridsize * squaresize;
const startRadiusConst = MAXPOS * 1 ; // distance from centre to start the camera at
const skyboxConst = MAXPOS * 3;
const maxRadiusConst = MAXPOS * 100 ; // maximum distance from camera we will render things
AB.maxSteps = 20000;
//-------------------------END OF TWEAKER'S BOX---------------------------------
// --- some useful random functions -------------------------------------------
function randomfloatAtoB ( A, B )
{
return ( A + ( Math.random() * (B-A) ) );
}
function randomintAtoB ( A, B )
{
return ( Math.round ( randomfloatAtoB ( A, B ) ) );
}
function randomBoolean()
{
if ( Math.random() < 0.5 ) { return false; }
else { return true; }
}
function World() {
this.endCondition = false;
var edges = [];
var fileArray = [];
var textureArray = [];
var player;
var enemy;
var ball;
var difficulty = "EASY";
var gameMode = "SCORE";
var ready = "set";
var timer = AB.clockTick*TIME_BEFORE_END;
//is used to display the final score, or the start button, or the timer
var str6 = "<p align=\"center\"><button id='startButton', style=\"height:30px;width:100px;background-color:#FF0000\"><b>START</b></button></p>";
function keyDownHandler(e)
// user control
// Note that this.takeAction(a) is constantly running at same time, redrawing the screen.
{
if (e.keyCode == 37) player.movement = -1;
if (e.keyCode == 39) player.movement = 1;
}
function keyUpHandler(e)
// user control
// Note that this.takeAction(a) is constantly running at same time, redrawing the screen.
{
if (e.keyCode == 37 && player.movement == -1) player.movement = 0;
else if (e.keyCode == 39 && player.movement == 1) player.movement = 0;
}
function initTextures()
{
fileArray.push('/uploads/strelki2/black.jpg');
fileArray.push(skyboxTexture[0]);
fileArray.push(skyboxTexture[1]);
fileArray.push(skyboxTexture[2]);
fileArray.push(skyboxTexture[3]);
fileArray.push(skyboxTexture[4]);
fileArray.push(skyboxTexture[5]);
fileArray.push("/uploads/strelki2/blue.jpg");
fileArray.push("/uploads/strelki2/pink.jpg");
fileArray.push("/uploads/strelki2/green.jpg");
textureArray = [fileArray.length];
for (let i = 0; i < fileArray.length; i++)
{
textureArray[i] = new THREE.ImageUtils.loadTexture( fileArray[i] );
}
for ( let i = 0; i < textureArray.length; i++ ) // for all textures
{
textureArray[i].minFilter = THREE.LinearFilter;
}
}
function initEdges()
{
for (var i = -gridsize*squaresize/2 ; i <= gridsize*squaresize/2; i += squaresize )
{
buildCube(i,-gridsize*squaresize/2);
buildCube(i, gridsize*squaresize/2);
buildCube(-gridsize*squaresize/2, i);
buildCube(gridsize*squaresize/2, i);
}
}
function buildCube(x, z)
{
var shape = new THREE.BoxGeometry( squaresize, squaresize, squaresize );
var cube = new THREE.Mesh( shape );
cube.position.x = x;
cube.position.z = z;
threeworld.scene.add(cube);
cube.material = new THREE.MeshBasicMaterial({ map: textureArray[0] });
edges.push(cube);
}
function initSkybox()
{
var materialArray = [
( new THREE.MeshBasicMaterial ( { map: textureArray[1], side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: textureArray[2], side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: textureArray[3], side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: textureArray[4], side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: textureArray[5], side: THREE.BackSide } ) ),
( new THREE.MeshBasicMaterial ( { map: textureArray[6], side: THREE.BackSide } ) ),
];
var skyGeometry = new THREE.CubeGeometry ( skyboxConst, skyboxConst, skyboxConst );
var skyMaterial = new THREE.MeshFaceMaterial ( materialArray );
var theskybox = new THREE.Mesh ( skyGeometry, skyMaterial );
threeworld.scene.add( theskybox ); // We are inside a giant cube
}
function initBall()
{
var sphereMaterial = new THREE.MeshLambertMaterial({color: 0xD43001});
ball = new THREE.Mesh(new THREE.SphereGeometry(100,50,50), sphereMaterial);
ball.material = new THREE.MeshBasicMaterial( { map: textureArray[7] } );
ball.position.x = 0;
ball.position.y = 0;
ball.position.z = 0;
//angle (radian), zero meaning it moves towards the players side
ball.direction = Math.PI;
//is increased each time there is contact with the ball
ball.velocity = SPEED_MULTIPLIER;
threeworld.scene.add(ball);
}
function resetBall()
{
ball.position.x = 0;
ball.position.z = 0;
ball.direction = Math.PI;
ball.velocity = SPEED_MULTIPLIER;
}
function initPaddles()
{
var shape = new THREE.BoxGeometry( playersize, squaresize, squaresize );
player = new THREE.Mesh( shape );
shape = new THREE.BoxGeometry( playersize, squaresize, squaresize );
enemy = new THREE.Mesh( shape );
player.material = new THREE.MeshBasicMaterial( { map: textureArray[8] } );
enemy.material = new THREE.MeshBasicMaterial( { map: textureArray[9] } );
player.position.x = 0;
player.position.y = 0;
player.position.z = gridsize*squaresize/2-squaresize;
player.movement = 0;
player.score = 0;
enemy.position.x = 0;
enemy.position.y = 0;
enemy.position.z = -gridsize*squaresize/2+squaresize;
enemy.movement = 0;
enemy.score = 0;
enemy.speed = 1;
threeworld.scene.add(player);
threeworld.scene.add(enemy);
}
function enemyMind()
{
if (enemy.position.x > ball.position.x+playersize/10) enemy.movement = -1;
else if (enemy.position.x < ball.position.x-playersize/10) enemy.movement = 1;
else enemy.movement = 0;
}
function processOpponentsMovement()
{
player.position.x += player.movement*squaresize;
if (player.position.x > gridsize*squaresize/2-playersize/2) player.position.x = gridsize*squaresize/2-playersize/2;
else if (player.position.x < -gridsize*squaresize/2+playersize/2) player.position.x = -gridsize*squaresize/2+playersize/2;
enemy.position.x += enemy.speed*enemy.movement*squaresize;
if (enemy.position.x > gridsize*squaresize/2-playersize/2) enemy.position.x = gridsize*squaresize/2-playersize/2;
else if (enemy.position.x < -gridsize*squaresize/2+playersize/2) enemy.position.x = -gridsize*squaresize/2+playersize/2;
}
function processBallMovement()
{
newX = ball.position.x + squaresize*ball.velocity*Math.sin(ball.direction);
newZ = ball.position.z + squaresize*ball.velocity*Math.cos(ball.direction);
//collision bottom side
if (newZ > gridsize*squaresize/2-squaresize)
{
ball.velocity += 0.1;
ball.direction = Math.PI-ball.direction;
processLoss(player);
}
//collision top side
else if (newZ < -gridsize*squaresize/2+squaresize)
{
ball.velocity += 0.1;
ball.direction = -Math.PI-ball.direction;
processLoss(enemy);
}
//collision left and right
else if (newX > gridsize*squaresize/2-squaresize || newX < -gridsize*squaresize/2+squaresize)
{
ball.velocity += 0.1;
ball.direction = -ball.direction;
}
ball.position.x += squaresize*ball.velocity*Math.sin(ball.direction);
ball.position.z += squaresize*ball.velocity*Math.cos(ball.direction);
}
function processLoss(opponent)
{
if (opponent.position.x > ball.position.x+playersize/2 || opponent.position.x < ball.position.x-playersize/2)
{
opponent.score += -1;
resetBall();
}
else
{
//let's add a little random to make it less predictable
//only happens when the enemy hits the ball
if (opponent.speed !== undefined) ball.direction += (opponent.speed/1.5+0.5)*randomfloatAtoB (-Math.PI/20, Math.PI/20);
else if (opponent.position.x > ball.position.x+playersize/4)
{
ball.direction += Math.PI/8;
}
else if (opponent.position.x < ball.position.x-playersize/4)
{
ball.direction -= Math.PI/8;
}
}
}
function updateScore()
{
var playerScore = -enemy.score;
var enemyScore = -player.score;
var str = "<p align=\"center\"><font size=\"+2\"><b>PLAYER "+playerScore+" - "+enemyScore+" ENEMY</b></font></p>";
$("#user_span5").html( str );
}
function initOptions()
{
$("#user_span1").html( "<p align=\"center\">Difficulty settings : <b>EASY</b></p>" );
var s = "<p align=\"center\"><button id='easyButton'>Easy</button> <button id='mediumButton'>Medium</button> <button id='hardButton'>Hard</button></p>";
$("#user_span2").html( s );
$("#user_span3").html( "<p align=\"center\">Mode settings : <b>SCORE</b></p>" );
s = "<p align=\"center\"><button id='scoreButton'>Score</button> <button id='timeButton'>Time</button></p>";
$("#user_span4").html( s );
$("#user_span6").html( str6 );
$("#user_span7").html( "<p align=\"center\"><font color=\"#C9C9C9\"><b>"+timer/AB.clockTick+" seconds remaining</b></font><p></b></p>" );
document.getElementById("easyButton").addEventListener("click", setToEasy);
document.getElementById("mediumButton").addEventListener("click", setToMedium);
document.getElementById("hardButton").addEventListener("click", setToHard);
document.getElementById("timeButton").addEventListener("click", setToTime);
document.getElementById("scoreButton").addEventListener("click", setToScore);
document.getElementById("startButton").addEventListener("click", startGame);
}
function updateHUD()
{
$("#user_span1").html( "<p align=\"center\">Difficulty settings : <b>"+difficulty+"</b></p>" );
$("#user_span3").html( "<p align=\"center\">Mode settings : <b>"+gameMode+"</b></p>" );
updateScore();
if (gameMode === "TIME")
{
$("#user_span7").html( "<p align=\"center\"><b>"+Math.floor(timer/AB.clockTick)+" seconds remaining</b><p></b></p>" );
}
else
{
$("#user_span7").html("<p align=\"center\"><font color=\"#C9C9C9\"><b>"+Math.floor(timer/AB.clockTick)+" seconds remaining</b></font><p></b></p>");
}
}
function setToEasy()
{
enemy.speed = EASY_MODE;
difficulty = "EASY";
}
function setToMedium()
{
enemy.speed = MEDIUM_MODE;
difficulty = "MEDIUM";
}
function setToHard()
{
enemy.speed = HARD_MODE;
difficulty = "HARD";
}
function setToTime()
{
gameMode = "TIME";
//TODO
}
function setToScore()
{
gameMode = "SCORE"
//TODO
}
function startGame()
{
console.log("start pressed");
ready = "start";
}
function endGame()
{
if (gameMode === "SCORE")
{
if (player.score == -SCORE_NEEDED || enemy.score == -SCORE_NEEDED)
{
ready = "end";
updateHUD();
if (player.score == -SCORE_NEEDED) str6 = "<p align=\"center\"><b>YOU LOSE!</b><p>";
else str6 = "<p align=\"center\"><b>YOU WIN!</b><p>";
$("#user_span6").html( str6 );
}
}
else
{
if (timer === 0)
{
ready = "end";
updateHUD();
if (player.score < enemy.score) str6 = "<p align=\"center\"><b>YOU LOSE!</b><p>";
else if (player.score > enemy.score) str6 = "<p align=\"center\"><b>YOU WIN!</b><p>";
else str6 = "<p align=\"center\"><b>IT'S A DRAW!</b><p>";
$("#user_span6").html( str6 );
}
}
}
this.newRun = function()
{
document.onkeydown = keyDownHandler;
document.onkeyup = keyUpHandler;
threeworld.init3d ( startRadiusConst, maxRadiusConst, SKYCOLOR );
initTextures();
initSkybox();
initEdges();
initPaddles();
initBall();
initOptions();
};
this.nextStep = function()
{
if (ready !== "end") updateHUD();
if (ready === "start")
{
processBallMovement();
enemyMind();
processOpponentsMovement();
endGame();
timer--;
}
};
this.endRun = function()
{
};
}