Luke Jones

jsdiver - commit 4e4e190

Upload initial files from submission release4e4e19039720a5bb471132d27c2f8b4df2988b20LukeJ<152485046+LukePJ25@users.noreply.github.com>2024-11-15T11:48:16Z
diff --git a/README.md b/README.md new file mode 100644 index 0000000..d24eb3e --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# JSDiver + +--- + +**JSDiver** is a simple HTML5 canvas game where you play as a skydiver, jumping from a plane and dodging obstacles in the sky as they appear. + +A demonstration of JSDiver can be played [here](https://users.aber.ac.uk/luj36/CS25320/jsdiver/). + +1. [Gameplay](#gameplay) + 1. [Controls](#controls) + 2. [Obstacles](#obstacles) + 1. [Large Obstacles](#large-obstacles) + 3. [Difficulty](#difficulty) + 4. [Debugging](#debugging) +2. [Installation](#installation) +3. [Sources](#sources) + +--- + +# Gameplay + +## Controls + +Use the arrows keys, or WASD, to move the player in all directions. + +## Obstacles + +As you fall, different obstacles like birds and kites will appear and move around. You need to avoid these objects. + +![Obstacles](/assets/readme/dangers.png) + +### Large Obstacles + +You will also come across large obstacles, like planes and helicopters. Before these obstacles appear, certain areas of the screen will flash red for a few moments. These areas need to be avoided, as the obstacle will soon appear and sweep across that region. + +## Difficulty + +There are three difficulty modes in JSDiver, _Easy_, _Medium_ and _Hard_. You can select the difficulty from the main menu, either by clicking on the difficulty level, or using the arrow keys to select them. + +Each difficulty mode will have different effects on gameplay: + +| | Easy | Medium | Difficulty | +|:--------------------------------|:------------------|:-----------------|:-----------------| +| Maximum Health | 5 | 5 | 3 | +| Obstacle Spawning Frequency | Every few seconds | Often | Constant! | +| Big Obstacle Spawning Frequency | Every 200 Points | Every 100 Points | Every 50 Points! | + +## Debugging + +You can press 'U' to toggle debugging mode, which will allow you to see debugging information such as a variable watch and bounding boxes for obstacles and the player. + +--- +# Installation + +The game can be deployed to an Apache Webserver using PostgreSQL. Clone the repository to the website's root. + +Within the `php` directory, there are two files, `db_secrets.php` and `get_connection.php`. +1. `db_secrets.php` should be configured to contain the correct parameters for connection to the PostgreSQL database. + 1. `DB_DRIVER` should be left as `pgsql`. + 2. `DB_HOST` should be set to your PostgreSQL hostname. + 3. `DB_NAME` should be the name of the database. + 4. `DB_USER` should be your username. + 5. `DB_PASSWORD` should be your password. +2. Inside `get_connection.php`, ensure that the reference to `db_secrets.php` on line 6 is corrected. + +>For the sake of security, ensure that your `db_secrets.php` is not within your website's directory tree. + +A table will be created inside your database automatically by `save_score.php`. You can configure the name you'd like to assign to the table, but ensure it is maintained between `save_scores.php` and `retrieve_scores.php`. + +--- +# Sources + +PHP and JavaScript leaderboard functions in `leaderboard.js`, `get_connection.php`, `retrieve_scores.php` and `save_score.php` were modified from original code provided by Edel Sheratt in October 2022. + diff --git a/assets/graphics.png b/assets/graphics.png new file mode 100644 index 0000000000000000000000000000000000000000..453e3a867fb32b9e24e4e87f9ca7ea2f429064df GIT binary patch literal 58203 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 bxbc4g?QXAE1w6wO00000NkvXXu0mjf;M=BT literal 0 HcmV?d00001 diff --git a/assets/readme/dangers.png b/assets/readme/dangers.png new file mode 100644 index 0000000000000000000000000000000000000000..cc75d4858b190c20b5970888da5569e7fd079b1c GIT binary patch literal 15932 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 OXsYVmFTQ6L{{I1~4Y6kc literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..e078e5b --- /dev/null +++ b/index.html @@ -0,0 +1,90 @@ +<!-- +Main Page for JSDiver +Luke Jones +--> + +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>JSDiver</title> + <link rel="stylesheet" href="style.css"> + <script src="js/leaderboard.js"></script> + <script> + let scoreSubmitted = false; + </script> +</head> +<body> +<img id="graphicSheet" alt="The game's sprite sheet." style="display: none;" src="assets/graphics.png"> + +<div id="main"> + <div id="content"> + <h1>JSDiver</h1> + <canvas width="700" height="800" onClick="requestStart()" id="gamebox"></canvas> + <h2>Leaderboard</h2> + <div id="leaderEntryItems"> + <label class="entryItem" for="scoreNameSubmit">Enter Your Name:</label> + <input id="scoreNameSubmit" class="entryItem" type="text" name="name"> + <button class="entryItem" onclick="requestScoreSubmit()">Submit</button> + <p id="leaderSubmitOutput"></p> + </div> + <table id="leaderboards"> + <thead> + <tr> + <td> + <em>Easy</em> + </td> + <td> + <em>Medium</em> + </td> + <td> + <em>Hard</em> + </td> + </tr> + </thead> + <tbody> + <tr> + <td class="smallTable"> + <table class="leaderboard"> + <thead> + <tr> + <th class="leader-heading">Name</th> + <th class="leader-heading">Score</th> + </tr> + </thead> + <tbody id="lb-easy"></tbody> + </table> + </td> + <td class="smallTable"> + <table class="leaderboard"> + <thead> + <tr> + <th class="leader-heading">Name</th> + <th class="leader-heading">Score</th> + </tr> + </thead> + <tbody id="lb-medium"></tbody> + </table> + </td> + <td class="smallTable"> + <table class="leaderboard"> + <thead> + <tr> + <th class="leader-heading">Name</th> + <th class="leader-heading">Score</th> + </tr> + </thead> + <tbody id="lb-hard"></tbody> + </table> + </td> + </tr> + </tbody> + </table> + </div> + + <script src="js/jsdiver.js"></script> +</div> + +</body> +</html> \ No newline at end of file diff --git a/js/jsdiver.js b/js/jsdiver.js new file mode 100644 index 0000000..b4467e1 --- /dev/null +++ b/js/jsdiver.js @@ -0,0 +1,1035 @@ +/* +* The main javascript for JSDiver +* jsiver.js +* Luke Jones +*/ + + +// Utility functions for general use +// Clamp +function clamp(v, mn, mx) { + return Math.max(mn, Math.min(v, mx)); +} + +// Check if value is in range +function rangeCheck(v, mn, mx) { + return (v <= mx && v >= mn); +} + +// Linear Interpolation +function lerp(va, vb, ratio) { + return va + ratio * (vb - va); +} + +// World Values +const WORLD_LEFT_LIMIT = 50; +const WORLD_RIGHT_LIMIT = 650; +const WORLD_TOP_LIMIT = 50; +const WORLD_BOTTOM_LIMIT = 750; + +// Performance Value +let frameInterval, frameNow, frameThen, elapsed; + +// Game Values +let debug = false; // Prints debug to console, draws extra debugging information to canvas. User can press "U" to enable debugging. + +const GameState = { + MENU: 'MENU', + OPENING_ANIM: 'OPENING_ANIM', + PLAYING: 'PLAYING', + CLOSING_ANIM: 'CLOSING_ANIM' +}; +let currentState = GameState.MENU; + +let mainRunning = false; +let gameInitialised = false; +let score = 0; // Increased by 1 with each frame of game activity. Used for calculations. Final and Displayed score is 10x Smaller. +let lastScore = 0; // Score saved from previous round. Reset when the player restarts. +let lastScoreDifficulty = 0; // The difficulty the user was just playing at when they scored. +let obstacles = []; // Stores 2D arrays containing 7 values, obstacle type, obstacle X, obstacle Y, obstacle "size" (radius), and the side of the canvas on which the object spawned, whether the obstacle has been hit already, the "angle of travel" (a value between 0 and 4 deciding how far they travel left/right) +let bigObstacles = []; // Stores 2D arrays containing 4 values, type (0 for plane, 1 for helicopter), side (0 for top/left, 1 for bottom/right), spawned (whether obstacle is in countdown or spawned), counter (how far along across the screen the obstacle is), hit - whether the obstacle has been hit already +let difficulty = 0; // 0 is easy, 1 is medium, 2 is hard. This is selected at the start but defaults to 0. +let startSpeed; +let graphics = document.getElementById("graphicSheet"); + +// Obstacle Spawning Frequencies +const smallFrequency = [100, 50, 25]; +const bigFrequency = [2000, 1000, 500]; +let bigObstacleActive = false; // If true, the game won't spawn small obstacles while the big one is active. + +// Controls +// Storing whether keys are held down +let left_down = false, right_down = false, down_down = false, up_down = false, click_down = false; +// Stores whether the keys are held down for 1 frame. +let left_tapped = false, right_tapped = false, space_tapped = false; + +// Player Graphic Coordinates for each direction of travel +const directionalPlayerGraphics = { + 'N': { x: 64, y: 32 }, + 'NE': { x: 128, y: 32 }, + 'E': { x: 32, y: 32 }, + 'SE': { x: 128, y: 0 }, + 'S': { x: 64, y: 0 }, + 'SW': { x: 96, y: 0 }, + 'W': { x: 0, y: 32 }, + 'NW': { x: 96, y: 32 } +}; + +// Player Values +let playerposx = 350; +let playerposy = 32; +let playeraccx = 0; +let playeraccy = 0; +let playervelx = 0; +let playervely = 0; +let playersize = 96; +let playerHealth = 5; +let maxPlayerHealth = 5; +let collision_cooldown = false; + +// Main Menu Values + +let menuInitialised = false; +let openingAnimTimer = 0; +let closingAnimTimer = 0; +let selectedDifficulty = 0; +// List of UI elements from graphics sprite sheet. 0 = , 1 = , 2 = , 3 = , 4 = +// [x position on sheet, y position on sheet, width on sheet, height on sheet] +let ui_graphics = [ + [160, 64, 32, 16], // Jump Button + [160, 96, 32, 16], // Hovered Jump Button + [160, 80, 32, 16], // Pressed Jump Button + [192, 144, 32, 32], // Key Image + [224, 144, 32, 32], // Pressed Key Image + [0, 128, 48, 16], // Difficulty Easy + [48, 128, 48, 16], // Difficulty Easy Hover + [0, 144, 48, 16], // Difficulty Medium + [48, 144, 48, 16], // Difficulty Medium Hover + [0, 160, 48, 16], // Difficulty Hard + [48, 160, 48, 16], // Difficulty Hard Hover + [192, 128, 48, 16], // Score Counter +] +let mousepos = [0, 0]; +// Current UI elements on the screen. +// [x pos, y pos, x size, y size, 'NAME', graphic from spritesheet, alternative graphic from spritesheet] +let ui_elements = []; + +function createUIElement(px, py, sx, sy, name, gindex, altgindex) { + ui_elements.push([px, py, sx, sy, name, gindex, altgindex]); +} + +function mouseOverElement(element) { + return rangeCheck(mousepos[0], element[0], element[0] + element[2]) && rangeCheck(mousepos[1], element[1], element[1] + element[3]); +} + +const g_box = document.getElementById("gamebox"); +const g_context = g_box.getContext("2d"); +g_context.imageSmoothingEnabled = false; +g_context.shadowColor = "rgba(0,0,0,0.25)"; +g_context.shadowBlur = 20; + +function hurtPlayer() { + createParticle(0, playerposx+32, playerposy+32, 1, 1, 1, 1); + createParticle(1, playerposx, playerposy, 0.8, 1, 1, 1); + playerHealth = clamp(playerHealth-1,0,maxPlayerHealth); + if (playerHealth <= 0) { + currentState = GameState.CLOSING_ANIM; + bigObstacles = []; + lastScore = Math.trunc(score / 10); + lastScoreDifficulty = difficulty; + } +} + +// Closing Animation Values +let closingAnimInitialised = false; +let playerStartPos = []; // The position where the players animation should start from +let playerCurrentAnimPos = []; // How far the player has fallen +const playerFinalAnimPos = [220,670]; // Where the player should land +let mountainHit = false; // Has the animation finished yet? + +// Particle Image Parameters +let particleImages = [ + [0, 64, 32, 32, -16, -16, 64, 64], // Smack + [32, 64, 32, 32, 16, 16, 64, 64], // Shock + [96, 64, 64, 32, 32, 16, 128, 64], // Large Cloud + [96, 96, 32, 32, 16, 16, 256, 256], // Small Cloud +]; +// Particle Age Limit per type - basically how long to let them exist before culling them off +let particleAges = [ + 6, + 20, + 1000, + 200, +] +// Existing Particle Objects +// Particles are stored as arrays and contain 7 parameters: type, x position, y position, scale, age, opacity, and whether it's a foreground (1) or background (0) particle. +// 0 = Smack, 1 = Shock, 2 = Large Cloud, 3 = Small Cloud +let particles = []; + +function createParticle(type, startPosX, startPosY, startingOpacity, bgfg) { + particles.push([type, startPosX, startPosY, 1, 0, startingOpacity, bgfg]); +} + +// Creates obstacle. big dictates whether obstacle should be a standard +// small one or a big one which fills the entire display. +function create_obstacle(big) { + if (big) { + let type, side; + if (Math.random() < 0.5) { + type = 0; // It's a plane + } else { + type = 1; // It's a helicopter + } + if (Math.random() < 0.5) { + side = 0; + } else { + side = 1; + } + bigObstacles.push([type, side, false, 0, false]); + bigObstacles.sort(); + } else { + let obstacleX = clamp(Math.random() * g_box.width, WORLD_LEFT_LIMIT, WORLD_RIGHT_LIMIT); + let obstacleY = g_box.height; + let obstacleSize = 96; + let obstacleDirection; // Dictated by the side of the screen it spawns on. E.g., if it's on the right side, then obstacleDirection = -1 (it travels left) + + // Type selector. Dictates the probability of a certain obstacle type. + // 90% chance of Bird [0] + // 10% chance of Kite [1] + let obstacleType; + let obstacleTypeSelector = Math.random() * 100; + if (rangeCheck(obstacleTypeSelector, 0, 90)) { + obstacleType = 0; + } else { + obstacleType = 1; + } + if (obstacleX > g_box.width / 2) { + obstacleDirection = -1; + } else { + obstacleDirection = 1; + } + obstacles.push([obstacleType, obstacleX, obstacleY, obstacleSize, obstacleDirection, false, Math.random()*3]); + obstacles.sort(); + } + +} + +function trigger_collision_cooldown() { + collision_cooldown = true; + setTimeout(function () { + collision_cooldown = false; + }, 250); +} + +// Process obstacle positions. If anim is true, they will move much faster to +// ensure they are cleared from the screen during the closing animation +function obstaclePositionTick(anim) { + let animSpeed = anim ? 2 : 1; // If anim enabled, move objects 2 times faster + // Obstacle Movement Updates + obstacles.forEach(function (obstacle) { + obstacle[2] -= (animSpeed * 5 * (1 + (score / 1000))); // Increases obstacle position, with the change in distance slightly larger with each score point. + + obstacle[1] += obstacle[4] * obstacle[6] * (1 + (score / 1000)); // Move obstacle left/right slightly with same idea as vertical movement. + }); + + // Removes obstacles no longer on screen + obstacles = obstacles.filter(function (obstacle) { + return obstacle[2] >= -128; + }); + + // Big Obstacle Movement Updates + bigObstacles.forEach(function (bigObstacle) { + if (bigObstacle[2]) { + // Move obstacle along + if(bigObstacle[4]){ + bigObstacle[3] += 20; + } else { + bigObstacle[3] += 10; + } + if (bigObstacle[3] >= 1850) { + bigObstacles = []; // Empty array, object is gone + bigObstacleActive = false; + } + } else { + bigObstacle[3]++; + bigObstacle[3]*=animSpeed; + // If obstacle has counted down enough + if (bigObstacle[3] > 150) { + // Set spawn flag to true + bigObstacle[2] = true; + bigObstacle[3] = 0; + } + } + }); +} + +function phys_update() { + + // Function to check if a given object is "colliding" with the player + // Essentially just compares the distance between the two and returns true if it's less than r. + // x is the X position of the object + // y is the Y position of the object + // r is the radius around the object in which presence is considered collision + function checkPlayerRadialCollision(x, y, r) { + return (Math.sqrt(Math.pow((x - playerposx), 2) + Math.pow(y - playerposy, 2)) <= r); + } + + // Function to check if the player's bounding box lies within a certain given zone. + // x is the left of the box + // y is the top of the box + // w is the width of the box + // h is the height of the box + function checkPlayerZoneCollision(x,y,w,h){ + if((playerposy - (playersize / 2))>(y+h)){return false;} + if((playerposx - (playersize / 2))>(x+w)){return false;} + if((playerposy + (playersize / 2))<y){return false;} + return (playerposx + (playersize / 2)) >= x; + + } + + // Physics controller + if (currentState === GameState.PLAYING) { + // Player Movement Update + if (right_down && !left_down) { + playeraccx = 1; + } else if (left_down && !right_down) { + playeraccx = -1; + } else { + playeraccx = 0; + } + if (up_down && !down_down) { + playeraccy = -1; + } else if (down_down && !up_down) { + playeraccy = 1; + } else { + playeraccy = 0; + } + playervelx = (playervelx + playeraccx) * 0.95; + playervely = (playervely + playeraccy) * 0.95; + playerposx += playervelx; + playerposy += playervely; + + // Clamp player position to world + if (!rangeCheck(playerposx, WORLD_LEFT_LIMIT, WORLD_RIGHT_LIMIT)) { + playerposx = clamp(playerposx, WORLD_LEFT_LIMIT, WORLD_RIGHT_LIMIT); + playeraccx = 0; + playervelx = 0; + } + if (!rangeCheck(playerposy, WORLD_TOP_LIMIT, WORLD_BOTTOM_LIMIT)) { + playerposy = clamp(playerposy, WORLD_TOP_LIMIT, WORLD_BOTTOM_LIMIT); + playeraccy = 0; + playervely = 0; + } + + // Process Obstacle Motion + obstaclePositionTick(false); + + // Collision Checks + obstacles.forEach(function (obstacle) { + if (!collision_cooldown) { + let col = checkPlayerRadialCollision(obstacle[1], obstacle[2], obstacle[3]); + if (col) { + if (!obstacle[5]) { + trigger_collision_cooldown(); + hurtPlayer(); + obstacle[5] = true; + } + } + } + }); + bigObstacles.forEach(function (bigObstacle) { + // Get obstacle positions + let obsy; + let obsx; + if (bigObstacle[1] === 0) { // Is at top/left + obsy = 0; + obsx = 0; + } else { // Is at bottom/right + obsy = g_box.height/2; + obsx = g_box.width/2; + } + let col; + g_context.fillStyle = 'rgba(255,0,255,0.5)' + if(bigObstacle[2]){ // If the obstacle is currently active. + if (bigObstacle[0] === 0) { // Is plane + col = checkPlayerZoneCollision(bigObstacle[3]-1024, obsy+144, 1024, g_box.height*0.32) + if(debug){ // If debugging enabled, draw rect over bounding box + g_context.fillRect(bigObstacle[3]-1024, obsy+144, 1024, g_box.height*0.32); + } + } else { // Is Helicopter + col = checkPlayerZoneCollision(obsx, g_box.height-bigObstacle[3], g_box.width/2, 404) + if(debug){ // If debugging enabled, draw rect over bounding box + g_context.fillRect(obsx, g_box.height-bigObstacle[3], g_box.width/2, 404); + } + } + if(col){ + if(!bigObstacle[4]){ + bigObstacle[4] = true; + hurtPlayer(); + } + } + } + }); + } +} + +// Shared draw functions +let fade = true; // If true, game will fade out slightly each frame, and out if false. +let fadeValue = 1; // Fade level, representing fade screen alpha between 0 and 1. +// These start at true and 1 because the game starts faded out. + +// Draws Fade Screen +function drawFade() { + if (fade) { + if (fadeValue < 1) { + fadeValue = clamp(fadeValue + 0.025, 0, 1); + } + } else { + if (fadeValue > 0) { + fadeValue = clamp(fadeValue - 0.025, 0, 1); + } + } + g_context.fillStyle = 'rgba(255, 255, 255,' + fadeValue + ')'; + g_context.fillRect(0, 0, g_box.width, g_box.height); +} + +// Draws game sky +function drawBackground() { + // Draw the sky gradient background + const sky_gradient = g_context.createLinearGradient(0, 0, 0, g_box.height); + sky_gradient.addColorStop(0, '#DEF9FF'); + sky_gradient.addColorStop(1, '#5EB6FF'); + g_context.fillStyle = sky_gradient; + g_context.fillRect(0, 0, g_box.width, g_box.height); + // Draw the mountain shape + g_context.beginPath(); + g_context.moveTo(0, g_box.height+10); + g_context.lineTo(-10, 710); + g_context.lineTo(200, 630); + g_context.lineTo(380, 690); + g_context.lineTo(540, 720); + g_context.lineTo(g_box.width+10, 730); + g_context.lineTo(g_box.width+10, g_box.height+10); + g_context.closePath(); + g_context.fillStyle = '#9ebd99'; + g_context.save(); + g_context.shadowColor = 'rgba(255,255,255,0.2)'; + g_context.shadowBlur = 20; + g_context.fill(); + g_context.strokeStyle = '#567c4d'; + g_context.stroke(); + g_context.restore(); + // If the closing animation has been played, draw a plaster on the mountain. + if(mountainHit){ + g_context.drawImage(graphics, 128, 96, 16, 16, playerFinalAnimPos[0], playerFinalAnimPos[1], 32, 32); + } + // Draw a new overlay to emulate a fog effect + const atmospheric_gradient = g_context.createLinearGradient(0, 0, 0, g_box.height); + atmospheric_gradient.addColorStop(0, 'rgba(255,255,255,0)'); + atmospheric_gradient.addColorStop(0.825, 'rgba(255,255,255,0)'); + atmospheric_gradient.addColorStop(1, 'rgba(221,247,255,0.8)'); + g_context.fillStyle = atmospheric_gradient; + g_context.fillRect(0, 0, g_box.width, g_box.height); +} + +// Draw Player +function drawPlayer(standingOnPlane, dx, dy, scale){ + let player_sprite_x = 32; + let player_sprite_y = 0; + let player_sprite_w = 32; + let player_sprite_h = 32; + let direction; + if(standingOnPlane){ // If the menu is active + g_context.drawImage(graphics, player_sprite_x, player_sprite_y, player_sprite_w, player_sprite_h, dx+42, dy, scale*playersize, scale*playersize); + } else { // Otherwise, the player must be playing + player_sprite_x = 0; + player_sprite_y = 0; + direction = ''; + if (up_down) { + direction += 'N'; + } else if (down_down) { + direction += 'S'; + } + if (left_down) { + direction += 'W'; + } else if (right_down) { + direction += 'E'; + } + if (direction in directionalPlayerGraphics) { + player_sprite_x = directionalPlayerGraphics[direction].x; + player_sprite_y = directionalPlayerGraphics[direction].y; + } + + g_context.drawImage(graphics, player_sprite_x, player_sprite_y, player_sprite_w, player_sprite_h, dx - (scale*playersize / 2), dy - (scale*playersize / 2), scale*playersize, scale*playersize); + + if (debug) { // If debugging enabled, drawGame box around player + g_context.fillStyle = "rgba(255,0,0,0.5)"; + g_context.fillRect(dx - (playersize / 2), dy - (playersize / 2), playersize, playersize); + } + } + +} + +// Draw plane across canvas at given y position +function drawPlane(y) { + let planeWidth = 178; + let yvib = Math.random() - 0.5 + y += yvib; + for (let i = 0; i < (g_box.width / planeWidth) + 1; i++) { + g_context.drawImage(graphics, 192, 0, 64, 64, (planeWidth * i) - (planeWidth / 2), y, planeWidth, planeWidth); + if(i === Math.trunc(((g_box.width / planeWidth) + 1)/2)){ + g_context.drawImage(graphics, 192, 64, 64, 64, (planeWidth * i) - (planeWidth / 2), y, planeWidth, planeWidth); + drawPlayer(true, (planeWidth * i) - (planeWidth / 2), 62+yvib, 1); + } + } +} + +// Draw a red pulse on a portion of the screen. Side 0=Top/Bottom 1=Left/Right, Alt 0=Top/Left 1=Bottom/Right (Depends on Side), Count (used to calculate alpha) +function drawPulse(side, alt, count) { + g_context.fillStyle = 'rgba(255, 0, 0,' + (0.4 * (Math.sin(count / 5))) + ')'; + if (side === 0) { + if (alt === 0) { + g_context.fillRect(0, 0, g_box.width, g_box.height / 2); + } else { + g_context.fillRect(0, g_box.height / 2, g_box.width, g_box.height / 2); + } + } else { + if (alt === 0) { + g_context.fillRect(0, 0, g_box.width / 2, g_box.height); + } else { + g_context.fillRect(g_box.width / 2, 0, g_box.width / 2, g_box.height); + } + } +} + +// Draw big obstacle +function drawBigObstacle(side, alt, count) { + let obsy; + let obsx = g_box.width/2; + if (alt === 0) { + obsy = 0; + } else { + obsy = (g_box.height / 2); + } + if (side === 0) { // Is plane + g_context.drawImage(graphics, 0, 176, 48, 32, count-1024, obsy, 288, 128); // Draw Plane Tail + g_context.drawImage(graphics, 0, 208, 256, 48, count-1024, obsy+128, 1024, 256); // Draw Plane Body + } else { // Is Helicopter + g_context.save(); + if (alt === 0) { + g_context.scale(-1, 1); + obsx = -obsx; + } + g_context.drawImage(graphics, 176, 176, 80, 32, obsx, g_box.height - count, g_box.width / 2, 116); // Draw Propellers + g_context.drawImage(graphics, 96, 128, 80, 80, obsx, g_box.height - count, g_box.width / 2, 404); // Draw Body + g_context.restore(); + } +} + +function drawMenu() { + drawBackground(); + // Draw UI elements + drawPlane(10); + + // Draw selection box over currently selected difficulty + switch (selectedDifficulty){ + case 0: + g_context.fillStyle = 'rgba(0,255,0,0.5)'; + break; + case 1: + g_context.fillStyle = 'rgba(255,153,0,0.5)'; + break; + case 2: + g_context.fillStyle = 'rgba(255,0,0,0.5)'; + break; + default: + g_context.fillStyle = 'rgba(255,255,255,0.5)'; + break; + } + g_context.fillRect(16 + (225 * selectedDifficulty), 380, 220, 100); + // Draw Buttons + ui_elements.forEach(function (item) { + g_context.save(); + if(item[5]===0){ + if (selectedDifficulty === 0) { + g_context.filter = 'hue-rotate(100deg)'; + } else if (selectedDifficulty === 1) { + g_context.filter = 'hue-rotate(50deg)'; + } + } + if (mouseOverElement(item)) { // If the user is currently hovering over the item, draw alt graphic + g_context.drawImage(graphics, ui_graphics[item[6]][0], ui_graphics[item[6]][1], ui_graphics[item[6]][2], ui_graphics[item[6]][3], item[0], item[1], item[2], item[3]); + } else { // Otherwise, draw normal graphic + g_context.drawImage(graphics, ui_graphics[item[5]][0], ui_graphics[item[5]][1], ui_graphics[item[5]][2], ui_graphics[item[5]][3], item[0], item[1], item[2], item[3]); + } + g_context.restore(); + }); + g_context.font = "bolder 40px Arial" + g_context.fillStyle = '#fff'; + g_context.fillText("Select a Difficulty:", 190, 300); + g_context.fillStyle = '#000'; + g_context.strokeText("Select a Difficulty:", 190, 300); + + if(lastScore!==0){ + g_context.font = "bolder 30px Arial" + g_context.fillStyle = '#fff'; + g_context.fillText("Score: "+lastScore, 270, 70); + g_context.fillText("Submit your score to the leaderboard!", 100, 120); + g_context.fillStyle = '#000'; + g_context.strokeText("Score: "+lastScore, 270, 70); + g_context.strokeText("Submit your score to the leaderboard!", 100, 120); + } + +} + +// Draw Obstacles +function drawObstacles(){ + obstacles.forEach(function (obstacle) { + if (obstacle[0] === 0) { + let flap = 0; + if ((score % 50) < 25) { + flap += 32; + } + g_context.save(); + if (obstacle[4] === 1) { // Draw bird facing direction of travel + g_context.scale(-1, 1); + g_context.drawImage(graphics, flap, 96, 32, 32, -obstacle[1] - (obstacle[3] / 2), obstacle[2] - (obstacle[3] / 2), obstacle[3], obstacle[3]); + } else { + g_context.drawImage(graphics, flap, 96, 32, 32, obstacle[1] - (obstacle[3] / 2), obstacle[2] - (obstacle[3] / 2), obstacle[3], obstacle[3]); + } + g_context.restore(); + } else if (obstacle[0] === 1) { + let kiteCorner = [obstacle[1] - 32,obstacle[2] - 48] + g_context.drawImage(graphics, 64, 64, 32, 48, kiteCorner[0], kiteCorner[1], 64, 96); + // Draw kite string + g_context.save(); + for(let j=0;j<5;j++){ + g_context.globalAlpha = 1-(j/5); + g_context.drawImage(graphics, 64, 112, 32, 16, kiteCorner[0]-(64*j)-64, kiteCorner[1]+(30*j)+96, 64, 32); + } + g_context.restore(); + } else { + g_context.fillStyle = "#f00"; + g_context.fillRect(obstacle[1], obstacle[2], obstacle[3], obstacle[3]); + } + if (debug) { // If debugging enabled, drawGame box around obstacle. + g_context.fillStyle = "rgba(187,0,255,0.5)"; + g_context.fillRect(obstacle[1] - (obstacle[3] / 2), obstacle[2] - (obstacle[3] / 2), obstacle[3], obstacle[3]); + } + }); +} + +// Draw and tick selected particles +function drawParticle(particle, mode) { + if (particle[6] === mode) { + g_context.save(); + g_context.globalAlpha = particle[5]; + g_context.drawImage(graphics, particleImages[particle[0]][0], particleImages[particle[0]][1], particleImages[particle[0]][2], particleImages[particle[0]][3], particle[1] + particleImages[particle[0]][4] - (particleImages[particle[0]][6] * particle[3]) / 2, particle[2] + particleImages[particle[0]][5] - (particleImages[particle[0]][7] * particle[3]) / 2, particleImages[particle[0]][6] * particle[3], particleImages[particle[0]][7] * particle[3]); + particle[4]++; + switch (particle[0]) { + case 0: + particle[5] *= 0.9; + break; + case 1: + particle[3] *= 1.05; + particle[5] *= 0.95; + break; + case 2: + particle[2] -= 2; + break; + case 3: + particle[2] -= 15; + break; + case 4: + particle[1] -= playeraccx; + particle[2] -= playeraccy; + particle[3] *= 0.98; + particle[5] *= 0.98; + break; + default: + break; + } + g_context.restore(); + } + // Remove particles past age limit + particles = particles.filter(function (particle) { + return particle[4] < particleAges[particle[0]]; + }); +} + +// Draw Closing Animation Frame +function drawClosingAnimation(){ + // Fill Background + drawBackground(); + + // Move Obstacles Off-Screen + obstaclePositionTick(true); + // Draw Obstacles Leaving + drawObstacles(); + // Draw big obstacle leaving, if it exists. + bigObstacles.forEach(function (bigObstacle){ + if(bigObstacle[2]){ + drawBigObstacle(bigObstacle[0], bigObstacle[1], bigObstacle[3]); + } else { + drawPulse(bigObstacle[0], bigObstacle[1], bigObstacle[3]); + } + }); + + // Draw Player + g_context.save(); + g_context.translate(playerCurrentAnimPos[0], playerCurrentAnimPos[1]); + g_context.rotate(clamp(5-(closingAnimTimer/20),0,5) * Math.PI); + if(closingAnimTimer < 100){ // If the animation is playing the part before he hits the mountain, draw the player + drawPlayer(false, 0, 0, clamp(1-(closingAnimTimer/100),0,1)); + } + g_context.restore(); + + // Ensure to get particles off-screen smoothly + particles.forEach(function(particle){ + drawParticle(particle, 1); + drawParticle(particle, 0); + }); +} + +// Draw Game Frame +function drawGame() { + // Fill Background + drawBackground(); + + // Background Clouds (Particles) + if ((Math.random() * 100) <= 1) { // 1% chance in each frame of cloud spawning + createParticle(2, Math.random() * g_box.width, g_box.height + 64, 0.5, 0); + } + + // Draw and Tick background Particles + particles.forEach(function (particle) { + if (particle[6] === 0) { + drawParticle(particle, 0); + } + }); + + // Draw Player (falling) + drawPlayer(false, playerposx, playerposy, 1); + + // Draw Obstacles + drawObstacles(); + + // Draw big obstacle, if it exists. + bigObstacles.forEach(function (bigObstacle){ + if(bigObstacle[2]){ + drawBigObstacle(bigObstacle[0], bigObstacle[1], bigObstacle[3]); + } else { + drawPulse(bigObstacle[0], bigObstacle[1], bigObstacle[3]); + } + }); + + // Create Foreground Particles + if ((Math.random() * 100) <= 1) { // 1% chance in each frame of foreground cloud spawning + createParticle(3, Math.random() * g_box.width, g_box.height + 64, 0.5, 1); + } + + // Draw and Tick foreground Particles + particles.forEach(function (particle) { + if (particle[6] === 1) { + drawParticle(particle, 1); + } + }); + + + // Draw Interface + g_context.fillStyle = "#ccf8aa"; + g_context.font = "bolder 30px Consolas"; + g_context.shadowColor = "rgba(0,0,0,1)"; + g_context.shadowBlur = 5; + g_context.drawImage(graphics, ui_graphics[11][0], ui_graphics[11][1], ui_graphics[11][2], ui_graphics[11][3], 8, g_box.height - 64, 144, 48); + g_context.fillText(String(Math.trunc(score / 10)), 20, g_box.height - 30); + + // Health Bar + let health_bar_position = [170, 745, 4]; // Top Left Position and Heart Padding + function drawHeart(index, state) { + const xOffset = health_bar_position[0] + (index * (32 + health_bar_position[2])); + const imageX = (state === 3) ? 128 : 144; + g_context.drawImage(graphics, imageX, 112, 16, 16, xOffset, health_bar_position[1], 32, 32); + } + + for (let i = 0; i < maxPlayerHealth; i++) { + if (playerHealth > i) { + drawHeart(i, 3); + } else if (playerHealth === i) { + drawHeart(i, 2); + } else { + drawHeart(i, 1) + } + } + + // Reset Shading + g_context.shadowColor = "rgba(0,0,0,0.25)"; + g_context.shadowBlur = 20; +} + +function requestStart() { + if (!mainRunning) { + frameInterval = 1000/60; + frameThen = performance.now(); + frameNow = performance.now(); + elapsed = frameNow - frameThen; + gameRuntimeHandler(); + } + mainRunning = true; +} + +function gameRuntimeHandler(){ + frameNow = performance.now(); + elapsed = frameNow - frameThen; + if (elapsed >= frameInterval) { + frameThen = frameNow - (elapsed % frameInterval); + main(); + } + requestAnimationFrame(gameRuntimeHandler); +} + +// Function to draw debug menu overlay if debugging is enabled. +let debuggingItems; +let spacing = 12; +function drawDebugMenu() { + debuggingItems = [ + ["FPS:.................: ", Math.trunc(1000/elapsed)], + ["Debug:...............: ", debug], + ["Score:...............: ", score], + ["Difficulty:..........: ", difficulty], + ["Health:..............: ", playerHealth], + ["fade:................: ", fade], + ["fadeValue:...........: ", fadeValue], + ["bigObstacleActive....: ", bigObstacleActive], + ["bigObstacles.........: ", bigObstacles], + ["mousepos.............: ", mousepos], + ["selectedDifficulty...: ", selectedDifficulty] + ]; + g_context.save(); + g_context.shadowBlur = 0; + g_context.fillStyle = 'rgba(0,0,0,0.5)'; + g_context.fillRect(0,0,300,spacing*(1+debuggingItems.length)); + g_context.fillStyle = '#fff'; + g_context.font = '12px Consolas'; + for(let i = 0;i<debuggingItems.length;i++){ + g_context.fillText(debuggingItems[i][0]+debuggingItems[i][1], 0, spacing*(i+1), 300); + } + g_context.restore(); +} + +// Start game function, called from Menu +function startGame(){ + currentState = GameState.OPENING_ANIM; + fade = true; + scoreSubmitted = false; +} + +// Main Gameloop Function. Called with every frame, +// ensuring logic is executed per game-flow, calling +// for physics tick and draw updates. +function main() { + if (currentState === GameState.MENU) { // If the player is currently at the menu + if (!menuInitialised) { + createUIElement(285, 600, 128, 64, 'STARTBTN', 0, 1); + createUIElement(285, 600, 128, 64, '', 0, 1); + createUIElement(30, 400, 192, 64, 'SELECTEASY', 5, 6); + createUIElement(255, 400, 192, 64, 'SELECTMEDIUM', 7, 8); + createUIElement(480, 400, 192, 64, 'SELECTHARD', 9, 10); + menuInitialised = true; + fade = false; + } else { + drawMenu(); + if (click_down) { + ui_elements.forEach(function (element) { + if (mouseOverElement(element)) { + switch (element[4]) { + case 'STARTBTN': + startGame(); + break; + case 'SELECTEASY': + selectedDifficulty = 0; + break; + case 'SELECTMEDIUM': + selectedDifficulty = 1; + break; + case 'SELECTHARD': + selectedDifficulty = 2; + break; + default: + break; + } + } + }); + } + if (left_tapped) { + selectedDifficulty = clamp(selectedDifficulty-1,0,2); + } else if (right_tapped) { + selectedDifficulty = clamp(selectedDifficulty+1,0,2); + } else if (space_tapped) { + startGame(); + } + } + } else if (currentState === GameState.OPENING_ANIM) { // If the player has just pressed start + if (openingAnimTimer > 100) { + currentState = GameState.PLAYING; + openingAnimTimer = 0; + } else { + openingAnimTimer++; + } + } else if (currentState === GameState.PLAYING) { // If the game is active + if (!gameInitialised) { // If first frame/game uninitialised + gameInitialised = true + score = 0; + lastScore = 0; + lastScoreDifficulty = difficulty; + playerposx = 350; + playerposy = 32; + playervelx = 0; + playervely = 0; + playeraccx = 0; + playeraccy = 0; + obstacles = []; + bigObstacles = []; + bigObstacleActive = false; + collision_cooldown = false; + difficulty = selectedDifficulty; + if (difficulty === 0) { + maxPlayerHealth = 5; + startSpeed = 5; + } else if (difficulty === 1) { + maxPlayerHealth = 5; + startSpeed = 10; + } else { + maxPlayerHealth = 3; + startSpeed = 15; + } + playerHealth = maxPlayerHealth; + fade = false; + } else { // If game underway + drawGame(); + phys_update(); + score++; + if(!bigObstacleActive){ + if (score % smallFrequency[difficulty] === 0) { + create_obstacle(false); + } + if (score % bigFrequency[difficulty] === 0) { + bigObstacleActive = true; + create_obstacle(true); + } + } + } + } else if (currentState === GameState.CLOSING_ANIM) { // If player has died and menu not yet reached + // This code is for the closing animation which plays after the player's death. + if(!closingAnimInitialised){ // If the animation hasn't started yet... + closingAnimInitialised = true; + gameInitialised = false; + playerStartPos = [playerposx, playerposy]; + playerCurrentAnimPos = [playerposx, playerposy]; + closingAnimTimer = 0; + } + + // Closing Anim Timer + if (closingAnimTimer > 200){ + fade = true; + } + if (closingAnimTimer > 250) { // Play for roughly 5 seconds before reaching menu + closingAnimTimer = 0; + currentState = GameState.MENU; + fade = false; + closingAnimInitialised = false; + mountainHit = false; + playerStartPos = []; + playerCurrentAnimPos = []; + } else { + // Process animation + drawClosingAnimation(); + if(closingAnimTimer === 100){ + mountainHit = true; + createParticle(0, playerFinalAnimPos[0]+32, playerFinalAnimPos[1]+32, 1, 1); + createParticle(1, playerFinalAnimPos[0], playerFinalAnimPos[1], 0.4, 1); + } else { + playerCurrentAnimPos[0] = lerp(playerStartPos[0], playerFinalAnimPos[0], clamp(closingAnimTimer/100,0,1)); + playerCurrentAnimPos[1] = lerp(playerStartPos[1],playerFinalAnimPos[1], clamp(closingAnimTimer/100,0,1)); + } + closingAnimTimer++; + } + } + drawFade(); + left_tapped = false; + right_tapped = false; + space_tapped = false; + if (debug) { + drawDebugMenu(); + } +} + +// Input Handler +function handleKeys(input_event, press) { + let inp_key; + if (input_event != null) { + inp_key = input_event.key; + // In the event that the user is currently focused on a text field, prioritise that over game control. + if (document.activeElement.tagName.toLowerCase() === "input") { + return; + } + input_event.preventDefault(); + switch (inp_key) { + case "ArrowLeft": + case "A": + case "a": + left_down = press; + left_tapped = press; + break; + case "ArrowRight": + case "D": + case "d": + right_down = press; + right_tapped = press; + break; + case "ArrowUp": + case "W": + case "w": + up_down = press; + break; + case "ArrowDown": + case "S": + case "s": + down_down = press; + break; + case " ": + space_tapped = press; + break; + case "U": + case "u": + if (press) { + debug = !debug; + } + break; + default: + break; + } + } +} + +document.onkeydown = function (event) { + handleKeys(event, true); +}; +document.onkeyup = function (event) { + handleKeys(event, false); +}; +document.onmousemove = function (event) { + let canvasBounds = g_box.getBoundingClientRect(); + mousepos = [Math.trunc(event.clientX - canvasBounds.left), Math.trunc(event.clientY - canvasBounds.top)]; +}; +document.onmousedown = function () { + click_down = true; +}; +document.onmouseup = function () { + click_down = false; +}; + +// Draws the once-seen starter text. +g_context.fillStyle = '#000'; +g_context.font = "bolder 30px Arial"; +g_context.fillText("Click to Start...", 285, 400); \ No newline at end of file diff --git a/js/leaderboard.js b/js/leaderboard.js new file mode 100644 index 0000000..0bfee1d --- /dev/null +++ b/js/leaderboard.js @@ -0,0 +1,107 @@ +// Leaderboard handler for JSDiver +// Original PHP interaction adapted from code provided by Edel Sherratt from October 2022. + + +let output, nameEntry, table, easyCol, medCol, hardCol; + +// Ensure content is loading before defining entry elements +document.addEventListener("DOMContentLoaded", function() { + output = document.getElementById("leaderSubmitOutput"); + nameEntry = document.getElementById("scoreNameSubmit"); + table = document.getElementById("leaderboards"); + easyCol = document.getElementById("lb-easy"); + medCol = document.getElementById("lb-medium"); + hardCol = document.getElementById("lb-hard"); +}); + +// Place message next to leaderboard submission point. No parameter 1 for removing message. If messageType is true, text will be red. +function outputMessage(messageText, messageType) { + if(messageType){ // Error + output.style = "color: #f00;" + } else { // General output + output.style = "color: #000;" + } + output.innerHTML = `<i>${messageText}</i>`; +} + +async function saveScore(name, score, difficulty) { + // Call PHP script to save score to database + const save_response = await fetch(`/php/save_score.php?name=${name}&score=${score}&difficulty=${difficulty}`, {method: 'GET'}) + + if (save_response.ok) { + scoreSubmitted = true; + outputMessage("Score Submitted.", false) + await retrieveScores(); + } else { + outputMessage("Score couldn't be saved. Try again later, or try refreshing the page.", true) + } + +} + +// Takes and parsed JSON data, calling createRow for each array of information, each representing a row in the table. +function populateRows(data){ + // Clear Existing Table Data + easyCol.innerHTML = ""; + medCol.innerHTML = ""; + hardCol.innerHTML = ""; + + // For every item in data + data.forEach(function (row) { + createRow(row["name"], row["score"], row["difficulty"]); + }); +} + +// Creates a row element and appends it to the leaderboard. +function createRow(name,score,difficulty) { + let newRow = document.createElement("tr"); + let nameCol = document.createElement("td"); + let scoreCol = document.createElement("td"); + nameCol.innerHTML = name; + scoreCol.innerHTML = score; + newRow.appendChild(nameCol); + newRow.appendChild(scoreCol); + switch (difficulty) { + case 0: + easyCol.appendChild(newRow); + break; + case 1: + medCol.appendChild(newRow); + break; + case 2: + hardCol.appendChild(newRow); + break; + default: + console.error("Score has no associated difficulty.") + break; + } +} + +async function retrieveScores() { + // Call PHP script to retrieve a list of the top 10 scores across each difficulty + const leaderboard_response = await fetch(`/php/retrieve_scores.php`, {method: 'GET'}) + + if(leaderboard_response.ok){ + const leaderboard_json = await leaderboard_response.json(); + populateRows(leaderboard_json); + } else { // Leaderboard retrieval failed + outputMessage("Failed to retrieve leaderboard data", true); + } +} + +async function requestScoreSubmit() { + // Clear error output + outputMessage("", false); + + if (lastScore === 0) { // If the score is 0, assume the player hasn't played yet + outputMessage("Make sure you play the game before submitting a score!", true) + } else if (nameEntry.value === "") { // If the player hasn't entered a name + outputMessage("Enter a name before submitting your score!", true) + } else { + if (!scoreSubmitted) { + await saveScore(nameEntry.value, lastScore, lastScoreDifficulty); + } + } +} + +// Get initial data +retrieveScores(); \ No newline at end of file diff --git a/php/db_secrets.php b/php/db_secrets.php new file mode 100644 index 0000000..71902bf --- /dev/null +++ b/php/db_secrets.php @@ -0,0 +1,8 @@ +<?php + // This should be stored outside of your webtree + const DB_DRIVER = 'pgsql'; + const DB_HOST = 'hostname'; + const DB_NAME = 'db_name'; + const DB_USER = 'username'; + const DB_PASSWORD = 'password'; + \ No newline at end of file diff --git a/php/get_connection.php b/php/get_connection.php new file mode 100644 index 0000000..1cd773a --- /dev/null +++ b/php/get_connection.php @@ -0,0 +1,14 @@ +<?php +// Originally written by Edel Sherratt in October 2022 +// Modified by Luke Jones for use with JSDiver in November 2024 + +// Establish a connection to the PostgreSQL database. +require 'YOUR_DB_SECRETS_FILE'; +function get_connection() { + $data_source_name = DB_DRIVER.":host=".DB_HOST.";dbname=".DB_NAME; + try { + return new PDO($data_source_name, DB_USER, DB_PASSWORD); + } catch (PDOException $e) { + return NULL; + } +} diff --git a/php/retrieve_scores.php b/php/retrieve_scores.php new file mode 100644 index 0000000..bded18f --- /dev/null +++ b/php/retrieve_scores.php @@ -0,0 +1,37 @@ +<?php +// Originally written by Edel Sherratt in October 2022 +// Modified by Luke Jones for use with JSDiver in November 2024 + +// Retrieves top scores from jsdiver_scores, and then sorts and +// populates tables. + +// Open Connection +require "get_connection.php"; +$conn = get_connection(); + +// Query which selects the top 10 scores of each difficulty +$query = " + WITH RankedScores AS ( + SELECT + name, + score, + difficulty, + ROW_NUMBER() OVER (PARTITION BY difficulty ORDER BY score DESC) AS rank + FROM jsdiver_scores + ) + SELECT name, score, difficulty + FROM RankedScores + WHERE rank <= 10 + ORDER BY difficulty, rank; +"; + +// Execute Query +$result = $conn -> query($query); + +// Encode retrieved data to JSON, and then send that JSON back to the JavaScript call. +echo json_encode($result->fetchAll(PDO::FETCH_ASSOC)); + +// Clear References +$result = null; +$query = null; +$conn = null; \ No newline at end of file diff --git a/php/save_score.php b/php/save_score.php new file mode 100644 index 0000000..44d5aa8 --- /dev/null +++ b/php/save_score.php @@ -0,0 +1,55 @@ +<?php +// Originally written by Edel Sherratt in October 2022 +// Modified by Luke Jones for use with JSDiver in November 2024 + +// Handle Missing Values (shouldn't be possible) +if (!array_key_exists("name", $_GET) || $_GET["name"] == "") { + $_GET["name"] = "Anonymous"; +} +if (!array_key_exists("score", $_GET) || $_GET["score"] == "") { + $_GET["score"] = 0; +} +// Assume easy mode +if (!array_key_exists("difficulty", $_GET) || $_GET["score"] == "") { + $_GET["difficulty"] = 0; +} + +// Open Connection +require "get_connection.php"; +$conn = get_connection(); + +// Carry out check to ensure table exists +$check_query = " + CREATE TABLE IF NOT EXISTS jsdiver_scores ( + name VARCHAR(255) NOT NULL, + score INT NOT NULL, + difficulty INT NOT NULL + ) +"; +$conn -> exec($check_query); + +// Initilaise SQL Query +$query = $conn-> +prepare(" + INSERT INTO jsdiver_scores + (name, score, difficulty) " . " + VALUES + (:name, :score, :difficulty) + "); + +// Outline submission variables +$submission_name = $_GET["name"]; +$submission_score = intval($_GET["score"]); +$submission_difficulty = intval($_GET["difficulty"]); + +// Bind variables to Query +$query->bindParam(":name", $submission_name); +$query->bindParam(":score", $submission_score); +$query->bindParam(":difficulty", $submission_difficulty); + +// Execute Query +$query->execute(); + +// Clear References +$query = null; +$conn = null; \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..c2d4ab3 --- /dev/null +++ b/style.css @@ -0,0 +1,138 @@ +/* +JSDiver's main stylesheet +Luke Jones +*/ + +#main { + border-left: 2px solid rgba(118, 157, 189, 0.84); + border-right: 2px solid rgba(118, 157, 189, 0.84); +} + +body { + color: black; + font-family: Carlito, "Segoe UI", Arial, serif; + background: rgb(94,182,255); + background: linear-gradient(0deg, rgba(94,182,255,1) 0%, rgba(222,249,255,1) 100%); + margin: 0; +} + +#gamebox { + background-color: white; + border: rgba(56, 77, 106, 0.84) solid 2px; + margin-left: auto; + margin-right: auto; + display: block; + box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5); +} + +#main { + background: linear-gradient(0deg, rgb(217, 250, 255) 0%, rgb(255, 255, 255) 100%); +} + +h1 { + color: #190707; + text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.27); +} + +h2 { + color: #190707; + text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.27); + margin-bottom: 1px; +} + +#leaderEntryItems { + margin: 8px; +} + +input, button { + border-width: 0; + padding: 4px; + outline: solid thin rgba(0,0,0,.2); +} + +input { + background: linear-gradient(0deg, rgb(231, 239, 255) 0%, rgb(225, 237, 255) 49.9%, rgb(235, 244, 255) 50%, rgb(244, 244, 244) 100%); + box-shadow: 0 0 8px rgba(0, 0, 0, 0.5); +} + +button { + background: linear-gradient(0deg, rgb(198, 219, 255) 0%, rgb(185, 214, 255) 49.9%, rgb(217, 233, 255) 50%, rgb(244, 244, 244) 100%); + box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5); +} +button:hover { + background: linear-gradient(0deg, rgb(231, 239, 255) 0%, rgb(225, 237, 255) 49.9%, rgb(235, 244, 255) 50%, rgb(244, 244, 244) 100%); + box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5); +} + +#leaderSubmitOutput { + color: #f00; +} + +#content { + width: 700px; + padding: 8px; + margin-left: auto; + margin-right: auto; + display: block; +} + +table, td{ + text-align: left; + vertical-align: top; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.smallTable { + border: 1px solid rgb(0, 0, 0); +} + +thead { + border: 1px solid black; + border-collapse: collapse; +} + +thead tr { + background: linear-gradient(0deg, rgb(198, 219, 255) 0%, rgb(185, 214, 255) 49.9%, rgb(217, 233, 255) 50%, rgb(244, 244, 244) 100%); +} +tbody tr { + background: linear-gradient(0deg, rgb(231, 239, 255) 0%, rgb(225, 237, 255) 49.9%, rgb(235, 244, 255) 50%, rgb(244, 244, 244) 100%); +} + +#leaderboards { + margin: auto; + box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5); + border: 1px solid black; + border-collapse: collapse; +} + +#lb-easy, #lb-medium, #lb-hard { + border: 0; +} + +.entryItem { + margin: inherit; +} + +.leader-heading { + width: 100px; +} + +@media only screen and (max-width: 800px) { + #main { + width: 100%; + } + #gamebox { + width: 100%; + } +} +@media only screen and (min-width: 800px) { + #main { + width: 800px; + margin: auto; + } + #gamebox { + width: 700px; + } +} \ No newline at end of file