Skip to content

Commit

Permalink
Merge pull request from UoB-COMSM0166/feature_UiAndDoorLogic_jh_20250228
Browse files Browse the repository at this point in the history
Add images and door logic; Make boundary detections fit background image
  • Loading branch information
h-d-jin authored Feb 28, 2025
2 parents 0204262 + bddedb6 commit 68f6010
Show file tree
Hide file tree
Showing 21 changed files with 181 additions and 116 deletions.
Binary file added docs/public/assets/background/menu_start.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/public/assets/background/room_tutorial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/public/assets/door/door_close.jpg
Binary file not shown.
Binary file added docs/public/assets/door/door_close.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/public/assets/door/door_open.jpg
Binary file not shown.
Binary file added docs/public/assets/door/door_open.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/public/assets/fonts/PressStart2P.ttf
Binary file not shown.
2 changes: 2 additions & 0 deletions docs/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<script src="../src/entities/enemies/Enemy.js"></script>
<script src="../src/entities/enemies/Chaser.js"></script>
<script src="../src/entities/enemies/Shooter.js"></script>
<script src="../src/entities/Door.js"></script>
<script src="../src/entities/Room.js"></script>

<!-- Views/UI -->
<script src="../src/ui/hud.js"`></script>
Expand Down
20 changes: 9 additions & 11 deletions docs/src/controllers/CollisionDetector.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
class CollisionDetector {
detectPlayerCollision(playerObj, objArray) {
detectPlayerCollision(playerObj, objArr) {
// Check the collision between the player and other objects. If there is a collision,
// the player bounces back.
return objArray.some(obj => this.detectCollision(playerObj, obj));
return objArr.some(obj => this.detectCollision(playerObj, obj));
}

detectBulletEnemyCollision(bulletArray, enemyArray) {
detectBulletEnemyCollision(bulletArr, enemyArr) {
// Check the collision between bullets and enemies. If there is a collision,
// the bullet vanishes and causes damage to the enemy.
enemyArray.forEach((enemyObj, enemyIndex) => {
bulletArray.forEach((bulletObj, bulletIndex) => {
enemyArr.forEach((enemyObj, enemyIndex) => {
bulletArr.forEach((bulletObj, bulletIndex) => {
if (this.detectCollision(bulletObj, enemyObj)) {
enemyArray[enemyIndex].hp = max(0, enemyObj.hp - bulletObj.damage);
enemyArr[enemyIndex].hp = max(0, enemyObj.hp - bulletObj.damage);

hitSound.currentTime=0; //music 让音效从头播放
hitSound.play();

if(enemyArray[enemyIndex].hp === 0){
if(enemyArr[enemyIndex].hp === 0){
deathSound.currentTime = 0;
deathSound.play();
}


bulletArray.splice(bulletIndex, 1);
bulletArr.splice(bulletIndex, 1);
}
});
});
Expand All @@ -40,7 +38,7 @@ class CollisionDetector {
hitBoundary(obj) {
let x = obj.position.x + obj.velocity.x;
let y = obj.position.y + obj.velocity.y;
return x < 0 || x > widthInPixel - obj.size.x || y < 0 || y > heightInPixel - obj.size.y;
return x < leftBoundary || x > rightBoundary - obj.size.x || y < topBoundary || y > bottomBoundary - obj.size.y;
}
}

29 changes: 22 additions & 7 deletions docs/src/controllers/InputHandler.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
class InputHandler {
constructor(cooldownTime = 2000, bulletDmg = 50) {
constructor(roomObj, cooldownTime = 2000) {
this.currentRoom = roomObj;
this.collisionDetector = new CollisionDetector();
this.collisionCoolDownTime = cooldownTime;
this.bulletDamage = bulletDmg;
this.lastCollisionTime = millis();
}

update() {
this.currentRoom.update();
player.updateVelocity();
player.updatePosition();
const collideWithEnemies = this.collisionDetector.detectPlayerCollision(player, enemies);
const collideWithObstacles = this.collisionDetector.detectPlayerCollision(player, obstacles);
const collideWithEnemies = this.collisionDetector.detectPlayerCollision(player, this.currentRoom.enemies);
const collideWithObstacles = this.collisionDetector.detectPlayerCollision(player, this.currentRoom.obstacles);
const playerHitBoundary = this.collisionDetector.hitBoundary(player);
if (collideWithEnemies || collideWithObstacles || playerHitBoundary) {
player.revertPosition();
Expand All @@ -26,8 +27,9 @@ class InputHandler {
// player.shoot(direction);
// }
this.updateBullets();
this.collisionDetector.detectBulletEnemyCollision(player.bullets, enemies);
this.removeEnemies(enemies);
this.collisionDetector.detectBulletEnemyCollision(player.bullets, this.currentRoom.enemies);
this.removeEnemies(this.currentRoom.enemies);
this.moveToNextRoom();
}

handlePlayerShooting() {
Expand All @@ -53,7 +55,6 @@ class InputHandler {
});
}


decreasePlayerHp() {
// The player will not receive any damage in the future 2 seconds.
if (millis() - this.lastCollisionTime < this.collisionCoolDownTime) {
Expand All @@ -65,4 +66,18 @@ class InputHandler {
hurtSound.currentTime = 0;
hurtSound.play();
}

moveToNextRoom(tolerance=player.size.x) {
if (!this.currentRoom.checkClearCondition()) return;

const playerMidX = player.position.x + player.size.x / 2;
const playerMidY = player.position.y + player.size.y / 2;
const doorX = this.currentRoom.door.position.x;
const doorY = this.currentRoom.door.position.y + this.currentRoom.door.size.y / 2;

if (dist(playerMidX, playerMidY, doorX, doorY) < tolerance) {
console.log("Move to the next room!");
loadRoom();
}
}
}
35 changes: 19 additions & 16 deletions docs/src/core/controller.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function checkSavePoint() {
// Save when player crosses the target position
const distanceX = abs(player.position.x - savePoint.position.x);
const distanceY = abs(player.position.y - savePoint.position.y);
const distanceX = abs(player.position.x - room.savePoint.position.x);
const distanceY = abs(player.position.y - room.savePoint.position.y);
if (!nearSavedPosition && distanceX < player.size.x && distanceY < player.size.y) {
saveGameData();
nearSavedPosition = true;
Expand All @@ -17,16 +17,16 @@ function checkSavePoint() {
function saveGameData() {
if (nearSavedPosition) return;

localStorage.setItem('lastSavePoint', JSON.stringify(savePoint));
localStorage.setItem('lastSavePoint', JSON.stringify(room.savePoint));
localStorage.setItem('playerHp', JSON.stringify(player.hp));
lastSavedPosition.xPos = savePoint.position.x;
lastSavedPosition.yPos = savePoint.position.y;
lastSavedPosition.xPos = room.savePoint.position.x;
lastSavedPosition.yPos = room.savePoint.position.y;
console.log("Game Saved!");
}

function loadGameData() {
generateEnemies();
generateObstacles();
room.generateEnemies();
room.generateObstacles();
let savedPosition = localStorage.getItem('lastSavePoint');
let playerHp = localStorage.getItem('playerHp');
if (!savedPosition || !playerHp) {
Expand Down Expand Up @@ -93,19 +93,22 @@ function exitGame() {
}

function resetGame() {
menuDisplayed = false;
isGamePaused = false;
gameOver = false;

player = new Player(playerX, playerY);
generateObstacles();
generateEnemies();
console.log("Player is reset!")
startTime = millis();
}

function checkWinCondition() {
// 当所有敌人被消灭,且玩家位于画布上方(yPos < 10)且血量大于 0 时,认为达成胜利条件
return (enemies.length === 0 && player.position.y < 10 && player.hp > 0)
room = new Room();
room.setup();
inputHandler = new InputHandler(room);
console.log("Game is reset!")
}

function isGameOver() {
return player.hp <= 0;
}

function loadRoom() {

}

54 changes: 10 additions & 44 deletions docs/src/core/main.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,35 @@
let pauseSound = new Audio("assets/music/Pause.mp3");
let hitSound = new Audio("assets/music/Enemy_Hurt.mp3");
let deathSound = new Audio("assets/music.Enemy_Death.mp3");
let deathSound = new Audio("assets/music/Enemy_Death.mp3");
let shootSound = new Audio("assets/music/Player_Shoot.mp3");
let hurtSound = new Audio("assets/music/Player_Hurt.mp3");
let deathSound2 = new Audio("assets/music/Player_Death.mp3");
let walkSound = new Audio("assets/music/Player_Walk.mp3");
walkSound.loop = true;

function generateObstacles() {
obstacles = [];
for (let i = 0; i < obstacleCount; i++) {
let x = random(hPadding, widthInPixel - hPadding);
let y = random(vPadding, heightInPixel - vPadding);
obstacles.push(new Obstacle(x, y));
}
}

function generateEnemies() {
enemies = [];
for (let i = 0; i < enemyCount; i++) {
let x = random(hPadding, widthInPixel - hPadding);
let y = random(vPadding, heightInPixel - vPadding);

let hp = random([smallEnemyHp, largeEnemyHp]);
enemies.push(new Enemy(x, y, hp));
}
}

function updateObstacles() {
obstacles.forEach(o => o.display());
}

function updateEnemies() {
enemies.forEach(e => {
e.update();
e.display();
});
}

function preload() {
uiFont = loadFont('assets/fonts/PressStart2P.ttf');
heart = loadImage('assets/icons/heart.svg');
damagedHeart = loadImage('assets/icons/damagedHeart.svg');
startMenuImg = loadImage('assets/background/menu_start.png');
closedDoorImg = loadImage('assets/door/door_close.png');
openDoorImg = loadImage('assets/door/door_open.png');
officeRoomImg = loadImage('assets/background/room_tutorial.png');
}

function setup() {
cnv = createCanvas(windowWidth, windowHeight);
adjustCanvasWithAspectRatio();
player = new Player(playerX, playerY);
savePoint = new SavePoint(savePointX, savePointY);
inputHandler = new InputHandler();
room = new Room();
room.setup();
inputHandler = new InputHandler(room);

setupMenu();
setupPauseMenu();
startTime = millis();
generateObstacles();
generateEnemies();
}

function draw() {
// push();
adjustCanvasWithAspectRatio();
background(220);
if (menuDisplayed) {
Expand All @@ -70,18 +41,13 @@ function draw() {
}
else {
displayTutorial();
updateObstacles();
updateEnemies();

// room.update();
inputHandler.update();
savePoint.display();
player.display();
drawUiHub();

checkSavePoint();
checkWinCondition();
}
// pop();
}

function keyPressed() {
Expand Down
16 changes: 16 additions & 0 deletions docs/src/entities/Door.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Door {
constructor(x = rightBoundary, y = heightInPixel / 2 - doorSize.h / 2) {
this.position = createVector(x, y);
this.size = createVector(doorSize.w, doorSize.h);
this.currentDoorImg = closedDoorImg;
}

display() {
image(this.currentDoorImg, this.position.x, this.position.y, this.size.x, this.size.y);
}

open() {
if (this.currentDoorImg === openDoorImg) return;
this.currentDoorImg = openDoorImg;
}
}
4 changes: 2 additions & 2 deletions docs/src/entities/Obstacle.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
class Obstacle {
constructor(x, y) {
this.position = createVector(x, y);
this.size = createVector(obstacleSize.w, obstacleSize.h);
this.size = createVector(heightInPixel / 12, heightInPixel / 12);
}

display() {
fill(100);
rect(this.position.x, this.position.y, this.size.x, this.size.y);
}
}
}
2 changes: 1 addition & 1 deletion docs/src/entities/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Player {
this.velocity = createVector(0, 0);
this.atk = defaultAtk;
this.maxAtk = playerMaxAtk;
this.size = createVector(playerSize.w, playerSize.h);
this.size = createVector(heightInPixel / 12, heightInPixel / 12);
this.bullets = [];
}

Expand Down
66 changes: 66 additions & 0 deletions docs/src/entities/Room.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class Room {
constructor() {
this.savePoint = null;
this.door = null;
this.enemies = [];
this.obstacles = [];
}

setup() {
this.savePoint = new SavePoint(savePointParam.x, savePointParam.y);
this.door = new Door();
this.generateObstacles();
this.generateEnemies();
startTime = millis();
}

update() {
image(officeRoomImg, 0, 0, widthInPixel, heightInPixel);
this.savePoint.display();
this.updateObstacles();
this.updateEnemies();
this.updateDoor();
this.checkClearCondition();
}

generateObstacles() {
this.obstacles = [];
const maxEntitySize = heightInPixel / 8;
for (let i = 0; i < obstacleCount; i++) {
let x = random(leftBoundary, rightBoundary - maxEntitySize);
let y = random(topBoundary, bottomBoundary - maxEntitySize);
this.obstacles.push(new Obstacle(x, y));
}
}

generateEnemies() {
this.enemies = [];
const maxEntitySize = heightInPixel / 8;
for (let i = 0; i < enemyCount; i++) {
let x = random(leftBoundary, rightBoundary - maxEntitySize);
let y = random(topBoundary, bottomBoundary - maxEntitySize);
let hp = random([smallEnemyHp, largeEnemyHp]);
this.enemies.push(new Enemy(x, y, hp));
}
}

updateObstacles() {
this.obstacles.forEach(o => o.display());
}

updateEnemies() {
this.enemies.forEach(e => {
e.update();
e.display();
});
}

updateDoor() {
if (this.checkClearCondition()) this.door.open();
this.door.display();
}

checkClearCondition() {
return (this.enemies.length === 0 && player.hp > 0);
}
}
3 changes: 1 addition & 2 deletions docs/src/entities/SavePoint.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
class SavePoint {
constructor(x, y) {
this.position = createVector(x, y);
this.size = savePointSize;
this.size = createVector(savePointSize.w, savePointSize.h);
this.size = createVector(savePointParam.w, savePointParam.h);
}

display() {
Expand Down
Loading

0 comments on commit 68f6010

Please sign in to comment.