shooty_ships
Table of Contents
Shooty Ships
- Roger and I created this game over 4 or 5 classes. It was an evolution of the bouncy balls demo series, itself which took 4 or 5 classes to cover.
- This took place before we began learning python but after we had studied PHP.
fi.html
fi.html
<!DOCTYPE HTML> <head> <link rel="theme.css"> <script src="mygames.js"></script> </head> <html> <body> <span class="title"> Fight IO <br> by Appledog </span> <hr> <div id="score"></div> <canvas id="myCanvas" style="border: 1px solid black;"> </canvas> <hr> <script> // Set Up Canvas var MAX_W = 600; var MAX_H = 480; var canvas1 = document.getElementById('myCanvas'); canvas1.width = MAX_W; canvas1.height = MAX_H; var ctx = canvas1.getContext('2d'); // Set Up Game var FPS = 60; var p1x = 100; var p1y = 100; var p1dx = 0; var p1dy = 0; var p2x = MAX_W-100; var p2y = MAX_H-100; var p2dx = 0; var p2dy = 0; var p1sx = 0; var p1sy = 0; var p1sdx = 0; var p1sdy = 0; var p1s = 0; var p2sx = 0; var p2sy = 0; var p2sdx = 0; var p2sdy = 0; var p2s = 0; var gameSpeed = 10; var shipSize = 32; var p1score = 0; var p2score = 0; var p1a = 135; var p2a = 315; // Set Up Animation Loop // This will draw the game. setInterval(gameLoop, 1000/FPS); // Set up controls // Now you can control the ships. document.onkeydown = function(evt) { evt = evt || window.event; // STOP // P1: q if (evt.keyCode == 81) { p1dx = p1dx * 0.8; p1dy = p1dy * 0.8; } // P2: space bar if (evt.keyCode == 32) { p2dx = p2dx * 0.8; p2dy = p2dx * 0.8; } // TURN LEFT // P1: a if (evt.keyCode == 65) { p1a = p1a - gameSpeed; if (p1a < 0) { p1a = p1a + 360; } } // P2: left arrow if (evt.keyCode == 37) { p2a = p2a - gameSpeed; if (p2a < 0) { p2a = p2a + 360; } } // RIGHT // P1: d if (evt.keyCode == 68) { p1a = p1a + gameSpeed; if (p1a > 360) { p1a = p1a - 360; } } // P2: right arrow if (evt.keyCode == 39) { p2a = p2a + gameSpeed; if (p2a > 360 ) { p2a = p2a - 360; } } // UP (Forward) // P1: a if (evt.keyCode == 87) { var radians = p1a * Math.PI / 180; var dx = Math.cos(radians); var dy = Math.sin(radians); p1dx = p1dx - (dx * gameSpeed*4); p1dy = p1dy - (dy * gameSpeed*4); } // P2: up arrow if (evt.keyCode == 38) { var radians = p2a * Math.PI / 180; var dx = Math.cos(radians); var dy = Math.sin(radians); p2dx = p2dx - (dx * gameSpeed*4); p2dy = p2dy - (dy * gameSpeed*4); } // DOWN (Reverse engines!) // P1: s if (evt.keyCode == 83) { var radians = p1a * Math.PI / 180; var dx = Math.cos(radians); var dy = Math.sin(radians); p1dx = p1dx + (dx * gameSpeed*4); p1dy = p1dy + (dy * gameSpeed*4); } // P2: down arrow if (evt.keyCode == 40) { var radians = p2a * Math.PI / 180; var dx = Math.cos(radians); var dy = Math.sin(radians); p2dx = p2dx + (dx * gameSpeed*4); p2dy = p2dy + (dy * gameSpeed*4); } // SHOOT // P1: e (69) if (evt.keyCode == 69) { shootGuns(1); } // P2: enter (13) if (evt.keyCode == 13) { shootGuns(2); } //alert (evt.keyCode); }; ///// function gameLoop() { moveShips(); moveShots(); checkRules(); drawGame(); } function moveShips() { p1x = p1x + p1dx/FPS; p1y = p1y + p1dy/FPS; p2x = p2x + p2dx/FPS; p2y = p2y + p2dy/FPS; } function moveShots() { if (p1s == 1) { p1sx = p1sx + p1sdx/FPS; p1sy = p1sy + p1sdy/FPS; } if (p2s == 1) { p2sx = p2sx + p2sdx/FPS; p2sy = p2sy + p2sdy/FPS; } } function checkRules() { checkShipsInside(); checkShipsMaxSpeed(); checkShots(); } function checkShipsInside(){ if (p1x > MAX_W) { p1x = 0; } if (p1y > MAX_H) { p1y = 0; } if (p2x > MAX_W) { p2x = 0; } if (p2y > MAX_H) { p2y = 0; } if (p1x < 0) { p1x = MAX_W; } if (p1y < 0) { p1y = MAX_H; } if (p2x < 0) { p2x = MAX_W; } if (p2y < 0) { p2y = MAX_H; } } function checkShipsMaxSpeed() { var p1speed = Math.abs(p1dx) + Math.abs(p1dy); var p2speed = Math.abs(p2dx) + Math.abs(p2dy); var MAX_SPEED = 1000; var BRAKES = 0.98; if (p1speed > MAX_SPEED) { p1dx = p1dx * BRAKES; p1dy = p1dy * BRAKES; } if (p2speed > MAX_SPEED) { p2dx = p2dx * BRAKES; p2dy = p2dy * BRAKES; } } function checkShots() { if (p1s == 1) { x = p2x; y = p2y; deg = p2a; width = 2*shipSize/3; height = shipSize; var pos0 = rotate(x, y, x, y - (height / 2), deg); var pos1 = rotate(x, y, x + (width / 2), y + (height / 2), deg); var pos2 = rotate(x, y, x - (width / 2), y + (height / 2), deg); x1 = pos0.x; x2 = pos1.x; x3 = pos2.x; y1 = pos0.y; y2 = pos1.y; y3 = pos2.y; if (isPointInTriangle(p1sx,p1sy,x1,y1,x2,y2,x3,y3)) { p1score = p1score + 1; p1s = 0; } } if (p2s == 1) { x = p1x; y = p1y; deg = p1a; width = 2*shipSize/3; height = shipSize; var pos0 = rotate(x, y, x, y - (height / 2), deg); var pos1 = rotate(x, y, x + (width / 2), y + (height / 2), deg); var pos2 = rotate(x, y, x - (width / 2), y + (height / 2), deg); x1 = pos0.x; x2 = pos1.x; x3 = pos2.x; y1 = pos0.y; y2 = pos1.y; y3 = pos2.y; if (isPointInTriangle(p2sx,p2sy,x1,y1,x2,y2,x3,y3)) { p2score = p2score + 1; p2s = 0; } } } function drawGame() { drawScore(); clearScreen(); drawShips(); drawShoots(); } function drawScore() { var scorediv = document.getElementById('score'); var msg = " Player 1: " + p1score.toFixed(0) + ", Player 2: " + p2score.toFixed(0); scorediv.innerHTML = msg; } function drawShips() { // Note x1,y1 is the direction. // We have: // p1a, p2a (angle) // p1x, p1y, p2x, p2y (location) drawShip(p1x, p1y, p1a, 2*shipSize/3, shipSize, "#FF0000"); drawShip(p2x, p2y, p2a, 2*shipSize/3, shipSize, "#0000FF"); } function shootGuns(p) { if (p == 1) { p1s = 1; // turn on the shoot. p1sx = p1x; p1sy = p1y; var radians = p1a * Math.PI / 180; var dx = Math.cos(radians); var dy = Math.sin(radians); p1sdx = -1 * dx * gameSpeed*24; p1sdy = -1 * dy * gameSpeed*24; } if (p == 2) { p2s = 1; p2sx = p2x; p2sy = p2y; var radians = p2a * Math.PI / 180; var dx = Math.cos(radians); var dy = Math.sin(radians); p2sdx = -1 * dx * gameSpeed*24; p2sdy = -1 * dy * gameSpeed*24; } } function drawShoots() { if (p1s == 1) { // draw p1 shot. var radius = 2; ctx.beginPath(); ctx.arc(p1sx, p1sy, radius, 0, 2 * Math.PI, false); ctx.fillStyle = "black"; ctx.fill(); ctx.lineWidth = 1; ctx.strokeStyle = "black"; ctx.stroke(); } if (p2s == 1) { // draw p2 shot. var radius = 2; ctx.beginPath(); ctx.arc(p2sx, p2sy, radius, 0, 2 * Math.PI, false); ctx.fillStyle = "black"; ctx.fill(); ctx.lineWidth = 1; ctx.strokeStyle = "black"; ctx.stroke(); } } function drawShip(x, y, deg, width, height, color) { var pos0 = rotate(x, y, x, y - (height / 2), deg); var pos1 = rotate(x, y, x + (width / 2), y + (height / 2), deg); var pos2 = rotate(x, y, x - (width / 2), y + (height / 2), deg); ctx.beginPath(); ctx.moveTo(pos0.x, pos0.y); ctx.lineTo(pos1.x, pos1.y); ctx.lineTo(pos2.x, pos2.y); ctx.lineTo(pos0.x, pos0.y); ctx.stroke(); ctx.fillStyle = color; ctx.fill(); } // This function uses barycentric coordinates to determine whether a point // is inside a triangle. The barycentric coordinates of a point with respect // to a triangle are a set of three numbers (alpha, beta, gamma) that describe // how the point can be expressed as a weighted sum of the vertices of the // triangle. If all three numbers are positive, the point is inside the triangle. // If any of the numbers is negative, the point is outside the triangle. function isPointInTriangle(x, y, x1, y1, x2, y2, x3, y3) { // Calculate the barycentric coordinates of the point with respect to the triangle const alpha = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); const beta = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); const gamma = 1 - alpha - beta; // Check if the point is inside the triangle return alpha > 0 && beta > 0 && gamma > 0; } ///// </script> </body> </html>
mygames.js
You will also need this, which is a small library of functions we came up with as we learned javascript. The original idea of this was to help Roger understand how to make a library of functions in javascript.
mygames.js
function rotate(ox, oy, x, y, r) { var xDiff = x - ox; var yDiff = y - oy; var rot = Math.atan2(xDiff, yDiff); var newRot = rot + (r * 3.141592653 / 180); var dx = Math.cos(newRot); var dy = Math.sin(newRot); var dist = Math.sqrt((xDiff*xDiff)+(yDiff*yDiff)); return { x: ox + (dx * dist), y: oy + (dy * dist) } } function getMousePos(canvas, event) { var rect = canvas.getBoundingClientRect(); return { x: event.clientX - rect.left, y: event.clientY - rect.top }; } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function getRandomColor() { var color = ''; while (color.length != 7) { color = "#" + Math.random().toString(16).slice(2, 8); } return color; } function colorScreen(c) { ctx.fillStyle = c; ctx.fillRect(0, 0, MAX_W, MAX_H); } function clearScreen() { colorScreen("#FFFFFF"); }
theme.css
.title { font-size: 20px; } .mytd { border: 1px solid black; height: 50px; width: 50px; }
shooty_ships.txt · Last modified: 2023/11/06 01:02 by appledog