games and custom themes and shit
83
2drocketleague/README.md
Normal file
@ -0,0 +1,83 @@
|
||||
<img src="assets/rocket-league-header.png" align="left" style="background:black; height:100px " />
|
||||
<img src="assets/2d_white1.png" style="background:black; height: 35px; top:30px; position:relative" />
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
# ROCKET LEAGUE 2D v0.9
|
||||
##(https://github.com/skempisty/rocket_league_2d)
|
||||
### Author: Stephen Kempisty
|
||||
|
||||
==========
|
||||
|
||||
## Introduction
|
||||
|
||||
Welcome to Rocket League 2D! Your favorite rocket powered battle car socCAR game in top down form! Find the full game online for free at:
|
||||
|
||||
<a>http://skempisty.github.io/rocket_league_2d/</a>
|
||||
|
||||
Development is ongoing, and many more features such as curved arena corners, boost pickups, multiple car models, and player registration/rankings are coming soon!
|
||||
|
||||
## Controls
|
||||
|
||||
#### Player 1 (Orange):
|
||||
- W = Accelerate
|
||||
- S = Brake/Reverse
|
||||
- A = Turn Left
|
||||
- D = Turn Right
|
||||
|
||||
#### Player 2 (Blue):
|
||||
- Up Arrow = Accelerate
|
||||
- Down Arrow = Brake/Reverse
|
||||
- Left Arrow = Turn Left
|
||||
- Right Arrow = Turn Right
|
||||
|
||||
## Game Flow
|
||||
|
||||
<img src="assets/rocket_league_2d_ss.png" />
|
||||
|
||||
Begin playing Rocket League 2D by pressing the start button after the game loads.
|
||||
|
||||
The game timer starts at 5:00. Try to score as many goals against your opponent as you can in that time to win the game! Simple and fun!
|
||||
|
||||
|
||||
## Technologies
|
||||
|
||||
Rocket League 2D runs completely in the browser with no installation required. Technologies used in production include:
|
||||
|
||||
|
||||
- HTML
|
||||
- CSS
|
||||
- Javascript
|
||||
- jQuery
|
||||
- Canvas
|
||||
|
||||
## Design
|
||||
|
||||
The general design approach taken for Rocket League 2D (RL2d) started with a focus on the minimum viable product (MVP). Coding basic features such as movement, collision detection, basic physics, scoring, and a timer was the first goal.
|
||||
|
||||
Once a MVP had been completed, some advanced features such as sound effects, car models, and refined collision physics could be completed.
|
||||
|
||||
RL2d development emphasized throwbacks to the original game on Ps4/Xbox One/PC. Sound effects come straight from Rocket League's sound files, and the aesthetic design was based on the aesthetics of the original Rocket League.
|
||||
|
||||
## Get Started
|
||||
|
||||
No installation is required for RL2d! Simply navigate to the following link and play away!
|
||||
|
||||
<a>http://skempisty.github.io/rocket_league_2d/</a>
|
||||
|
||||
If you would like to contribute to further development of RL2d, feel free to fork this repository. Permission to snoop around in the code is given whole-heartedly!
|
||||
|
||||
|
||||
## Next Steps
|
||||
There are many exciting features planned that unfortunately did not make it into the release version of RL2d. Please check back for future versions. New features such as the following are coming soon!
|
||||
|
||||
- Car to Car collisions
|
||||
- Curved arena corners
|
||||
- Ball graphic and rolling animation
|
||||
- Boost pickups and usage
|
||||
- Improved goal interaction/animation
|
||||
- Improved/varied car models
|
||||
- Player registration
|
||||
- Player rankings
|
||||
|
BIN
2drocketleague/assets/.DS_Store
vendored
Normal file
BIN
2drocketleague/assets/2000px-Soccer_field_-_empty.svg.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
2drocketleague/assets/2d_white1.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
2drocketleague/assets/Car.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
2drocketleague/assets/Car_blue.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
2drocketleague/assets/Car_orange.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
2drocketleague/assets/Planer-Regular-webfont.ttf
Executable file
BIN
2drocketleague/assets/RLball.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
2drocketleague/assets/ball-hit.ogg
Normal file
BIN
2drocketleague/assets/ball-wall-hit.ogg
Normal file
BIN
2drocketleague/assets/fieldbackground.jpg
Normal file
After Width: | Height: | Size: 654 KiB |
BIN
2drocketleague/assets/game-over.ogg
Normal file
BIN
2drocketleague/assets/goal_horn.ogg
Normal file
BIN
2drocketleague/assets/goal_impact.ogg
Normal file
BIN
2drocketleague/assets/ready-set-go.ogg
Normal file
BIN
2drocketleague/assets/rocket-league-header.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
2drocketleague/assets/rocket_league_2d_ss.png
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
2drocketleague/assets/timer-running-out.ogg
Normal file
BIN
2drocketleague/assets/two-minute-warning.ogg
Normal file
231
2drocketleague/css/main.css
Normal file
@ -0,0 +1,231 @@
|
||||
|
||||
body{
|
||||
background: url(../assets/fieldbackground.jpg);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'planerregular';
|
||||
src: url('Planer-Regular-webfont.eot');
|
||||
src: url('Planer-Regular-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('../assets/Planer-Regular-webfont.ttf') format('truetype'),
|
||||
url('Planer-Regular-webfont.svg#planerregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: blue;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
canvas {
|
||||
position: relative;
|
||||
border: solid 3px white;
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
display: block;
|
||||
background: url(../assets/2000px-Soccer_field_-_empty.svg.png);
|
||||
background-size: 109.7% 107.7%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
z-index: -1
|
||||
}
|
||||
|
||||
.center {
|
||||
position: relative;
|
||||
width: 70%;
|
||||
margin: -5px auto;
|
||||
text-align: center;
|
||||
height: 60%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: inline-block;
|
||||
height: 100px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.twod-logo {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -30px;
|
||||
height: 35px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.scoreboard {
|
||||
position: relative;
|
||||
top: -20px;
|
||||
display: inline-block;
|
||||
height: 50px;
|
||||
width: 60px;
|
||||
border: solid 4px black;
|
||||
font-size: 300%;
|
||||
text-align: center;
|
||||
font-family: 'planerregular';
|
||||
color: white;
|
||||
text-shadow: 2px 2px black;;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.orange {
|
||||
background: orange;
|
||||
border-left: solid 2px white;
|
||||
border-bottom: solid 2px white;
|
||||
border-top: solid 2px white;
|
||||
}
|
||||
|
||||
.blue {
|
||||
background: blue;
|
||||
border-right: solid 2px white;
|
||||
border-bottom: solid 2px white;
|
||||
border-top: solid 2px white;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
width: 0px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.logo-timer {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
background: black;
|
||||
padding: 0px 30px 0px 30px;
|
||||
border-radius: 5%;
|
||||
}
|
||||
|
||||
.count-down {
|
||||
position: relative;
|
||||
width: 324px;
|
||||
height: 75px;
|
||||
top: -25px;
|
||||
border-radius: 5%;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
background: black;
|
||||
display: inline-block;
|
||||
color: white;
|
||||
font-size: 400%;
|
||||
font-family: 'planerregular';
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.game-over {
|
||||
|
||||
position: absolute;
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
background: gray;
|
||||
left: 50%;
|
||||
top: 55%;
|
||||
margin-top: -250px;
|
||||
margin-left: -250px;
|
||||
border-radius: 10%;
|
||||
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.play-again {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 20px;
|
||||
margin-left: -100px;
|
||||
width: 200px;
|
||||
background-color: yellow; /* Green */
|
||||
/*border: none;*/
|
||||
color: black;
|
||||
padding: 15px 32px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 25px;
|
||||
font-family: 'planerregular';
|
||||
border-radius: 10%;
|
||||
}
|
||||
|
||||
.winner-announce {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 40px;
|
||||
margin-left: -200px;
|
||||
width: 400px;
|
||||
height: 250px;
|
||||
text-align: center;
|
||||
font-size: 100px;
|
||||
font-family: 'planerregular';
|
||||
}
|
||||
|
||||
.start-button {
|
||||
background: green;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 75%;
|
||||
font-family: planerregular;
|
||||
color: white;
|
||||
font-size: 225%;
|
||||
padding: 10px;
|
||||
border: solid white 2px;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
font-family: planerregular;
|
||||
position: absolute;
|
||||
height: 200px;
|
||||
width: 500px;
|
||||
margin-left: -260px;
|
||||
left: 50%;
|
||||
top: 125px;
|
||||
color: white;
|
||||
background: rgba(0,0,0,.6);
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.controls {
|
||||
font-size: 200%;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.car-image {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.car-image img {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
#orange-controls {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
#controls-text {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 35%;
|
||||
margin: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
#blue-controls {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
|
82
2drocketleague/index.html
Normal file
@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<script src="/js/all.js"></script>
|
||||
<title>Rocket League 2d</title>
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<script src="https://code.jquery.com/jquery-2.2.3.js" integrity="sha256-laXWtGydpwqJ8JA+X9x2miwmaiKhn8tVmOVEigRNtP4=" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.2.1/math.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<audio src="assets/goal_impact.ogg" class="goal-impact"></audio>
|
||||
<audio src="assets/goal_horn.ogg" class="goal-horn"></audio>
|
||||
<audio src="assets/ball-hit.ogg" class="ball-hit"></audio>
|
||||
<audio src="assets/two-minute-warning.ogg" class="two-minute-warning"></audio>
|
||||
<audio src="assets/timer-running-out.ogg" class="timer-running-out"></audio>
|
||||
<audio src="assets/game-over.ogg" class="game-over"></audio>
|
||||
|
||||
<!-- ScoreBoard and Timer -->
|
||||
<div>
|
||||
<div class="center">
|
||||
<div class="scoreboard orange"></div>
|
||||
<div class="spacer"></div>
|
||||
<div class="logo-timer">
|
||||
<img class="logo" src="assets/rocket-league-header.png" alt="">
|
||||
<img class="twod-logo" src="assets/2d_white1.png" alt="">
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="scoreboard blue"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start Match Button -->
|
||||
<div class="start-button">
|
||||
Start Match
|
||||
</div>
|
||||
|
||||
<!-- Play Instructions -->
|
||||
<div class="instructions">
|
||||
<div class="controls">
|
||||
Controls
|
||||
</div>
|
||||
<div id="control-diagram">
|
||||
<div class="car-image">
|
||||
<img src="assets/Car_orange.png" alt="">
|
||||
</div>
|
||||
<div id="orange-controls">
|
||||
<p>W</p>
|
||||
<p>S</p>
|
||||
<p>A</p>
|
||||
<p>D</p>
|
||||
</div>
|
||||
<div id="controls-text">
|
||||
<p>Accelerate</p>
|
||||
<p>Brake/Reverse</p>
|
||||
<p>Turn Left</p>
|
||||
<p>Turn Right</p>
|
||||
</div>
|
||||
<div id="blue-controls">
|
||||
<p>↑</p>
|
||||
<p>↓</p>
|
||||
<p>←</p>
|
||||
<p>→</p>
|
||||
</div>
|
||||
<div class="car-image">
|
||||
<img src="assets/Car_blue.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pop up on Game Over -->
|
||||
<div class="game-over hidden">
|
||||
<div class="winner-announce"></div>
|
||||
<button class="play-again">Play Again?</button>
|
||||
</div>
|
||||
|
||||
<script src="js/main.js"></script>
|
||||
<script src="js/collisions.js"></script>
|
||||
<script src="js/car_wall_collision.js"></script>
|
||||
</body>
|
||||
</html>
|
71
2drocketleague/js/car_wall_collision.js
Normal file
@ -0,0 +1,71 @@
|
||||
function carWallCollisionDetect() {
|
||||
|
||||
for (var i=0; i<players.length; i++) {
|
||||
var sinTheta = Math.sin(players[i].rot*Math.PI/180);
|
||||
var cosTheta = Math.cos(players[i].rot*Math.PI/180);
|
||||
|
||||
|
||||
//Actually SouthEast corner on canvas
|
||||
players[i].southEastCorner = [players[i].xMid + ((players[i].width/2)*cosTheta) - ((players[i].height/2)*sinTheta),
|
||||
players[i].yMid + ((players[i].width/2)*sinTheta) + ((players[i].height/2)*cosTheta)
|
||||
];
|
||||
|
||||
//Actually SouthWest corner on canvas
|
||||
players[i].southWestCorner = [players[i].xMid + ((-players[i].width/2)*cosTheta) - ((players[i].height/2)*sinTheta),
|
||||
players[i].yMid + ((-players[i].width/2)*sinTheta) + ((players[i].height/2)*cosTheta)
|
||||
];
|
||||
|
||||
//Actually NorthEast corner on canvas
|
||||
players[i].northEastCorner = [players[i].xMid + ((players[i].width/2)*cosTheta) - ((-players[i].height/2)*sinTheta),
|
||||
players[i].yMid + ((players[i].width/2)*sinTheta) + ((-players[i].height/2)*cosTheta)
|
||||
];
|
||||
|
||||
|
||||
//Actually NorthWest corner on canvas
|
||||
players[i].northWestCorner = [players[i].xMid + ((-players[i].width/2)*cosTheta) - ((-players[i].height/2)*sinTheta),
|
||||
players[i].yMid + ((- players[i].width/2)*sinTheta) + ((-players[i].height/2)*cosTheta)
|
||||
];
|
||||
|
||||
players[i].arrayX = [players[i].northEastCorner[0],
|
||||
players[i].northWestCorner[0],
|
||||
players[i].southEastCorner[0],
|
||||
players[i].southWestCorner[0]
|
||||
];
|
||||
players[i].arrayY = [players[i].northEastCorner[1],
|
||||
players[i].northWestCorner[1],
|
||||
players[i].southEastCorner[1],
|
||||
players[i].southWestCorner[1]
|
||||
];
|
||||
|
||||
// Check X values
|
||||
for (var j=0; j < players[i].arrayX.length; j++) {
|
||||
if (players[i].arrayX[j] >= CANVAS_WIDTH) {
|
||||
while (players[i].arrayX[j] >= CANVAS_WIDTH) {
|
||||
players[i].xMid -= 2;
|
||||
carWallCollisionDetect();
|
||||
}
|
||||
}
|
||||
if (players[i].arrayX[j] <= 0) {
|
||||
while (players[i].arrayX[j] <= 0) {
|
||||
players[i].xMid += 2;
|
||||
carWallCollisionDetect();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check Y values
|
||||
for (var j=0; j < players[i].arrayY.length; j++) {
|
||||
if (players[i].arrayY[j] >= CANVAS_HEIGHT) {
|
||||
while (players[i].arrayY[j] >= CANVAS_HEIGHT) {
|
||||
players[i].yMid -= 2;
|
||||
carWallCollisionDetect();
|
||||
}
|
||||
}
|
||||
if (players[i].arrayY[j] <= 0) {
|
||||
while (players[i].arrayY[j] <= 0) {
|
||||
players[i].yMid += 2;
|
||||
carWallCollisionDetect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
434
2drocketleague/js/collisions.js
Normal file
@ -0,0 +1,434 @@
|
||||
Math.roundTo = function(place, value) {
|
||||
return Math.round(value * place) / place;
|
||||
}
|
||||
|
||||
// PASS IN players[], returns perpendicular distance of both players from face to ball center
|
||||
function frontFaceToBallCalc(playerArray) {
|
||||
var distVect = [];
|
||||
var distMag = [];
|
||||
for (var i=0; i < playerArray.length; i++) {
|
||||
var frontFaceVector = [playerArray[i].arrayX[0] - playerArray[i].arrayX[1], playerArray[i].arrayY[0] - playerArray[i].arrayY[1]];
|
||||
var frontFaceMag = playerArray[i].width;
|
||||
var frontFacePtv = [ball.x - playerArray[i].arrayX[1], ball.y - playerArray[i].arrayY[1]];
|
||||
var unitFrontFaceVector=[];
|
||||
var projFrontVect=[];
|
||||
var closest=[];
|
||||
|
||||
for (var j=0; j<2; j++) {
|
||||
unitFrontFaceVector[j] = frontFaceVector[j]/frontFaceMag;
|
||||
}
|
||||
|
||||
var projFrontMag = math.dot(frontFacePtv, unitFrontFaceVector);
|
||||
|
||||
if (projFrontMag < 0) {
|
||||
closest = [playerArray[i].arrayX[0], playerArray[i].arrayY[0]];
|
||||
} else if (projFrontMag > frontFaceMag) {
|
||||
closest = [playerArray[i].arrayX[1], playerArray[i].arrayY[1]];
|
||||
} else {
|
||||
for (var j=0; j<2; j++) {
|
||||
projFrontVect[j] = projFrontMag*unitFrontFaceVector[j];
|
||||
}
|
||||
closest = [playerArray[i].arrayX[1] + projFrontVect[0] , playerArray[i].arrayY[1] + projFrontVect[1]];
|
||||
}
|
||||
|
||||
distVect[i] = [ball.x - closest[0], ball.y - closest[1]];
|
||||
distMag[i] = Math.hypot(distVect[i][0], distVect[i][1]);
|
||||
|
||||
}
|
||||
return [distMag[0], distMag[1]];
|
||||
}
|
||||
|
||||
// PASS IN output from frontFaceToBallCalc(), returns nothing, affects speed/direction of ball if impacted by a car
|
||||
function carFrontBallCollision(outputFromFrontFaceToBallCalc) {
|
||||
for (var i=0; i < 2; i++) {
|
||||
var frontFaceResult = outputFromFrontFaceToBallCalc[i];
|
||||
|
||||
// IF CONTACT OCCURS
|
||||
if (frontFaceResult < ball.radius) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + 1.5*players[i].vel));
|
||||
|
||||
if(velMag < players[i].vel) velMag = players[i].vel + 2;
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle + Math.PI/2;
|
||||
|
||||
ball.velX = -1*velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -1*velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -2*velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -2*velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PASS IN players[], returns perpendicular distance of both players from face to ball center
|
||||
function rightFaceToBallCalc(playerArray) {
|
||||
var distVect = [];
|
||||
var distMag = [];
|
||||
for (var i=0; i < playerArray.length; i++) {
|
||||
var rightFaceVector = [playerArray[i].arrayX[2] - playerArray[i].arrayX[0], playerArray[i].arrayY[2] - playerArray[i].arrayY[0]];
|
||||
var rightFaceMag = playerArray[i].height;
|
||||
var rightFacePtv = [ball.x - playerArray[i].arrayX[0], ball.y - playerArray[i].arrayY[0]];
|
||||
var unitRightFaceVector=[];
|
||||
var projRightVect=[];
|
||||
var closest=[];
|
||||
|
||||
for (var j=0; j<2; j++) {
|
||||
unitRightFaceVector[j] = rightFaceVector[j]/rightFaceMag;
|
||||
}
|
||||
|
||||
var projRightMag = math.dot(rightFacePtv, unitRightFaceVector);
|
||||
|
||||
if (projRightMag < 0) {
|
||||
closest = [playerArray[i].arrayX[2], playerArray[i].arrayY[2]];
|
||||
} else if (projRightMag > rightFaceMag) {
|
||||
closest = [playerArray[i].arrayX[0], playerArray[i].arrayY[0]];
|
||||
} else {
|
||||
for (var j=0; j<2; j++) {
|
||||
projRightVect[j] = projRightMag*unitRightFaceVector[j];
|
||||
}
|
||||
closest = [playerArray[i].arrayX[0] + projRightVect[0] , playerArray[i].arrayY[0] + projRightVect[1]];
|
||||
}
|
||||
|
||||
distVect[i] = [ball.x - closest[0], ball.y - closest[1]];
|
||||
distMag[i] = Math.hypot(distVect[i][0], distVect[i][1]);
|
||||
|
||||
}
|
||||
return [distMag[0], distMag[1]];
|
||||
}
|
||||
|
||||
// PASS IN output from rightFaceToBallCalc(), returns nothing, affects speed/direction of ball if impacted by a car
|
||||
function carRightBallCollision(outputFromRightFaceToBallCalc) {
|
||||
for (var i=0; i < 2; i++) {
|
||||
var rightFaceResult = outputFromRightFaceToBallCalc[i];
|
||||
|
||||
// IF CONTACT OCCURS
|
||||
if (rightFaceResult < ball.radius) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle + Math.PI;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
// CHANGE PLAYER SPEED REDUCTION AFTER HIT */
|
||||
players[i].vel *= .9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PASS IN players[], returns perpendicular distance of both players from face to ball center
|
||||
function leftFaceToBallCalc(playerArray) {
|
||||
var distVect = [];
|
||||
var distMag = [];
|
||||
for (var i=0; i < playerArray.length; i++) {
|
||||
var leftFaceVector = [playerArray[i].arrayX[1] - playerArray[i].arrayX[3], playerArray[i].arrayY[1] - playerArray[i].arrayY[3]];
|
||||
var leftFaceMag = playerArray[i].height;
|
||||
var leftFacePtv = [ball.x - playerArray[i].arrayX[3], ball.y - playerArray[i].arrayY[3]];
|
||||
var unitLeftFaceVector=[];
|
||||
var projLeftVect=[];
|
||||
var closest=[];
|
||||
|
||||
for (var j=0; j<2; j++) {
|
||||
unitLeftFaceVector[j] = leftFaceVector[j]/leftFaceMag;
|
||||
}
|
||||
|
||||
var projLeftMag = math.dot(leftFacePtv, unitLeftFaceVector);
|
||||
|
||||
if (projLeftMag < 0) {
|
||||
closest = [playerArray[i].arrayX[1], playerArray[i].arrayY[1]];
|
||||
} else if (projLeftMag > leftFaceMag) {
|
||||
closest = [playerArray[i].arrayX[3], playerArray[i].arrayY[3]];
|
||||
} else {
|
||||
for (var j=0; j<2; j++) {
|
||||
projLeftVect[j] = projLeftMag*unitLeftFaceVector[j];
|
||||
}
|
||||
closest = [playerArray[i].arrayX[3] + projLeftVect[0] , playerArray[i].arrayY[3] + projLeftVect[1]];
|
||||
}
|
||||
|
||||
distVect[i] = [ball.x - closest[0], ball.y - closest[1]];
|
||||
distMag[i] = Math.hypot(distVect[i][0], distVect[i][1]);
|
||||
|
||||
}
|
||||
return [distMag[0], distMag[1]];
|
||||
}
|
||||
|
||||
// PASS IN output from leftFaceToBallCalc(), returns nothing, affects speed/direction of ball if impacted by a car
|
||||
function carLeftBallCollision(outputFromLeftFaceToBallCalc) {
|
||||
for (var i=0; i < 2; i++) {
|
||||
var leftFaceResult = outputFromLeftFaceToBallCalc[i];
|
||||
|
||||
// IF CONTACT OCCURS
|
||||
if (leftFaceResult < ball.radius) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
// CHANGE PLAYER SPEED REDUCTION AFTER HIT */
|
||||
players[i].vel *= .9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PASS IN players[], returns perpendicular distance of both players from face to ball center
|
||||
function bottomFaceToBallCalc(playerArray) {
|
||||
var distVect = [];
|
||||
var distMag = [];
|
||||
for (var i=0; i < playerArray.length; i++) {
|
||||
var bottomFaceVector = [playerArray[i].arrayX[2] - playerArray[i].arrayX[3], playerArray[i].arrayY[2] - playerArray[i].arrayY[3]];
|
||||
var bottomFaceMag = playerArray[i].width;
|
||||
var bottomFacePtv = [ball.x - playerArray[i].arrayX[3], ball.y - playerArray[i].arrayY[3]];
|
||||
var unitBottomFaceVector=[];
|
||||
var projBottomVect=[];
|
||||
var closest=[];
|
||||
|
||||
for (var j=0; j<2; j++) {
|
||||
unitBottomFaceVector[j] = bottomFaceVector[j]/bottomFaceMag;
|
||||
}
|
||||
|
||||
var projBottomMag = math.dot(bottomFacePtv, unitBottomFaceVector);
|
||||
|
||||
if (projBottomMag < 0) {
|
||||
closest = [playerArray[i].arrayX[2], playerArray[i].arrayY[2]];
|
||||
} else if (projBottomMag > bottomFaceMag) {
|
||||
closest = [playerArray[i].arrayX[3], playerArray[i].arrayY[3]];
|
||||
} else {
|
||||
for (var j=0; j<2; j++) {
|
||||
projBottomVect[j] = projBottomMag*unitBottomFaceVector[j];
|
||||
}
|
||||
closest = [playerArray[i].arrayX[3] + projBottomVect[0] , playerArray[i].arrayY[3] + projBottomVect[1]];
|
||||
}
|
||||
|
||||
distVect[i] = [ball.x - closest[0], ball.y - closest[1]];
|
||||
distMag[i] = Math.hypot(distVect[i][0], distVect[i][1]);
|
||||
|
||||
}
|
||||
return [distMag[0], distMag[1]];
|
||||
}
|
||||
|
||||
// PASS IN output from bottomFaceToBallCalc(), returns nothing, affects speed/direction of ball if impacted by a car
|
||||
function carBottomBallCollision(outputFromBottomFaceToBallCalc) {
|
||||
for (var i=0; i < 2; i++) {
|
||||
var bottomFaceResult = outputFromBottomFaceToBallCalc[i];
|
||||
|
||||
// IF CONTACT OCCURS
|
||||
if (bottomFaceResult < ball.radius) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
if(velMag < players[i].vel) velMag = players[i].vel + 2;
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle - Math.PI/2;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -2*velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -2*velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CORNER HIT DETECTION */
|
||||
|
||||
// INPUT is the corner in array form [players[i].northEastCorner[0], players[i].northEastCorner[1]]
|
||||
// OUTPUT true of false depending on corner collision detected
|
||||
function testCornerInBall(corner) {
|
||||
// Uses equation of a circle to calculate if corner lies within the ball
|
||||
if (Math.pow(corner[0] - ball.x, 2) + Math.pow(corner[1] - ball.y, 2) < Math.pow(ball.radius, 2)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function intersectPlayers(player1CornerArray, player2CornerArray) {
|
||||
|
||||
}
|
||||
|
||||
/* CORNER HIT RESPONSE */
|
||||
|
||||
function northEastCornerHit() {
|
||||
for (var i=0; i< players.length; i++) {
|
||||
// DEFINES the northeast corner for both players
|
||||
var corner = [players[i].arrayX[0], players[i].arrayY[0]];
|
||||
if (testCornerInBall(corner) === true) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle + Math.PI*3/4;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function northWestCornerHit() {
|
||||
for (var i=0; i< players.length; i++) {
|
||||
// DEFINES the northwest corner for both players
|
||||
var corner = [players[i].arrayX[1], players[i].arrayY[1]];
|
||||
if (testCornerInBall(corner) === true) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle + Math.PI/4;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function southEastCornerHit() {
|
||||
for (var i=0; i< players.length; i++) {
|
||||
// DEFINES the southeast corner for both players
|
||||
var corner = [players[i].arrayX[2], players[i].arrayY[2]];
|
||||
if (testCornerInBall(corner) === true) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle - Math.PI*3/4;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function southWestCornerHit() {
|
||||
for (var i=0; i< players.length; i++) {
|
||||
// DEFINES the southwest corner for both players
|
||||
var corner = [players[i].arrayX[3], players[i].arrayY[3]];
|
||||
if (testCornerInBall(corner) === true) {
|
||||
$('.ball-hit').trigger("play");
|
||||
var velMag;
|
||||
var turnAngle = players[i].rot*Math.PI/180;
|
||||
var bounceAngle = Math.atan(ball.velY / (ball.velX + players[i].vel));
|
||||
|
||||
velMag = Math.hypot(ball.velY, (ball.velX + players[i].vel));
|
||||
|
||||
var resultAngle = turnAngle + bounceAngle - Math.PI/4;
|
||||
|
||||
ball.velX = -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.velY = -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
|
||||
ball.x += -velMag * Math.roundTo(100000, Math.cos(resultAngle));
|
||||
ball.y += -velMag * Math.roundTo(100000, Math.sin(resultAngle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ballWallCollisionDetect(bound) {
|
||||
if (ball.x + ball.radius >= CANVAS_WIDTH) {
|
||||
////////////////////////////////////////////////////////////
|
||||
// GOAL LOGIC AND RESPONSE -- BLUE GOAL (RIGHT)
|
||||
////////////////////////////////////////////////////////////
|
||||
if (ball.y + ball.radius <= CANVAS_HEIGHT - bound && ball.y - ball.radius >= bound) {
|
||||
|
||||
// GIVE POINT
|
||||
scoreOrange++;
|
||||
$('.orange').text(scoreOrange);
|
||||
// CUE CELEBRATION ANIMATION
|
||||
$('.goal-impact').trigger("play");
|
||||
$('.goal-horn').trigger("play");
|
||||
// RESET STATE
|
||||
resetGame();
|
||||
|
||||
} else {
|
||||
while (ball.x + ball.radius >= CANVAS_WIDTH) {
|
||||
ball.x -= 2;
|
||||
}
|
||||
ball.velX = -ball.velX;
|
||||
ball.velX += .5;
|
||||
}
|
||||
}
|
||||
if (ball.x - ball.radius <= 0) {
|
||||
////////////////////////////////////////////////////////////
|
||||
// GOAL LOGIC AND RESPONSE -- ORANGE GOAL (LEFT)
|
||||
////////////////////////////////////////////////////////////
|
||||
if (ball.y + ball.radius <= CANVAS_HEIGHT - bound && ball.y - ball.radius >= bound) {
|
||||
|
||||
// GIVE POINT
|
||||
scoreBlue++;
|
||||
$('.blue').text(scoreBlue);
|
||||
// CUE CELEBRATION ANIMATION
|
||||
$('.goal-impact').trigger("play");
|
||||
$('.goal-horn').trigger("play");
|
||||
// RESET STATE
|
||||
resetGame();
|
||||
|
||||
} else {
|
||||
|
||||
while (ball.x - ball.radius <= 0) {
|
||||
ball.x += 2;
|
||||
}
|
||||
ball.velX = -ball.velX;
|
||||
ball.velX -= .5;
|
||||
}
|
||||
}
|
||||
if (ball.y + ball.radius >= CANVAS_HEIGHT) {
|
||||
while (ball.y + ball.radius >= CANVAS_HEIGHT) {
|
||||
ball.y -= 2;
|
||||
}
|
||||
ball.velY = -ball.velY;
|
||||
ball.velY += .5;
|
||||
}
|
||||
if (ball.y - ball.radius <= 0) {
|
||||
while (ball.y - ball.radius <= 0) {
|
||||
ball.y += 2;
|
||||
}
|
||||
ball.velY = -ball.velY;
|
||||
ball.velY -= .5;
|
||||
}
|
||||
}
|
||||
|
322
2drocketleague/js/main.js
Normal file
@ -0,0 +1,322 @@
|
||||
// SET CANVAS SIZE AND APPEND TO BODY
|
||||
var CANVAS_WIDTH = 1200;
|
||||
var CANVAS_HEIGHT = 555;
|
||||
|
||||
var canvasElement = $("<canvas width='" + CANVAS_WIDTH +
|
||||
"' height='" + CANVAS_HEIGHT + "'></canvas>");
|
||||
var canvas = canvasElement.get(0).getContext("2d");
|
||||
canvasElement.appendTo('body');
|
||||
var players = [];
|
||||
var scoreOrange = 0;
|
||||
var scoreBlue = 0;
|
||||
var timerCount = 120; // 2 Minute Time Limit
|
||||
var timerID;
|
||||
|
||||
// DRAW
|
||||
function draw() {
|
||||
canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
canvas.fillStyle = "rgba(255, 120, 0, .7)";
|
||||
canvas.fillRect(0,0,CANVAS_WIDTH/2,CANVAS_HEIGHT);
|
||||
canvas.fillStyle = "rgba(0, 0, 255, .5)";
|
||||
canvas.fillRect(CANVAS_WIDTH/2,0,CANVAS_WIDTH/2,CANVAS_HEIGHT);
|
||||
ball.draw();
|
||||
for (var i=0; i<players.length; i++) {
|
||||
players[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATE
|
||||
function update() {
|
||||
for(var i=0; i < players.length; i++) {
|
||||
players[i].xMid += (players[i].vel * Math.sin(players[i].rot*Math.PI/180));
|
||||
players[i].yMid += -(players[i].vel * Math.cos(players[i].rot*Math.PI/180));
|
||||
}
|
||||
|
||||
ball.x += ball.velX;
|
||||
ball.y += ball.velY;
|
||||
|
||||
//// DEFINES GOALS AND EDGE OF ARENA
|
||||
// input -> goal width
|
||||
ballWallCollisionDetect(180);
|
||||
carWallCollisionDetect();
|
||||
//// CAR TO BALL COLLISION REACTION (DETECTION(PLAYERS ARRAY))
|
||||
carFrontBallCollision(frontFaceToBallCalc(players));
|
||||
carRightBallCollision(rightFaceToBallCalc(players));
|
||||
carLeftBallCollision(leftFaceToBallCalc(players));
|
||||
carBottomBallCollision(bottomFaceToBallCalc(players));
|
||||
//// Updates position of all corners of both vehicles
|
||||
northEastCornerHit();
|
||||
northWestCornerHit();
|
||||
southEastCornerHit();
|
||||
southWestCornerHit();
|
||||
}
|
||||
|
||||
/* PLAYER CONSTRUCTOR */
|
||||
|
||||
function Player(color, xInitial, yInitial, rotInitial, colorPath) {
|
||||
this.color = color;
|
||||
this.x = xInitial;
|
||||
this.y = yInitial;
|
||||
this.rot = rotInitial;
|
||||
this.vel = 0;
|
||||
this.width = 45;
|
||||
this.height = 75;
|
||||
this.xMid = this.x + this.width/2;
|
||||
this.yMid = this.y + this.height/2;
|
||||
this.draw = function() {
|
||||
var drawing = new Image();
|
||||
drawing.src = colorPath;
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(this.xMid, this.yMid);
|
||||
canvas.rotate(this.rot*Math.PI/180);
|
||||
canvas.drawImage(drawing, -this.width/2, -this.height/2,this.width,this.height);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
/* DEFINE BALL OBJECT */
|
||||
|
||||
// caching ball image outside of draw function so it only loads once
|
||||
var ballDrawing = new Image();
|
||||
ballDrawing.onload = function () {
|
||||
ball.draw();
|
||||
}
|
||||
ballDrawing.src = "assets/RLball.png";
|
||||
|
||||
var ball = {
|
||||
x: CANVAS_WIDTH/2,
|
||||
y: CANVAS_HEIGHT/2,
|
||||
radius: 30,
|
||||
velX: 0,
|
||||
velY: 0,
|
||||
draw: function() {
|
||||
canvas.drawImage(ballDrawing, this.x-this.radius, this.y-this.radius, this.radius*2, this.radius*2);
|
||||
}
|
||||
}
|
||||
|
||||
/* CREATE/RESET PLAYERS AND BALL */
|
||||
|
||||
function resetGame() {
|
||||
canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
players = [];
|
||||
player1 = new Player("dodgerblue", CANVAS_WIDTH/9-45/2, CANVAS_HEIGHT/2-75/2, 90, "assets/Car_orange.png");
|
||||
player2 = new Player("orange", CANVAS_WIDTH/9*8-45/2, CANVAS_HEIGHT/2-75/2, -90, "assets/Car_blue.png");
|
||||
players.push(player1, player2);
|
||||
ball.x = CANVAS_WIDTH/2;
|
||||
ball.y = CANVAS_HEIGHT/2;
|
||||
ball.velX = 0;
|
||||
ball.velY = 0;
|
||||
ball.draw();
|
||||
}
|
||||
|
||||
/* STARTS GAME ON PRESS OF START BUTTON */
|
||||
|
||||
function startGame() {
|
||||
resetGame();
|
||||
setTimer();
|
||||
$('.start-button').css("display", "none");
|
||||
$('.logo-timer').replaceWith('<div class="count-down">2:00</div>');
|
||||
$('.center').css("height", "110px");
|
||||
}
|
||||
|
||||
|
||||
function KeyboardController(keys, repeat) {
|
||||
var timers= {};
|
||||
|
||||
// When key is pressed and we don't already think it's pressed, call the
|
||||
// key action callback and set a timer to generate another one after a delay
|
||||
//
|
||||
document.onkeydown= function(event) {
|
||||
var key= (event || window.event).keyCode;
|
||||
if (!(key in keys))
|
||||
return true;
|
||||
if (!(key in timers)) {
|
||||
timers[key]= null;
|
||||
keys[key]();
|
||||
if (repeat!==0)
|
||||
timers[key]= setInterval(keys[key], repeat);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Cancel timeout and mark key as released on keyup
|
||||
//
|
||||
document.onkeyup= function(event) {
|
||||
var key= (event || window.event).keyCode;
|
||||
if (key in timers) {
|
||||
if (timers[key]!==null)
|
||||
clearInterval(timers[key]);
|
||||
delete timers[key];
|
||||
}
|
||||
};
|
||||
|
||||
// When window is unfocused we may not get key events. To prevent this
|
||||
// causing a key to 'get stuck down', cancel all held keys
|
||||
//
|
||||
window.onblur= function() {
|
||||
for (key in timers)
|
||||
if (timers[key]!==null)
|
||||
clearInterval(timers[key]);
|
||||
timers= {};
|
||||
};
|
||||
};
|
||||
|
||||
KeyboardController({
|
||||
// PLAYER 1 CONTROLS
|
||||
// A
|
||||
65: function() { players[0].rot -= 10; },
|
||||
// W
|
||||
87: function() { players[0].vel < 4 ? players[0].vel += .15 : players[0].vel = players[0].vel; },
|
||||
// D
|
||||
68: function() { players[0].rot += 10; },
|
||||
// S
|
||||
83: function() { players[0].vel > -2.5 ? players[0].vel -= .25 : players[0].vel = players[0].vel; },
|
||||
// PLAYER 2 CONTROLS
|
||||
// left
|
||||
37: function() { players[1].rot -= 10; },
|
||||
// up
|
||||
38: function() { players[1].vel < 4 ? players[1].vel += .15 : players[1].vel = players[1].vel; },
|
||||
// right
|
||||
39: function() { players[1].rot += 10; },
|
||||
// down
|
||||
40: function() { players[1].vel > -2.5 ? players[1].vel -= .25 : players[1].vel = players[1].vel; },
|
||||
}, 50);
|
||||
|
||||
|
||||
/* BALL SPEED DECAY */
|
||||
function ballFriction(friction) {
|
||||
if (Math.hypot(ball.velX, ball.velY) > 0) {
|
||||
ball.velX -= ball.velX*friction;
|
||||
ball.velY -= ball.velY*friction;
|
||||
}
|
||||
}
|
||||
|
||||
function carFriction(friction) {
|
||||
for (var i=0; i < players.length; i++) {
|
||||
players[i].vel -= players[i].vel*friction;
|
||||
}
|
||||
}
|
||||
|
||||
// SPEED DECAY FUNCTION CALL
|
||||
setInterval(function() {
|
||||
ballFriction(.2);
|
||||
carFriction(.1);
|
||||
}, 500);
|
||||
|
||||
// TIMER ACTION
|
||||
function setTimer() {
|
||||
timerID = setInterval(function() {
|
||||
var timeRemaining = timerLogic(timerCount-1);
|
||||
$('.count-down').text(timeRemaining[0] + ":" + timeRemaining[1]);
|
||||
if (timerCount > -1) {
|
||||
timerCount--;
|
||||
}
|
||||
if (timerCount === 30) {
|
||||
$('.two-minute-warning').trigger("play");
|
||||
}
|
||||
if (timerCount <= 10 && timerCount > 0) {
|
||||
//pause playing
|
||||
$('.timer-running-out').trigger('pause');
|
||||
//set play time to 0
|
||||
$('.timer-running-out').prop("currentTime",0);
|
||||
$('.timer-running-out').trigger("play");
|
||||
}
|
||||
if (timerCount === 0) {
|
||||
$('.game-over').trigger("play");
|
||||
}
|
||||
if (timerCount === -1) {
|
||||
$('.count-down').text("0:00");
|
||||
gameOver();
|
||||
clearInterval(timerID);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function timerLogic(timerCount) {
|
||||
var minutes = Math.floor(timerCount/60);
|
||||
var seconds = timerCount - minutes*60;
|
||||
seconds = (seconds % 60 > 9) ? seconds % 60 : "0" + seconds % 60;
|
||||
return [minutes, seconds];
|
||||
}
|
||||
|
||||
function gameOver() {
|
||||
clearInterval(timerID);
|
||||
$('.game-over').toggleClass('hidden');
|
||||
winnerAnnounce = $('.winner-announce');
|
||||
if (scoreBlue > scoreOrange) {
|
||||
winnerAnnounce.text("WINNER! BLUE");
|
||||
winnerAnnounce.css("color", "blue");
|
||||
|
||||
} else if (scoreOrange > scoreBlue) {
|
||||
winnerAnnounce.text("WINNER! ORANGE");
|
||||
winnerAnnounce.css("color", "orange");
|
||||
} else {
|
||||
winnerAnnounce.text("TIE GAME!");
|
||||
winnerAnnounce.css("color", "white");
|
||||
}
|
||||
}
|
||||
|
||||
function playAgain() {
|
||||
resetGame();
|
||||
|
||||
// STOP time
|
||||
clearInterval(timerID);
|
||||
timerCount = 120;
|
||||
$('.count-down').text("2:00");
|
||||
setTimer();
|
||||
|
||||
// RESET Score
|
||||
scoreOrange = 0;
|
||||
scoreBlue = 0;
|
||||
$('.orange').text(scoreOrange);
|
||||
$('.blue').text(scoreBlue);
|
||||
}
|
||||
|
||||
// FPS SETTING
|
||||
var FPS = 60;
|
||||
setInterval(function() {
|
||||
update();
|
||||
requestAnimationFrame(draw);
|
||||
}, 1000/FPS);
|
||||
|
||||
/* DOM INITIALIZATION */
|
||||
|
||||
$('.orange').text(scoreOrange);
|
||||
$('.blue').text(scoreBlue);
|
||||
|
||||
/* EVENT LISTENERS */
|
||||
var playButton = $('.play-again');
|
||||
|
||||
// Instructions Pane
|
||||
$instructions = $('.instructions');
|
||||
|
||||
// START BUTTON
|
||||
$startButton = $('.start-button');
|
||||
$startButton.on("click", function() {
|
||||
startGame();
|
||||
$instructions.toggleClass('hidden');
|
||||
});
|
||||
$startButton.hover(function(event) {
|
||||
$startButton.css("background", "darkgreen");
|
||||
}, function(event) {
|
||||
$startButton.css("background", "green");
|
||||
});
|
||||
|
||||
|
||||
// play-again button CLICK
|
||||
playButton.on("click", function() {
|
||||
playAgain();
|
||||
$('.game-over').toggleClass('hidden');
|
||||
});
|
||||
|
||||
// PLAY AGAIN? BUTTON
|
||||
playButton.hover(function(event) {
|
||||
playButton.css("background-color", "black");
|
||||
playButton.css("color", "yellow");
|
||||
}, function(event) {
|
||||
playButton.css("background-color", "yellow");
|
||||
playButton.css("color", "black");
|
||||
});
|
||||
|
||||
|
BIN
2drocketleague/unnamed.png
Normal file
After Width: | Height: | Size: 28 KiB |
1
404.html
@ -16,6 +16,7 @@
|
||||
<!-- initialize my stuff -->
|
||||
<script src="/js/all.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<script src="/js/themes.js"></script>
|
||||
<link rel="stylesheet" href="/themes.css" />
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
|
||||
|
10
about.html
@ -15,6 +15,7 @@
|
||||
<!-- initialize my stuff -->
|
||||
<script src="/js/all.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<script src="/js/themes.js"></script>
|
||||
<script src="/js/randomquote.js"></script>
|
||||
<link rel="stylesheet" href="/themes.css" />
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
@ -66,12 +67,15 @@
|
||||
<p><a href="/backgrounds.html">View Background Credits</a></p>
|
||||
|
||||
<h2>Developers</h2>
|
||||
<a href="https://github.com/skysthelimitt"><sl-avatar image="https://cdn.discordapp.com/avatars/1014608595263950848/fbc25e2f109d98e9f50c361342dbc4f7.webp" label="skysthelimitt"></sl-avatar> <p>Sky</p></a>
|
||||
<div class="samerow">
|
||||
<a href="https://github.com/skysthelimitt"><sl-avatar image="/img/pfps/sky.webp" label="skysthelimitt"></sl-avatar> <p>Sky</p></a>
|
||||
<a href="https://github.com/a456pur"><sl-avatar image="/img/pfps/astra.webp" label="a456pur"></sl-avatar> <p>a456pur</p></a>
|
||||
</div>
|
||||
|
||||
<h2>Supporters</h2>
|
||||
<div class="samerow">
|
||||
<a class="avatar" href="https://discord.com/users/731338278082445376"><sl-avatar image="https://cdn.discordapp.com/avatars/731338278082445376/1844d9f0f33f23cb385c6b412e3a6040.webp" label="Caidn"></sl-avatar> <p>Caidn</p></a>
|
||||
<a class="avatar" href="https://discord.com/users/778709612621987850"><sl-avatar image="https://cdn.discordapp.com/avatars/778709612621987850/365d4b71e0da64cc20ad75d612bdd7c4.webp" label="ayo"></sl-avatar> <p>ayo</p></a>
|
||||
<a class="avatar" href="https://discord.com/users/731338278082445376"><sl-avatar image="/img/pfps/caidn.webp" label="Caidn"></sl-avatar> <p>Caidn</p></a>
|
||||
<a class="avatar" href="https://discord.com/users/778709612621987850"><sl-avatar image="/img/pfps/ayo.webp" label="ayo"></sl-avatar> <p>ayo</p></a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|