<< Back to Code Snippets & Analyses
Galactic Frigate (JavaScript code)
////////////////////////////////
//INIT (NOT FUNCTIONS)//////////
////////////////////////////////
//canvas
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//audio variables (only work on website, but doesn't crash local)
var audioMainSongPath = 'https://lovablesightsandsounds.com/wp-content/uploads/song_general.mp3';
var audioShootPath = 'https://lovablesightsandsounds.com/wp-content/uploads/SmallSwordHit.wav';
var audioHitPath = 'https://lovablesightsandsounds.com/wp-content/uploads/CFalcon-Boom.wav';
var audioChoosePath = 'https://lovablesightsandsounds.com/wp-content/uploads/Highlight.wav';
var audioSelectorPath = 'https://lovablesightsandsounds.com/wp-content/uploads/Highlight2.wav';
var audioMainSong = new Audio(audioMainSongPath);
var audioShoot = new Audio(audioShootPath);
var audioHit = new Audio(audioHitPath);
var audioChoose = new Audio(audioChoosePath);
var audioSelector = new Audio(audioSelectorPath);
audioMainSong.loop = true;
audioMainSong.volume = 0.7;
var initSongVar = false;
//keyboard event listeners
document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);
//fps and milliseconds-per-frame
var fps = 30;
var mpf = 1000/fps;
//loops/modes/"rooms"
var titleLoopVar = true;
var twoPlayerLoopVar = false;
var playerVsCpuLoopVar = false;
var cpuVsCpuLoopVar = false;
var instructionsLoopVar = false;
//text sizes
//e.g. ctx.font = victoryTextSize + ' ' + 'serif';
var victoryTextSize = canvas.height*.2 + 'px';
var titleTextSize = canvas.height*.2 + 'px';
var titleSelectionSize = canvas.height*.1 + 'px';
var titleSelectionModifier = .07;
var titleSelectionSize = canvas.height*titleSelectionModifier + 'px';
//input button checks
var wPressed = false;
var aPressed = false;
var sPressed = false;
var dPressed = false;
var upPressed = false;
var downPressed = false;
var leftPressed = false;
var rightPressed = false;
var spacePressed = false;
var shiftPressed = false;
var wPrevState = false;
var aPrevState = false;
var sPrevState = false;
var dPrevState = false;
var upPrevState = false;
var downPrevState = false;
var leftPrevState = false;
var rightPrevState = false;
var spacePrevState = false;
var shiftPrevState = false;
var wJustPressed = false;
var aJustPressed = false;
var sJustPressed = false;
var dJustPressed = false;
var upJustPressed = false;
var downJustPressed = false;
var leftJustPressed = false;
var rightJustPressed = false;
var spaceJustPressed = false;
var shiftJustPressed = false;
///////////////////////
//TITLE VARIABLES//////
///////////////////////
var selectorOption = 0;
var choiceX = canvas.width*.34;
var choice0Y = canvas.height*.7;
var choice1Y = canvas.height*.766;
var choice2Y = canvas.height*.833;
var choice3Y = canvas.height*.9;
var selectorFrontX = canvas.width*.32;
var selectorBackX = canvas.width*.3;
var selector0Y1 = choice0Y-(canvas.height*(titleSelectionModifier*.3575));
var selector0Y2 = choice0Y-(canvas.height*(titleSelectionModifier*.715));
var selector0Y3 = choice0Y;
var selector1Y1 = choice1Y-(canvas.height*(titleSelectionModifier*.3575));
var selector1Y2 = choice1Y-(canvas.height*(titleSelectionModifier*.715));
var selector1Y3 = choice1Y;
var selector2Y1 = choice2Y-(canvas.height*(titleSelectionModifier*.3575));
var selector2Y2 = choice2Y-(canvas.height*(titleSelectionModifier*.715));
var selector2Y3 = choice2Y;
var selector3Y1 = choice3Y-(canvas.height*(titleSelectionModifier*.3575));
var selector3Y2 = choice3Y-(canvas.height*(titleSelectionModifier*.715));
var selector3Y3 = choice3Y;
//////////////////////////////////
//GAMEPLAY STATE VARIABLES, ETC.//
//////////////////////////////////
//variables to (dis)allow player control
var player1alive = true;
var player2alive = true;
//victory check: 0=n/a, 1=p1, 2=p2, 3=draw
var winner = 0;
//true when it's time to show postgame commands
var showPostgameCommands = false;
//auto-rematch variables
var autoRematchEnabled = 0;
var autoRematchState = 9;
var autoRematchText = "";
var autoRematchTimer = 0;
///////////////////////
//SHIP & PARTS FEATURES
///////////////////////
//ship body
var shipBodyRadius = canvas.width/24;
//ship turret
var turretHeight = canvas.width/40;
var turretWidth = canvas.width/13.333;
//bullet
var bulletHeight = canvas.width/60;
var bulletWidth = canvas.width/15;
//ammo tally rectangle
var tallyHeight = canvas.width/26.666;
var tallyWidth = canvas.width/160;
var tallyBuffer = canvas.width/80;
//ammo counters
var maxAmmo = 4;
var leftAmmoCount = maxAmmo;
var rightAmmoCount = maxAmmo;
//ship body coordinates
var leftShipY = canvas.height/2;
var rightShipY = canvas.height/2;
var leftShipX = shipBodyRadius;
var rightShipX = (canvas.width – shipBodyRadius);
//turret coordinates
var leftTurretY = leftShipY – turretHeight*.5;
var rightTurretY = rightShipY – turretHeight*.5;
var leftTurretX = leftShipX;
var rightTurretX = rightShipX;
//movement speeds
var shipSpeed = 3*(fps/30);
var fastShot = 9*(fps/30);
var slowShot = 3*(fps/30);
var slowTimer = 4*fps; //4 seconds
//ammo tally creation & coordinates
var leftAmmoTallies = [];
var leftTallyStartX = leftShipX – shipBodyRadius*.5;
for (var t=0; t<leftAmmoCount; t++) {
leftAmmoTallies[t] = { x: leftTallyStartX + t*tallyBuffer, y: leftShipY – tallyHeight*.5 };
}
var rightAmmoTallies = [];
var rightTallyStartX = rightShipX + (shipBodyRadius*.5-tallyWidth);
for (var t=0; t<rightAmmoCount; t++) {
rightAmmoTallies[t] = { x: rightTallyStartX – t*tallyBuffer, y: rightShipY – tallyHeight*.5 };
}
var bulletArray = [];
for (var b=0; b<maxAmmo; b++) {
bulletArray[b] = new Bullet(0, 0, 1, 1, b, 0);
}
for (var b=maxAmmo; b<maxAmmo*2; b++) {
bulletArray[b] = new Bullet(0, 0, 1, 2, b, 0);
}
//decay line creation & coordinates
var baseDecayTimer = 0.6*fps;
var leftDecayTimer = baseDecayTimer;
var rightDecayTimer = baseDecayTimer;
var leftDecayState = 0;
var rightDecayState = 0;
var decayDistance = (shipBodyRadius + turretWidth)/7;
var decayHeight = shipBodyRadius*2;
var decayBaseWidth = tallyWidth;
var decayWidthMod = 2;
var leftDecayLines = [];
for (var d=0; d<7; d++) {
leftDecayLines[d] = { x: 0, y: 0 };
}
var leftDecayStartX = leftShipX – shipBodyRadius;
var rightDecayLines = [];
for (var d=0; d<7; d++) {
rightDecayLines[d] = { x: 0, y: 0 };
}
var rightDecayStartX = rightShipX – shipBodyRadius*2 + decayBaseWidth;
////////////////////////////////
//INIT FUNCTIONS////////////////
////////////////////////////////
function initSong() {
if (initSongVar == false) {
audioMainSong.play()
initSongVar = true;
}
}
function initTitle() {
//always start rooms with song check
audioMainSong.play()
//selector
selectorOption = 0;
//ship body coordinates
leftShipY = canvas.height/2;
rightShipY = canvas.height/2;
leftShipX = shipBodyRadius;
rightShipX = (canvas.width – shipBodyRadius);
//turret coordinates
leftTurretY = leftShipY – turretHeight*.5;
rightTurretY = rightShipY – turretHeight*.5;
leftTurretX = leftShipX;
rightTurretX = rightShipX;
//ammo counters
leftAmmoCount = maxAmmo;
rightAmmoCount = maxAmmo;
//ammo tally creation & coordinates
leftAmmoTallies = [];
leftTallyStartX = leftShipX – shipBodyRadius*.5;
for (var t=0; t<leftAmmoCount; t++) {
leftAmmoTallies[t] = { x: leftTallyStartX + t*tallyBuffer, y: leftShipY – tallyHeight*.5 };
}
rightAmmoTallies = [];
rightTallyStartX = rightShipX + (shipBodyRadius*.5-tallyWidth);
for (var t=0; t<rightAmmoCount; t++) {
rightAmmoTallies[t] = { x: rightTallyStartX – t*tallyBuffer, y: rightShipY – tallyHeight*.5 };
}
//reset decay variables
leftDecayTimer = baseDecayTimer;
rightDecayTimer = baseDecayTimer;
leftDecayState = 0;
rightDecayState = 0;
//reset bullets
for (var b=0; b<maxAmmo*2; b++) {
bulletArray[b].state = 0;
bulletArray[b].hitYet = 0;
}
}
function initTwoPlayer() {
//always start rooms with song check
audioMainSong.play()
//variables to (dis)allow player control
player1alive = true;
player2alive = true;
//victory check: 0=n/a, 1=p1, 2=p2, 3=draw
winner = 0;
//true when it's time to show postgame commands
showPostgameCommands = false;
//auto-rematch variables
autoRematchState = 9;
autoRematchText = "";
autoRematchTimer = 0;
//ship body coordinates
leftShipY = canvas.height/2;
rightShipY = canvas.height/2;
leftShipX = shipBodyRadius;
rightShipX = (canvas.width – shipBodyRadius);
//turret coordinates
leftTurretY = leftShipY – turretHeight*.5;
rightTurretY = rightShipY – turretHeight*.5;
leftTurretX = leftShipX;
rightTurretX = rightShipX;
//ammo counters
leftAmmoCount = maxAmmo;
rightAmmoCount = maxAmmo;
//ammo tally creation & coordinates
leftAmmoTallies = [];
leftTallyStartX = leftShipX – shipBodyRadius*.5;
for (var t=0; t<leftAmmoCount; t++) {
leftAmmoTallies[t] = { x: leftTallyStartX + t*tallyBuffer, y: leftShipY – tallyHeight*.5 };
}
rightAmmoTallies = [];
rightTallyStartX = rightShipX + (shipBodyRadius*.5-tallyWidth);
for (var t=0; t<rightAmmoCount; t++) {
rightAmmoTallies[t] = { x: rightTallyStartX – t*tallyBuffer, y: rightShipY – tallyHeight*.5 };
}
//reset decay variables
leftDecayTimer = baseDecayTimer;
rightDecayTimer = baseDecayTimer;
leftDecayState = 0;
rightDecayState = 0;
//reset bullets
for (var b=0; b<maxAmmo*2; b++) {
bulletArray[b].state = 0;
bulletArray[b].hitYet = 0;
}
}
////////////////////////////////////////////
//OBJECT CONSTRUCTORS (NOT PART OF A LOOP)//
////////////////////////////////////////////
//'type' = 1 or 2 (fast or slow, respectively)
//'player' = 1 or 2
//'state' = 0, 1, 2 (unpresent, traveling, stopped)
function Bullet(x, y, type, player, ID, state) {
this.timer = slowTimer;
this.slowWalled = 0;
this.hitYet = 0;
this.x = x;
this.y = y;
this.type = type;
if (player == 1) {
//this.direction = 1;
}
else if (player == 2) {
//this.direction = -1;
}
this.id = ID;
this.state = state;
this.drawSelf = function() {
ctx.beginPath();
ctx.rect(this.x, this.y, bulletWidth, bulletHeight);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
this.leftsFastShot = function() {
if (this.state == 1) {
this.x += fastShot;
}
}
this.leftsSlowShot = function() {
if (this.state == 1) {
this.x += slowShot;
if ((this.x + bulletWidth >= canvas.width) && (this.slowWalled == 0)) {
this.state = 2;
this.slowWalled = 1;
}
}
if (this.state == 2) {
this.timer -= 1;
if (this.timer <= 0) {
this.state = 1;
}
}
}
this.rightsFastShot = function() {
if (this.state == 1) {
this.x -= fastShot;
}
}
this.rightsSlowShot = function() {
if (this.state == 1) {
this.x -= slowShot;
if ((this.x – bulletWidth <= 0) && (this.slowWalled == 0)) {
this.state = 2;
this.slowWalled = 1;
}
}
if (this.state == 2) {
this.timer -= 1;
if (this.timer <= 0) {
this.state = 1;
}
}
}
}
/////////////////////////////////////////
//EVENT LISTENERS (NOT PART OF A LOOP)///
/////////////////////////////////////////
function keyDownHandler(e) {
if(e.code == 'KeyW') {
wPressed = true;
}
else if(e.code == 'KeyS') {
sPressed = true;
}
if(e.code == 'KeyA') {
aPressed = true;
}
else if(e.code == 'KeyD') {
dPressed = true;
}
if(e.code == 'ArrowUp') {
upPressed = true;
e.preventDefault();
}
else if(e.code == 'ArrowDown') {
downPressed = true;
e.preventDefault();
}
if(e.code == 'ArrowLeft') {
leftPressed = true;
e.preventDefault();
}
else if(e.code == 'ArrowRight') {
rightPressed = true;
e.preventDefault();
}
if(e.code == 'Space') {
spacePressed = true;
e.preventDefault();
}
if((e.code == 'ShiftLeft') || (e.code == 'ShiftRight')) {
shiftPressed = true;
e.preventDefault();
}
}
function keyUpHandler(e) {
if(e.code == 'KeyW') {
wPressed = false;
}
else if(e.code == 'KeyS') {
sPressed = false;
}
if(e.code == 'KeyA') {
aPressed = false;
}
else if(e.code == 'KeyD') {
dPressed = false;
}
if(e.code == 'ArrowUp') {
upPressed = false;
}
else if(e.code == 'ArrowDown') {
downPressed = false;
}
if(e.code == 'ArrowLeft') {
leftPressed = false;
}
else if(e.code == 'ArrowRight') {
rightPressed = false;
}
if(e.code == 'Space') {
spacePressed = false;
}
if((e.code == 'ShiftLeft') || (e.code == 'ShiftRight')) {
shiftPressed = false;
}
}
///////////////////////////////////////////
//CALLABLE FUNCTIONS (NOT PART OF A LOOP)//
///////////////////////////////////////////
function roomSender(room) {
if (room == 0) {
titleLoopVar = true;
twoPlayerLoopVar = false;
playerVsCpuLoopVar = false;
cpuVsCpuLoopVar = false;
instructionsLoopVar = false;
initTitle();
}
else if (room == 1) {
titleLoopVar = false;
twoPlayerLoopVar = true;
playerVsCpuLoopVar = false;
cpuVsCpuLoopVar = false;
instructionsLoopVar = false;
initTwoPlayer();
}
}
/////////////////////////////////////////
//INPUT FUNCTIONS////////////////////////
/////////////////////////////////////////
//run this at the start of main loop
function justPressed() {
if ((wPrevState == false) && (wPressed == true)) {
wJustPressed = true;
}
if ((aPrevState == false) && (aPressed == true)) {
aJustPressed = true;
}
if ((sPrevState == false) && (sPressed == true)) {
sJustPressed = true;
}
if ((dPrevState == false) && (dPressed == true)) {
dJustPressed = true;
}
if ((upPrevState == false) && (upPressed == true)) {
upJustPressed = true;
}
if ((downPrevState == false) && (downPressed == true)) {
downJustPressed = true;
}
if ((leftPrevState == false) && (leftPressed == true)) {
leftJustPressed = true;
}
if ((rightPrevState == false) && (rightPressed == true)) {
rightJustPressed = true;
}
if ((spacePrevState == false) && (spacePressed == true)) {
spaceJustPressed = true;
}
if ((shiftPrevState == false) && (shiftPressed == true)) {
shiftJustPressed = true;
}
}
//run this directly before draw functions in main loop
function justPressedResetter() {
wPrevState = wPressed;
aPrevState = aPressed;
sPrevState = sPressed;
dPrevState = dPressed;
upPrevState = upPressed;
downPrevState = downPressed;
leftPrevState = leftPressed;
rightPrevState = rightPressed;
spacePrevState = spacePressed;
shiftPrevState = shiftPressed;
wJustPressed = false;
aJustPressed = false;
sJustPressed = false;
dJustPressed = false;
upJustPressed = false;
downJustPressed = false;
leftJustPressed = false;
rightJustPressed = false;
spaceJustPressed = false;
shiftJustPressed = false;
}
/////////////////////////////////////////
//TITLE LOGIC FUNCTIONS//////////////////
/////////////////////////////////////////
function titleLogic() {
if (titleLoopVar) {
if (sJustPressed || downJustPressed) {
selectorOption += 1;
let blip = new Audio(audioSelectorPath);
blip.play();
}
else if (wJustPressed || upJustPressed) {
selectorOption -= 1;
let blip = new Audio(audioSelectorPath);
blip.play();
}
if (selectorOption < 0) {
selectorOption = 3;
}
if (selectorOption > 3) {
selectorOption = 0;
}
if (spaceJustPressed) {
roomSender(selectorOption+1);
let blip = new Audio(audioChoosePath);
blip.play();
}
}
}
/////////////////////////////////////////
//GAMEPLAY LOGIC FUNCTIONS///////////////
/////////////////////////////////////////
function leftShipMove() {
if (wPressed) {
leftShipY -= shipSpeed;
}
if (sPressed) {
leftShipY += shipSpeed;
}
if (leftShipY – shipBodyRadius < 0) {
leftShipY = shipBodyRadius;
}
if (leftShipY + shipBodyRadius > canvas.height) {
leftShipY = canvas.height – shipBodyRadius;
}
leftTurretY = leftShipY – turretHeight*.5;
}
function rightShipMove() {
if (upPressed) {
rightShipY -= shipSpeed;
}
if (downPressed) {
rightShipY += shipSpeed;
}
if (rightShipY – shipBodyRadius < 0) {
rightShipY = shipBodyRadius;
}
if (rightShipY + shipBodyRadius > canvas.height) {
rightShipY = canvas.height – shipBodyRadius;
}
rightTurretY = rightShipY – turretHeight*.5;
}
function leftAmmoMove() {
for (var t=0; t<maxAmmo; t++) {
var tallyX = leftTallyStartX + t*tallyBuffer;
var tallyY = leftShipY – tallyHeight*.5;
leftAmmoTallies[t].x = tallyX;
leftAmmoTallies[t].y = tallyY;
}
}
function rightAmmoMove() {
for (var t=0; t<maxAmmo; t++) {
var tallyX = rightTallyStartX – t*tallyBuffer;
var tallyY = rightShipY – tallyHeight*.5;
rightAmmoTallies[t].x = tallyX;
rightAmmoTallies[t].y = tallyY;
}
}
function shootBullet() {
if (dJustPressed && player1alive) {
for (var b=0; b<maxAmmo; b++) {
if (bulletArray[b].state == 0) {
bulletArray[b].x = leftShipX + bulletWidth*.5;
bulletArray[b].y = leftShipY – bulletHeight*.5;
bulletArray[b].type = 1;
bulletArray[b].player = 1;
bulletArray[b].state = 1;
leftAmmoCount -= 1;
let blip = new Audio(audioShootPath);
blip.play();
break;
}
}
}
if (aJustPressed && player1alive) {
for (var b=0; b<maxAmmo; b++) {
if (bulletArray[b].state == 0) {
bulletArray[b].x = leftShipX + bulletWidth*.75;
bulletArray[b].y = leftShipY – bulletHeight*.5;
bulletArray[b].type = 2;
bulletArray[b].player = 1;
bulletArray[b].state = 1;
bulletArray[b].timer = slowTimer;
bulletArray[b].slowWalled = 0;
leftAmmoCount -= 1;
let blip = new Audio(audioShootPath);
blip.play();
break;
}
}
}
if (leftJustPressed && player2alive) {
for (var b=maxAmmo; b<maxAmmo*2; b++) {
if (bulletArray[b].state == 0) {
bulletArray[b].x = rightShipX – bulletWidth*.5;
bulletArray[b].y = rightShipY – bulletHeight*.5;
bulletArray[b].type = 1;
bulletArray[b].player = 2;
bulletArray[b].state = 1;
rightAmmoCount -= 1;
let blip = new Audio(audioShootPath);
blip.play();
break;
}
}
}
if (rightJustPressed && player2alive) {
for (var b=maxAmmo; b<maxAmmo*2; b++) {
if (bulletArray[b].state == 0) {
bulletArray[b].x = rightShipX – bulletWidth*.75;
bulletArray[b].y = rightShipY – bulletHeight*.5;
bulletArray[b].type = 2;
bulletArray[b].player = 2;
bulletArray[b].state = 1;
bulletArray[b].timer = slowTimer;
bulletArray[b].slowWalled = 0;
rightAmmoCount -= 1;
let blip = new Audio(audioShootPath);
blip.play();
break;
}
}
}
}
function travelingBullets() {
for (var b=0; b<maxAmmo*2; b++) {
if ((bulletArray[b].state > 0) && (bulletArray[b].player == 1)) {
if (bulletArray[b].type == 1) {
bulletArray[b].leftsFastShot();
}
else if (bulletArray[b].type == 2) {
bulletArray[b].leftsSlowShot();
}
}
if ((bulletArray[b].state > 0) && (bulletArray[b].player == 2)) {
if (bulletArray[b].type == 1) {
bulletArray[b].rightsFastShot();
}
else if (bulletArray[b].type == 2) {
bulletArray[b].rightsSlowShot();
}
}
}
}
function destroyBullet() {
for (var b=0; b<maxAmmo*2; b++) {
if (((bulletArray[b].x < 0 ) || (bulletArray[b].x > canvas.width)) && (bulletArray[b].state == 1)) {
bulletArray[b].state = 0;
if (b<maxAmmo) {
leftAmmoCount += 1;
}
else if (b>=maxAmmo) {
rightAmmoCount += 1;
}
}
}
}
function setLeftDecayLines() {
//position them
for (var d=0; d<7; d++) {
var decayX = leftDecayStartX + d*decayDistance;
var decayY = leftShipY – decayHeight*.5;
leftDecayLines[d].x = decayX;
leftDecayLines[d].y = decayY;
}
if (player1alive == false) {
leftDecayTimer -= 1;
if (leftDecayTimer <= 0 && leftDecayState < 3) {
leftDecayTimer = baseDecayTimer;
leftDecayState += 1;
}
}
}
function setRightDecayLines() {
//position them
for (var d=0; d<7; d++) {
var decayX = rightDecayStartX + d*decayDistance;
var decayY = rightShipY – decayHeight*.5;
rightDecayLines[d].x = decayX;
rightDecayLines[d].y = decayY;
}
if (player2alive == false) {
rightDecayTimer -= 1;
if (rightDecayTimer <= 0 && rightDecayState < 3) {
rightDecayTimer = baseDecayTimer;
rightDecayState += 1;
}
}
}
//run collision detection in physics function AFTER all move functions
function collisionDetection() {
for (var b=0; b<maxAmmo*2; b++) {
var bc = bulletArray[b];
//check collision with left's bullets against right ship
if (bc.player == 1 && bc.state > 0 && bc.hitYet == 0 && player2alive) {
var bcLeft = bc.x;
var bcRight = bc.x + bulletWidth;
var bcTop = bc.y;
var bcBottom = bc.y + bulletHeight;
var rightTurretLeft = rightTurretX – turretWidth;
var rightTurretRight = rightTurretX;
var rightTurretTop = rightTurretY;
var rightTurretBottom = rightTurretY + turretHeight;
var bulletC = { x: bc.x, y: bc.y, w: bulletWidth, h: bulletHeight };
var rightTurretC = { x: rightTurretX, y: rightTurretY, w: -turretWidth, h: turretHeight };
var rightShipC = { x: rightShipX, y: rightShipY, r: shipBodyRadius };
//test for collision with circular ship body
var distX = Math.abs(rightShipC.x – bulletC.x-bulletC.w/2);
var distY = Math.abs(rightShipC.y – bulletC.y-bulletC.h/2);
var circleHit = true;
if (distX > (bulletC.w/2 + rightShipC.r)) {
circleHit = false;
}
if (distY > (bulletC.h/2 + rightShipC.r)) {
circleHit = false;
}
if (distX <= (bulletC.w/2) && circleHit == true) {
player2alive = false;
bc.hitYet = 1;
let blip = new Audio(audioHitPath);
blip.play();
}
if (distY <= (bulletC.h/2) && circleHit == true) {
player2alive = false;
bc.hitYet = 1;
let blip = new Audio(audioHitPath);
blip.play();
}
//end test collision with circular ship body
//test for collision with turret
if (bcRight > rightTurretLeft && bcLeft < rightTurretRight && bcBottom > rightTurretTop && bcTop < rightTurretBottom) {
player2alive = false;
bc.hitYet = 1;
let blip = new Audio(audioHitPath);
blip.play();
}
}
//check collision with right's bullets against left ship
if (bc.player == 2 && bc.state > 0 && bc.hitYet == 0 && player1alive) {
var bcLeft = bc.x – bulletWidth;
var bcRight = bc.x;
var bcTop = bc.y;
var bcBottom = bc.y + bulletHeight;
var leftTurretLeft = leftTurretX;
var leftTurretRight = leftTurretX + turretWidth;
var leftTurretTop = leftTurretY;
var leftTurretBottom = leftTurretY + turretHeight;
var bulletC = { x: bc.x-bulletWidth, y: bc.y, w: bulletWidth, h: bulletHeight };
var leftTurretC = { x: leftTurretX, y: leftTurretY, w: turretWidth, h: turretHeight };
var leftShipC = { x: leftShipX, y: leftShipY, r: shipBodyRadius };
//test for collision with circular ship body
var distX = Math.abs(leftShipC.x – bulletC.x-bulletC.w/2);
var distY = Math.abs(leftShipC.y – bulletC.y-bulletC.h/2);
var circleHit = true;
if (distX > (bulletC.w/2 + leftShipC.r)) {
circleHit = false;
}
if (distY > (bulletC.h/2 + leftShipC.r)) {
circleHit = false;
}
if (distX <= (bulletC.w/2) && circleHit == true) {
player1alive = false;
bc.hitYet = 1;
let blip = new Audio(audioHitPath);
blip.play();
}
if (distY <= (bulletC.h/2) && circleHit == true) {
player1alive = false;
bc.hitYet = 1;
let blip = new Audio(audioHitPath);
blip.play();
}
//end test collision with circular ship body
//test for collision with turret
if (bcRight > leftTurretLeft && bcLeft < leftTurretRight && bcBottom > leftTurretTop && bcTop < leftTurretBottom) {
player1alive = false;
bc.hitYet = 1;
let blip = new Audio(audioHitPath);
blip.play();
}
}
}
}
function victoryCheck() {
if (winner == 0) {
if (player1alive == true && player2alive == false) {
winner = 1;
}
else if (player1alive == false && player2alive == true) {
winner = 2;
}
else if (player1alive == false && player2alive == false) {
winner = 3;
}
}
}
function victoryDeclaration() {
if (winner == 1) {
//do something maybe;
}
else if (winner == 2) {
//do something maybe;
}
else if (winner == 3) {
//do something maybe;
}
if ((leftDecayState == 3 || rightDecayState == 3) && !(showPostgameCommands)) {
showPostgameCommands = true;
}
if (autoRematchEnabled == 1) {
if (showPostgameCommands) {
autoRematchTimer += 1;
}
if ((autoRematchTimer >= 1) && (autoRematchTimer < fps*1)) {
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*1) && (autoRematchTimer < fps*2) && (autoRematchState == 9)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*2) && (autoRematchTimer < fps*3) && (autoRematchState == 8)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*3) && (autoRematchTimer < fps*4) && (autoRematchState == 7)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*4) && (autoRematchTimer < fps*5) && (autoRematchState == 6)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*5) && (autoRematchTimer < fps*6) && (autoRematchState == 5)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*6) && (autoRematchTimer < fps*7) && (autoRematchState == 4)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*7) && (autoRematchTimer < fps*8) && (autoRematchState == 3)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*8) && (autoRematchTimer < fps*9) && (autoRematchState == 2)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
}
else if ((autoRematchTimer >= fps*9) && (autoRematchTimer < fps*10) && (autoRematchState == 1)) {
autoRematchState -= 1;
autoRematchText = autoRematchState.toString();
initTwoPlayer();
}
}
}
function postgameSelection() {
if (showPostgameCommands) {
if (spaceJustPressed) {
let blip = new Audio(audioChoosePath);
blip.play();
roomSender(0);
}
else if (shiftJustPressed) {
let blip = new Audio(audioChoosePath);
blip.play();
initTwoPlayer();
}
}
}
/////////////////////////////////////////
//DRAW FUNCTIONS/////////////////////////
/////////////////////////////////////////
function drawBackground() {
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function drawLeftShip() {
//body
ctx.beginPath();
ctx.arc(leftShipX, leftShipY, shipBodyRadius, 0, Math.PI*2);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
//turret
ctx.beginPath();
ctx.rect(leftTurretX, leftTurretY, turretWidth, turretHeight);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
function drawRightShip() {
//body
ctx.beginPath();
ctx.arc(rightShipX, rightShipY, shipBodyRadius, 0, Math.PI*2);
ctx.fillStyle = 'white'
ctx.fill();
ctx.closePath();
//turret
ctx.beginPath();
ctx.rect(rightTurretX, rightTurretY, -turretWidth, turretHeight);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
function drawLeftAmmo() {
for (var t=0; t<leftAmmoCount; t++) {
ctx.beginPath();
ctx.rect(leftAmmoTallies[t].x, leftAmmoTallies[t].y, tallyWidth, tallyHeight);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
}
function drawRightAmmo() {
for (var t=0; t<rightAmmoCount; t++) {
ctx.beginPath();
ctx.rect(rightAmmoTallies[t].x, rightAmmoTallies[t].y, tallyWidth, tallyHeight);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
}
function drawLeftDecayLines() {
if (player1alive == false) {
for (var d=0; d<7; d++) {
ctx.beginPath();
ctx.rect(leftDecayLines[d].x, leftDecayLines[d].y, decayBaseWidth+decayWidthMod*leftDecayState, decayHeight);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
}
}
function drawRightDecayLines() {
if (player2alive == false) {
for (var d=0; d<7; d++) {
ctx.beginPath();
ctx.rect(rightDecayLines[d].x, rightDecayLines[d].y, decayBaseWidth+decayWidthMod*rightDecayState, decayHeight);
ctx.fillStyle = 'black';
ctx.fill();
ctx.closePath();
}
}
}
function drawLeftBullet() {
for (var b=0; b<maxAmmo; b++) {
if (bulletArray[b].state > 0) {
ctx.beginPath();
ctx.rect(bulletArray[b].x, bulletArray[b].y, bulletWidth, bulletHeight);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
}
}
function drawRightBullet() {
for (var b=maxAmmo; b<maxAmmo*2; b++) {
if (bulletArray[b].state > 0) {
ctx.beginPath();
ctx.rect(bulletArray[b].x, bulletArray[b].y, -bulletWidth, bulletHeight);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
}
}
function drawVictoryDeclaration() {
if (winner == 1) {
ctx.font = victoryTextSize + ' ' + 'serif';
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
ctx.fillText('VICTORY', canvas.width/2, canvas.height*.466);
ctx.fillText('P1', canvas.width/2, canvas.height*.666);
}
else if (winner == 2) {
ctx.font = victoryTextSize + ' ' + 'serif';
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
ctx.fillText('VICTORY', canvas.width/2, canvas.height*.466);
ctx.fillText('P2', canvas.width/2, canvas.height*.666);
}
else if (winner == 3) {
ctx.font = victoryTextSize + ' ' + 'serif';
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
ctx.fillText('DRAW', canvas.width/2, canvas.height*.5);
}
if (showPostgameCommands) {
ctx.font = titleSelectionSize + ' ' + 'serif';
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
ctx.fillText('SPACE for TITLE', canvas.width/2, canvas.height*.8);
ctx.fillText('SHIFT for REMATCH', canvas.width/2, canvas.height*.866);
if (autoRematchEnabled == 1) {
ctx.fillText('AUTO-REMATCH in ' + autoRematchText, canvas.width/2, canvas.height*.933);
}
}
}
function drawTitleText() {
ctx.font = titleTextSize + ' ' + 'serif';
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
ctx.fillText('GALACTIC', canvas.width/2, canvas.height*.333);
ctx.fillText('FRIGATE', canvas.width/2, canvas.height*.533);
ctx.font = titleSelectionSize + ' ' + 'serif';
ctx.textAlign = 'left';
ctx.fillText('TWO-PLAYER', choiceX, choice0Y);
ctx.fillText('PLAYER VS. CPU', choiceX, choice1Y);
ctx.fillText('CPU VS. CPU', choiceX, choice2Y);
ctx.fillText('RULES', choiceX, choice3Y);
}
function drawTitleSelector() {
if (selectorOption == 0) {
ctx.beginPath();
ctx.moveTo(selectorFrontX, selector0Y1);
ctx.lineTo(selectorBackX, selector0Y2);
ctx.lineTo(selectorBackX, selector0Y3);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
else if (selectorOption == 1) {
ctx.beginPath();
ctx.moveTo(selectorFrontX, selector1Y1);
ctx.lineTo(selectorBackX, selector1Y2);
ctx.lineTo(selectorBackX, selector1Y3);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
else if (selectorOption == 2) {
ctx.beginPath();
ctx.moveTo(selectorFrontX, selector2Y1);
ctx.lineTo(selectorBackX, selector2Y2);
ctx.lineTo(selectorBackX, selector2Y3);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
else if (selectorOption == 3) {
ctx.beginPath();
ctx.moveTo(selectorFrontX, selector3Y1);
ctx.lineTo(selectorBackX, selector3Y2);
ctx.lineTo(selectorBackX, selector3Y3);
ctx.fillStyle = 'white';
ctx.fill();
ctx.closePath();
}
}
function drawTitleShips() {
drawLeftShip();
drawRightShip();
drawLeftAmmo();
drawRightAmmo();
}
/////////////////////////////////////////
//COMPOSITE FUNCTIONS////////////////////
/////////////////////////////////////////
//LOGIC
//titleLogic isn't here bc it's not composed of any other functions; it's above
function twoPlayerLogic() {
if (twoPlayerLoopVar) {
leftShipMove();
rightShipMove();
leftAmmoMove();
rightAmmoMove();
setLeftDecayLines();
setRightDecayLines();
shootBullet();
travelingBullets();
destroyBullet();
collisionDetection();
victoryCheck();
victoryDeclaration();
postgameSelection();
}
}
//DRAW
function drawTitle() {
if (titleLoopVar) {
drawTitleText();
drawTitleSelector();
drawTitleShips();
}
}
function drawTwoPlayer() {
if (twoPlayerLoopVar) {
drawLeftShip();
drawRightShip();
drawLeftDecayLines();
drawRightDecayLines();
drawLeftAmmo();
drawRightAmmo();
drawLeftBullet();
drawRightBullet();
drawVictoryDeclaration();
}
}
/////////////////////////////////////////
//ULTIMATE COMPOSITE FUNCTIONS///////////
/////////////////////////////////////////
function logic() {
titleLogic();
twoPlayerLogic();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
drawTitle();
drawTwoPlayer();
}
/////////////////////////////////////////
//MAIN LOOP//////////////////////////////
/////////////////////////////////////////
function main() {
initSong();
justPressed();
logic();
justPressedResetter();
draw();
}
setInterval(main, mpf);