diff --git a/.env.example b/.env.example index 821e903..f46c8c7 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ POSTGRES_PORT=5432 EXPRESS_PORT=3000 +FRONTEND_PORT=8080 POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres diff --git a/README.md b/README.md index 71ff3b6..82d8404 100644 --- a/README.md +++ b/README.md @@ -1,163 +1,30 @@ # RaspberryRocketeer -## Class Diagram of all classes +## How to run -```mermaid -classDiagram -direction BT -class Collidable { - collides(o: Entity) boolean -} -class Database { - any _db - any db -} -class Entity { - constructor(position: Position, width: number, height: number, fill: number) - Position _position - number _width - number _height - number fill - boolean _showHitbox - update() void - draw() void - Position position - number width - number height - boolean showHitbox -} -class Game { - number id - number score - string playtime - Date date - number userId -} -class GamePgPromiseRepository { - insert(game: Game) Promise~Game~ - serialize(raw: any) Game -} -class GameRepository { - insert(game: Game) Promise~Game~ -} -class HighscoreLeaderboard -class HighscoreLeaderboardPgPromiseRepository { - getAll() Promise~HighscoreLeaderboard~ - serialize(raw: any) HighscoreLeaderboard -} -class HighscoreLeaderboardRepository { - getAll() Promise~HighscoreLeaderboard~ -} -class Leaderboard -class LeaderboardEntry { - number username - number rank - T score -} -class Obstacle { - constructor(position: Position, obstacleWidth: number, obstacleHeight: number, pipeImagePath: string) - Pipe pipeTop - Pipe pipeBottom - number padding - number speed - number _distanceBetweenPipes - number _startX - resetPosition() void - randomizeHeight() void - randomRange(min: number, max: number) number - update() void - draw() void - collides(o: Entity) boolean - any startX - any distanceBetweenPipes -} -class Pipe { - constructor(positionX: number, width: number, height: number) - any _image - update() void - draw() void - move(speed: number) void - collides(o: Entity) boolean - any image -} -class Position { - constructor(x: number, y: number) - number _x - number _y - number x - number y -} -class Raspberry { - constructor(image: string) - number lift - number gravity - number _velocity - any _image - Position position - number maxVelocity - number WIDTH - number HEIGHT - number FILL - update() void - applyGravity() void - forceBoundaries() void - boost() void - draw() void - number velocity - any image -} -class TimeLeaderboard -class TimeLeaderboardPgPromiseRepository { - getAll() Promise~TimeLeaderboard~ - serialize(raw: any) TimeLeaderboard -} -class TimeLeaderboardRepository { - getAll() Promise~TimeLeaderboard~ -} -class User { - number id - string name -} -class UserPgPromiseRepository { - getById(id: number) Promise~User~ - getByName(name: string) Promise~User~ - withIdExists(id: number) Promise~boolean~ - withNameExists(name: string) Promise~boolean~ - insert(user: Omit~User, "id"~) Promise~User~ - serialize(raw: any) User -} -class UserRepository { - getById(id: number) Promise~User~ - getByName(name: string) Promise~User~ - withIdExists(userId: number) Promise~boolean~ - withNameExists(username: string) Promise~boolean~ - insert(user: Omit~User, "id"~) Promise~User~ -} -class UserScores { - number userId - number highscore - number totalScore - string totalPlaytime - number averageScore - number gamesPlayed -} -class UserScoresPgPromiseRepository { - getById(id: number) Promise~UserScores~ - serialize(raw: any) UserScores -} -class UserScoresRepository { - getById(userId: number) Promise~UserScores~ -} - -GamePgPromiseRepository --> GameRepository -HighscoreLeaderboardPgPromiseRepository --> HighscoreLeaderboardRepository -Obstacle ..> Collidable -Obstacle --> Entity -Pipe ..> Collidable -Pipe --> Entity -Raspberry --> Entity -TimeLeaderboardPgPromiseRepository --> TimeLeaderboardRepository -UserPgPromiseRepository --> UserRepository -UserScoresPgPromiseRepository --> UserScoresRepository +### Copy .env +First you need to copy the `.env.example`. +```shell +cp .env.example .env ``` + +Note: It is recommended to change the values for the database user. + +### Install node packages +Go into the frontend folder using +```shell +cd frontend +``` +and run: +```shell +npm install +``` + +### Start the container (in the project root) + +```shell +docker compose up --build +``` + +You can then access the website on `localhost:8080` diff --git a/backend/api/src/repositories/pgPromise/HighscoreLeaderboardPgPromiseRepository.ts b/backend/api/src/repositories/pgPromise/HighscoreLeaderboardPgPromiseRepository.ts index 1f00f7d..36c9043 100644 --- a/backend/api/src/repositories/pgPromise/HighscoreLeaderboardPgPromiseRepository.ts +++ b/backend/api/src/repositories/pgPromise/HighscoreLeaderboardPgPromiseRepository.ts @@ -12,7 +12,7 @@ export class HighscoreLeaderboardPgPromiseRepository extends HighscoreLeaderboar async getPage(entriesPerPage, page): Promise { const raw: any = await Database.db.manyOrNone( - 'SELECT * FROM lb_highscore INNER JOIN "user" ON user_id = id ORDER BY rank LIMIT $1 OFFSET $2*$1;', + 'SELECT * FROM lb_highscore INNER JOIN "user" ON user_id = id ORDER BY rank LIMIT $1 OFFSET $2;', [entriesPerPage, page * entriesPerPage] ); return this.serialize(raw); diff --git a/backend/api/src/repositories/pgPromise/TimeLeaderboardPgPromiseRepository.ts b/backend/api/src/repositories/pgPromise/TimeLeaderboardPgPromiseRepository.ts index 705b3f8..b2b2ca8 100644 --- a/backend/api/src/repositories/pgPromise/TimeLeaderboardPgPromiseRepository.ts +++ b/backend/api/src/repositories/pgPromise/TimeLeaderboardPgPromiseRepository.ts @@ -12,7 +12,7 @@ export class TimeLeaderboardPgPromiseRepository extends TimeLeaderboardRepositor async getPage(entriesPerPage: number, page: number): Promise { const raw: any = await Database.db.manyOrNone( - 'SELECT * FROM lb_total_playtime INNER JOIN "user" ON user_id = id ORDER BY rank LIMIT $1 OFFSET $2*$1;', + 'SELECT * FROM lb_total_playtime INNER JOIN "user" ON user_id = id ORDER BY rank LIMIT $1 OFFSET $2;', [entriesPerPage, page * entriesPerPage] ); return this.serialize(raw); diff --git a/backend/db/initScripts/loadMockData.sql b/backend/db/initScripts/loadMockData.sql deleted file mode 100644 index 7735cc9..0000000 --- a/backend/db/initScripts/loadMockData.sql +++ /dev/null @@ -1,40 +0,0 @@ -insert into "user" (name) values ('dpettus0'); -insert into "user" (name) values ('egreetland1'); -insert into "user" (name) values ('smontford2'); -insert into "user" (name) values ('idagwell3'); -insert into "user" (name) values ('lgagan4'); -insert into "user" (name) values ('acarmont5'); -insert into "user" (name) values ('kjermyn6'); -insert into "user" (name) values ('dokieran7'); -insert into "user" (name) values ('pdrinkel8'); - -insert into game (user_id, score, playtime, date) values ('1', 74, '19:59', '2022-07-19'); -insert into game (user_id, score, playtime, date) values ('1', 86, '20:32', '2022-11-24'); -insert into game (user_id, score, playtime, date) values ('1', 68, '10:41', '2022-03-24'); -insert into game (user_id, score, playtime, date) values ('2', 39, '5:55', '2022-06-01'); -insert into game (user_id, score, playtime, date) values ('2', 20, '9:23', '2022-03-12'); -insert into game (user_id, score, playtime, date) values ('2', 28, '23:45', '2022-04-01'); -insert into game (user_id, score, playtime, date) values ('2', 44, '18:43', '2022-06-24'); -insert into game (user_id, score, playtime, date) values ('3', 92, '14:54', '2022-11-06'); -insert into game (user_id, score, playtime, date) values ('3', 73, '0:45', '2022-07-26'); -insert into game (user_id, score, playtime, date) values ('3', 27, '2:49', '2022-02-03'); -insert into game (user_id, score, playtime, date) values ('4', 26, '2:32', '2022-07-19'); -insert into game (user_id, score, playtime, date) values ('4', 12, '17:03', '2022-04-25'); -insert into game (user_id, score, playtime, date) values ('4', 6, '8:49', '2021-12-03'); -insert into game (user_id, score, playtime, date) values ('4', 22, '22:27', '2022-03-02'); -insert into game (user_id, score, playtime, date) values ('5', 94, '1:04', '2022-10-19'); -insert into game (user_id, score, playtime, date) values ('5', 2, '2:14', '2022-04-06'); -insert into game (user_id, score, playtime, date) values ('5', 21, '17:18', '2022-06-03'); -insert into game (user_id, score, playtime, date) values ('6', 33, '16:01', '2022-02-02'); -insert into game (user_id, score, playtime, date) values ('6', 27, '7:03', '2022-02-06'); -insert into game (user_id, score, playtime, date) values ('6', 62, '0:45', '2022-11-15'); -insert into game (user_id, score, playtime, date) values ('7', 12, '8:54', '2022-06-29'); -insert into game (user_id, score, playtime, date) values ('7', 63, '16:01', '2022-11-05'); -insert into game (user_id, score, playtime, date) values ('7', 29, '0:46', '2022-10-01'); -insert into game (user_id, score, playtime, date) values ('8', 67, '1:27', '2022-09-29'); -insert into game (user_id, score, playtime, date) values ('8', 84, '10:37', '2021-12-18'); -insert into game (user_id, score, playtime, date) values ('8', 14, '19:14', '2022-01-31'); -insert into game (user_id, score, playtime, date) values ('9', 21, '19:04', '2022-03-08'); -insert into game (user_id, score, playtime, date) values ('9', 46, '2:34', '2022-04-18'); -insert into game (user_id, score, playtime, date) values ('9', 78, '9:33', '2022-09-10'); -insert into game (user_id, score, playtime, date) values ('9', 82, '11:19', '2022-11-29'); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index f21adcc..2672685 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,23 +1,32 @@ -version: '3.1' - -services: - db: - build: backend/db - container_name: postgres-db - environment: - POSTGRES_DB: ${POSTGRES_DB} - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - ports: - - "${POSTGRES_PORT}:5432" - volumes: - - ./backend/pgdata:/var/lib/postgresql/data - - api: - build: backend/api - depends_on: - - db - container_name: express-api - ports: - - "${EXPRESS_PORT}:3000" - +version: '3.1' + +services: + db: + build: backend/db + container_name: postgres-db + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + ports: + - "${POSTGRES_PORT}:5432" + volumes: + - ./backend/pgdata:/var/lib/postgresql/data + + api: + build: backend/api + depends_on: + - db + container_name: express-api + ports: + - "${EXPRESS_PORT}:3000" + + vue: + build: frontend + container_name: frontend + ports: + - "${FRONTEND_PORT}:8080" + + + volumes: + - ./frontend:/app diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..3298622 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,3 @@ +node_modules +.gitignore +README.md diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..e8524c9 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,11 @@ +FROM node:18 + +COPY . /app +WORKDIR /app + +RUN npm install + +EXPOSE 8080 + +ENTRYPOINT ["npm", "run", "serve"] + diff --git a/frontend/package.json b/frontend/package.json index fbffbbe..a11bdcd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,11 +10,11 @@ }, "dependencies": { "bootstrap": "^5.2.3", - "vue": "^3.2.13" + "vue": "^3.2.13", + "@vue/cli-service": "~5.0.0" }, "devDependencies": { "@vue/cli-plugin-typescript": "~5.0.0", - "@vue/cli-service": "~5.0.0", "typescript": "~4.5.5" } } diff --git a/frontend/public/game.js b/frontend/public/game.js index 1fc0b9d..3b51b91 100644 --- a/frontend/public/game.js +++ b/frontend/public/game.js @@ -1,20 +1,20 @@ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { +var __extends = (this && this.__extends) || (function(){ + var extendStatics = function(d, b){ extendStatics = Object.setPrototypeOf || - ({__proto__: []} instanceof Array && function (d, b) { + ({__proto__: []} instanceof Array && function(d, b){ d.__proto__ = b; }) || - function (d, b) { - for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; + function(d, b){ + for(var p in b) if(Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; - return function (d, b) { - if (typeof b !== "function" && b !== null) + return function(d, b){ + if(typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); - function __() { + function __(){ this.constructor = d; } @@ -45,21 +45,21 @@ var hasAlreadyScored = false; var hasDied = true; var ready = true; -function preload() { +function preload(){ font = loadFont(FONT_PATH); backgroundImage = loadImage(BACKGROUND_IMAGE_PATH); pipeImage = loadImage(PIPE_IMAGE_PATH); floorImage = loadImage(FLOOR_IMAGE_PATH); } -function setup() { +function setup(){ createCanvas(1085, 600); floorHeight = height / 5; setupObstacleConsts(); setupFont(); setupGame(); var originalSetItem = localStorage.setItem; - localStorage.setItem = function (key, value) { + localStorage.setItem = function(key, value){ var event = new Event('itemInserted'); event.value = value; // Optional.. @@ -69,57 +69,57 @@ function setup() { }; } -function setupObstacleConsts() { +function setupObstacleConsts(){ obstacleOffset = width / OBSTACLE_COUNT; obstacleWidth = width / 22.727272727272727272; Obstacle.distanceBetweenPipes = height / 2.5; Obstacle.startX = width; } -function setupFont() { +function setupFont(){ textSize(75); textAlign(CENTER); textFont(font); } -function setupGame() { +function setupGame(){ paused = true; raspberry = new Raspberry(RASPBERRY_IMAGE_PATH); setupObstacles(); } -function setupObstacles() { +function setupObstacles(){ obstacles = []; instantiateObstacles(OBSTACLE_COUNT); - obstacles.forEach(function (obstacle) { + obstacles.forEach(function(obstacle){ return obstacle.randomizeHeight(); }); } -function instantiateObstacles(number) { - for (var i = 0; i < number; i++) { +function instantiateObstacles(number){ + for(var i = 0; i < number; i++){ obstacles.push(new Obstacle(new Position(width + obstacleOffset * i, 0), obstacleWidth, height, pipeImage)); } } -function draw() { +function draw(){ update(); gameLoop(); drawGame(); } -function drawGame() { +function drawGame(){ drawScenery(); drawEntities(); displayScore(); } -function drawScenery() { +function drawScenery(){ background(backgroundImage); drawFloor(); } -function drawFloor() { +function drawFloor(){ push(); noFill(); image(floorImage, 0, height - floorHeight, width, floorHeight); @@ -127,68 +127,71 @@ function drawFloor() { pop(); } -function drawEntities() { +function drawEntities(){ raspberry.draw(); drawObstacles(); } -function drawObstacles() { - obstacles.forEach(function (obstacle) { +function drawObstacles(){ + obstacles.forEach(function(obstacle){ obstacle.draw(); }); } -function gameLoop() { - if (!paused) { +function gameLoop(){ + if(!paused){ collisionCheck(obstacles[0]); checkRaspberryScore(); } } -function collisionCheck(o) { - if (o.collides(raspberry)) { +function collisionCheck(o){ + if(o.collides(raspberry)){ die(); setupGame(); } } -function die() { +function die(){ + if(localStorage.getItem("frontend-ready") == "false") + return; + ready = false; hasDied = true; playTime = Date.now() - startTime; exportToLocalStorage(); - setTimeout(function () { + setTimeout(function(){ return ready = true; }, 1000); } -function exportToLocalStorage() { +function exportToLocalStorage(){ localStorage.setItem("game-playTime", String(playTime)); localStorage.setItem("game-score", String(score)); localStorage.setItem("game-isRunning", String(!hasDied)); } -function displayScore() { +function displayScore(){ push(); fill(195, 33, 34); text(score, 0, height / 8, width, height); pop(); } -function update() { - if (!paused) { +function update(){ + if(!paused){ raspberry.update(); } - obstacles.forEach(function (obstacle) { - if (!paused) { + obstacles.forEach(function(obstacle){ + if(!paused){ obstacle.update(); checkObstacleReset(obstacle); } }); } -function checkObstacleReset(obstacle) { - if (obstacle.position.x < -obstacleWidth) { +function checkObstacleReset(obstacle){ + if(obstacle.position.x < -obstacleWidth){ obstacle.resetPosition(); obstacles.shift(); obstacles.push(obstacle); @@ -196,40 +199,41 @@ function checkObstacleReset(obstacle) { } } -function checkRaspberryScore() { - if ((obstacles[0].position.x + obstacles[0].width / 2) < (raspberry.position.x + raspberry.width / 2) - && !hasAlreadyScored) { +function checkRaspberryScore(){ + if((obstacles[0].position.x + obstacles[0].width / 2) < (raspberry.position.x + raspberry.width / 2) + && !hasAlreadyScored){ score += 1; hasAlreadyScored = true; } } -function resetScore() { - if (hasDied) { - hasDied = false; - score = 0; - hasAlreadyScored = false; - startTime = Date.now(); - exportToLocalStorage(); - } +function resetScore(){ + if(!hasDied || localStorage.getItem("frontend-ready") == "false") + return; + + hasDied = false; + score = 0; + hasAlreadyScored = false; + startTime = Date.now(); + exportToLocalStorage(); } -function keyPressed() { - if (!ready) +function keyPressed(){ + if(!ready) return; - if (BOOST_KEYS.includes(key.toLowerCase())) { + if(BOOST_KEYS.includes(key.toLowerCase())){ resetScore(); raspberry.boost(); } - if (key == "Escape") { + if(key == "Escape"){ paused = !paused; - } else if (paused) { + } else if(paused){ paused = false; } } -var Entity = (function () { - function Entity(position, width, height, fill) { +var Entity = (function(){ + function Entity(position, width, height, fill){ this.position = position; this.width = width; this.height = height; @@ -238,46 +242,46 @@ var Entity = (function () { } Object.defineProperty(Entity.prototype, "position", { - get: function () { + get: function(){ return this._position; }, - set: function (value) { + set: function(value){ this._position = value; }, enumerable: false, configurable: true }); Object.defineProperty(Entity.prototype, "width", { - get: function () { + get: function(){ return this._width; }, - set: function (value) { + set: function(value){ this._width = value; }, enumerable: false, configurable: true }); Object.defineProperty(Entity.prototype, "height", { - get: function () { + get: function(){ return this._height; }, - set: function (value) { + set: function(value){ this._height = value; }, enumerable: false, configurable: true }); Object.defineProperty(Entity.prototype, "showHitbox", { - get: function () { + get: function(){ return this._showHitbox; }, - set: function (value) { + set: function(value){ this._showHitbox = value; }, enumerable: false, configurable: true }); - Entity.prototype.draw = function () { + Entity.prototype.draw = function(){ push(); fill(this.fill); rect(this.position.x, this.position.y, this.width, this.height); @@ -285,10 +289,10 @@ var Entity = (function () { }; return Entity; }()); -var Obstacle = (function (_super) { +var Obstacle = (function(_super){ __extends(Obstacle, _super); - function Obstacle(position, obstacleWidth, obstacleHeight, image) { + function Obstacle(position, obstacleWidth, obstacleHeight, image){ var _this = _super.call(this, position, obstacleWidth, obstacleHeight, 0) || this; _this.speed = 3; _this.padding = height / 6.6666666666666666; @@ -297,62 +301,62 @@ var Obstacle = (function (_super) { } Object.defineProperty(Obstacle, "startX", { - set: function (value) { + set: function(value){ this._startX = value; }, enumerable: false, configurable: true }); Object.defineProperty(Obstacle, "distanceBetweenPipes", { - set: function (value) { + set: function(value){ this._distanceBetweenPipes = value; }, enumerable: false, configurable: true }); - Obstacle.prototype.createPipes = function (position, obstacleHeight, obstacleWidth, pipeImage) { + Obstacle.prototype.createPipes = function(position, obstacleHeight, obstacleWidth, pipeImage){ this.pipeTop = new Pipe(position.x, obstacleWidth, obstacleHeight, pipeImage); this.pipeBottom = new Pipe(position.x, obstacleWidth, obstacleHeight, pipeImage); }; - Obstacle.prototype.resetPosition = function () { + Obstacle.prototype.resetPosition = function(){ this.randomizeHeight(); this.pipeBottom.position.x = Obstacle._startX; this.pipeTop.position.x = Obstacle._startX; }; - Obstacle.prototype.randomizeHeight = function () { + Obstacle.prototype.randomizeHeight = function(){ this.pipeTop.height = this.randomRange(this.padding, height - this.padding - Obstacle._distanceBetweenPipes); this.pipeBottom.position.y = this.pipeTop.height + Obstacle._distanceBetweenPipes; this.pipeBottom.height = height - this.pipeTop.height - this.padding; }; - Obstacle.prototype.randomRange = function (min, max) { + Obstacle.prototype.randomRange = function(min, max){ return Math.random() * (max - min) + min; }; - Obstacle.prototype.update = function () { + Obstacle.prototype.update = function(){ this.pipeTop.move(this.speed); this.pipeBottom.move(this.speed); this.position.x = this.pipeTop.position.x; }; - Obstacle.prototype.draw = function () { + Obstacle.prototype.draw = function(){ this.pipeTop.draw(); this.pipeBottom.draw(); }; - Obstacle.prototype.collides = function (o) { + Obstacle.prototype.collides = function(o){ return this.pipeTop.collides(o) || this.pipeBottom.collides(o); }; return Obstacle; }(Entity)); -var Pipe = (function (_super) { +var Pipe = (function(_super){ __extends(Pipe, _super); - function Pipe(positionX, width, height, image) { + function Pipe(positionX, width, height, image){ var _this = _super.call(this, new Position(positionX, 0), width, height, 0) || this; _this.image = image; return _this; } - Pipe.prototype.update = function () { + Pipe.prototype.update = function(){ }; - Pipe.prototype.draw = function () { + Pipe.prototype.draw = function(){ push(); noFill(); var imageAspectRatio = this.image.height / this.image.width; @@ -361,30 +365,30 @@ var Pipe = (function (_super) { rect(this.position.x, this.position.y, this.width, this.height); pop(); }; - Pipe.prototype.drawImage = function (computedImageHeight, imageAspectRatio) { - if (this.height > computedImageHeight) { + Pipe.prototype.drawImage = function(computedImageHeight, imageAspectRatio){ + if(this.height > computedImageHeight){ var maxImageYPos = Math.ceil(this.height / computedImageHeight) * computedImageHeight; - for (var imageYPosition = 0; imageYPosition < maxImageYPos; imageYPosition += computedImageHeight) { - if (imageYPosition + computedImageHeight >= maxImageYPos) { + for(var imageYPosition = 0; imageYPosition < maxImageYPos; imageYPosition += computedImageHeight){ + if(imageYPosition + computedImageHeight >= maxImageYPos){ this.cropLastImage(imageYPosition, computedImageHeight, imageAspectRatio); break; } image(this.image, this.position.x, this.position.y + imageYPosition, this.width, computedImageHeight); } - } else { + } else{ image(this.image, this.position.x, this.position.y, this.width, this.height); } }; - Pipe.prototype.cropLastImage = function (imageYPosition, computedImageHeight, imageAspectRatio) { + Pipe.prototype.cropLastImage = function(imageYPosition, computedImageHeight, imageAspectRatio){ var amountOfImages = Math.floor(imageYPosition / computedImageHeight); var heightToEdge = this.height - (amountOfImages * computedImageHeight); var croppedImage = this.image.get(0, 0, this.image.width, this.image.height - (heightToEdge * imageAspectRatio)); image(croppedImage, this.position.x, this.position.y + imageYPosition, this.width, heightToEdge); }; - Pipe.prototype.move = function (speed) { + Pipe.prototype.move = function(speed){ this.position.x -= speed; }; - Pipe.prototype.collides = function (o) { + Pipe.prototype.collides = function(o){ return this.position.x < (o.position.x + o.width) && (this.position.x + this.width) > o.position.x && this.position.y < (o.position.y + o.height) && @@ -392,27 +396,27 @@ var Pipe = (function (_super) { }; return Pipe; }(Entity)); -var Position = (function () { - function Position(x, y) { +var Position = (function(){ + function Position(x, y){ this._x = x; this._y = y; } Object.defineProperty(Position.prototype, "x", { - get: function () { + get: function(){ return this._x; }, - set: function (value) { + set: function(value){ this._x = value; }, enumerable: false, configurable: true }); Object.defineProperty(Position.prototype, "y", { - get: function () { + get: function(){ return this._y; }, - set: function (value) { + set: function(value){ this._y = value; }, enumerable: false, @@ -420,10 +424,10 @@ var Position = (function () { }); return Position; }()); -var Raspberry = (function (_super) { +var Raspberry = (function(_super){ __extends(Raspberry, _super); - function Raspberry(image) { + function Raspberry(image){ var _this = this; Raspberry.position = new Position(width / 6, height / 2); Raspberry.height = height / 14.2857142857142857; @@ -438,73 +442,73 @@ var Raspberry = (function (_super) { } Object.defineProperty(Raspberry.prototype, "velocity", { - get: function () { + get: function(){ return this._velocity; }, - set: function (value) { + set: function(value){ this._velocity = (Math.abs(this.velocity) > Raspberry.maxVelocity) ? Raspberry.maxVelocity : value; }, enumerable: false, configurable: true }); Object.defineProperty(Raspberry.prototype, "image", { - get: function () { + get: function(){ return this._image; }, - set: function (path) { + set: function(path){ this._image = loadImage(path); }, enumerable: false, configurable: true }); - Raspberry.prototype.update = function () { + Raspberry.prototype.update = function(){ this.applyGravity(); this.forceBoundaries(); }; - Raspberry.prototype.applyGravity = function () { + Raspberry.prototype.applyGravity = function(){ this.velocity += this.gravity; this.position.y += this.velocity; }; - Raspberry.prototype.forceBoundaries = function () { + Raspberry.prototype.forceBoundaries = function(){ this.boundaryTop(); this.boundaryBottom(); }; - Raspberry.prototype.boundaryTop = function () { - if (this.position.y < 0) { + Raspberry.prototype.boundaryTop = function(){ + if(this.position.y < 0){ this.position.y = 0; this.velocity = 0; } }; - Raspberry.prototype.boundaryBottom = function () { - if (this.position.y + this.height + Raspberry.bottomFloorOffset > height) { + Raspberry.prototype.boundaryBottom = function(){ + if(this.position.y + this.height + Raspberry.bottomFloorOffset > height){ this.position.y = height - this.height - Raspberry.bottomFloorOffset; this.velocity = 0; } }; - Raspberry.prototype.boost = function () { + Raspberry.prototype.boost = function(){ this.velocity += this.lift; }; - Raspberry.prototype.draw = function () { + Raspberry.prototype.draw = function(){ push(); noFill(); this.setPose(); this.drawObject(); pop(); }; - Raspberry.prototype.drawObject = function () { + Raspberry.prototype.drawObject = function(){ this.drawHitBox(); this.drawRocket(); }; - Raspberry.prototype.drawRocket = function () { + Raspberry.prototype.drawRocket = function(){ image(this.image, 0, 0, this.width, this.height); rect(0, 0, this.width, this.height); }; - Raspberry.prototype.drawHitBox = function () { - if (!this.showHitbox) { + Raspberry.prototype.drawHitBox = function(){ + if(!this.showHitbox){ noStroke(); } }; - Raspberry.prototype.setPose = function () { + Raspberry.prototype.setPose = function(){ translate(this.position.x, this.position.y); rotate((PI / 2) * (this.velocity / Raspberry.maxVelocity)); }; diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 005dd11..a5859cc 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -13,7 +13,7 @@
- +
@@ -59,7 +59,9 @@ export default defineComponent({ leaderboardEvent: new Event('reloadLeaderboard') } }, - + created() { + localStorage.setItem("frontend-ready", "false"); + }, methods: { async fetchFromApi(path: string, method: "GET" | "POST") { @@ -80,6 +82,12 @@ export default defineComponent({ await this.updateUserScores(); } window.dispatchEvent(this.leaderboardEvent); + }, + logOut(){ + this.user = null; + this.userId = -1; + this.userScores = {}; + localStorage.setItem('frontend-ready', 'false'); } }, }); @@ -99,9 +107,11 @@ export default defineComponent({ .everything { margin-bottom: 4em; } + .hidden { visibility: hidden; } + .logout-wrapper { display: flex; justify-content: right; diff --git a/frontend/src/components/Game.vue b/frontend/src/components/Game.vue index 9ce31fe..0fbbed1 100644 --- a/frontend/src/components/Game.vue +++ b/frontend/src/components/Game.vue @@ -58,3 +58,9 @@ export default { }, } + + \ No newline at end of file diff --git a/frontend/src/components/Leaderboard.vue b/frontend/src/components/Leaderboard.vue index 2ee7b32..f5ac5d9 100644 --- a/frontend/src/components/Leaderboard.vue +++ b/frontend/src/components/Leaderboard.vue @@ -9,9 +9,12 @@
-
+
+
+ Loading... +
@@ -39,11 +42,7 @@ export default { }, created() { this.updatePage(); - window.addEventListener('itemInserted', (event) => { - if (event.key === 'game-isRunning' && event.value === 'false'){ - this.updatePage(); - } - }, false) + window.addEventListener('itemInserted', event => this.onItemInserted(event), false); }, methods: { async fetchPage() { @@ -53,21 +52,33 @@ export default { title() { return this.type === "totalplaytime" ? "Total Playtime" : "Highscore"; }, - nextPage() { + async nextPage() { + if (this.page.length !== this.entriesPerPage) return; + this.pageNumber++; - this.updatePage(); + await this.updatePage(); + if (this.page.length === 0) { + this.prevPage(); + } }, prevPage() { - if (this.pageNumber > 0) this.pageNumber--; + if (this.pageNumber <= 0) return; + + this.pageNumber--; this.updatePage(); }, async updatePage() { let tempPage = await this.fetchPage(); for (let i = 0; i < this.entriesPerPage; i++) { - this.page.pop() + this.page.pop(); } for (const entry of tempPage) { - this.page.push(entry) + this.page.push(entry); + } + }, + onItemInserted(event) { + if (event.key === 'game-isRunning' && event.value === 'false') { + this.updatePage(); } } } diff --git a/frontend/src/components/LeaderboardEntry.vue b/frontend/src/components/LeaderboardEntry.vue index 7f37210..d39a95f 100644 --- a/frontend/src/components/LeaderboardEntry.vue +++ b/frontend/src/components/LeaderboardEntry.vue @@ -1,17 +1,18 @@