[Added] Ability to serve the project using nginx on localhost:4600
This commit is contained in:
+36
-1
@@ -63,4 +63,39 @@ RUN cd libs/raylib/src && \
|
||||
emar rcs libraylib.a rcore.o rshapes.o rtextures.o rtext.o rmodels.o utils.o raudio.o && \
|
||||
cd ../..
|
||||
|
||||
CMD ["bash"]
|
||||
# CMD ["bash"]
|
||||
|
||||
FROM development as build
|
||||
|
||||
RUN mkdir dist html src include assets
|
||||
|
||||
COPY include include
|
||||
COPY src src
|
||||
COPY html html
|
||||
COPY assets assets
|
||||
|
||||
# CMD ["tail", "-f", "/dev/null"]
|
||||
# Run the production build command to generate game.js and game.wasm
|
||||
RUN source /app/libs/emsdk/emsdk_env.sh && \
|
||||
emcc $(find src/ -name "*.cpp") -o dist/game.js -O3 -Wno-missing-braces \
|
||||
-I./include -I/app/libs/raylib/build/raylib/include \
|
||||
-L/app/libs/raylib/src /app/libs/raylib/src/libraylib.a \
|
||||
-s ALLOW_MEMORY_GROWTH=1 -s INITIAL_MEMORY=536870912 -s MAXIMUM_MEMORY=4294967296 \
|
||||
-s --preload-file assets@/assets -s USE_GLFW=3 -s ASSERTIONS=2 -DPLATFORM_WEB
|
||||
|
||||
# CMD ["tail", "-f", "/dev/null"]
|
||||
|
||||
FROM nginx:alpine as production
|
||||
|
||||
# Remove the default nginx index.html
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
# Copy the generated files from the production stage into the Nginx html directory
|
||||
COPY --from=build /app/dist/ /usr/share/nginx/html/
|
||||
COPY --from=build /app/html/index.html /usr/share/nginx/html/
|
||||
|
||||
# Expose port 80 to allow Nginx to serve the files
|
||||
EXPOSE 80
|
||||
|
||||
# Start Nginx server
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -1,2 +1,39 @@
|
||||
# WebJelly-Rescue
|
||||
Jelly Rescue, but now for the web!
|
||||
[Jelly Rescue](https://github.com/Ninjaws/JellyGame), but now for the web!
|
||||
|
||||
## Installation
|
||||
### Install Docker
|
||||
- On Windows and Mac
|
||||
```
|
||||
Install Docker Desktop
|
||||
Windows: https://docs.docker.com/desktop/install/windows-install/
|
||||
Mac: https://docs.docker.com/desktop/install/mac-install/
|
||||
```
|
||||
- On Linux
|
||||
```bash
|
||||
# For Debian-based systems
|
||||
sudo apt install -y docker.io
|
||||
sudo apt install docker-compose
|
||||
|
||||
#For Arch-based systems
|
||||
sudo pacman -S docker.io
|
||||
sudo pacman -S docker-compose
|
||||
|
||||
# Making Docker run now and on startup
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# Using the CLI without sudo
|
||||
sudo usermod -aG docker $USER
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
## How to run
|
||||
- Navigate to the root of the project
|
||||
- Open a terminal
|
||||
- Start the container:
|
||||
```bash
|
||||
docker compose up #(might take a few minutes to build)
|
||||
```
|
||||
- Visit https://localhost:4600 to play the game locally
|
||||
- Or visit play it live [here!](https://jelly.ianvink.nl)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: production
|
||||
image: jelly-rescue-prod
|
||||
container_name: jelly-rescue-prod-cont
|
||||
ports:
|
||||
- "4600:80"
|
||||
restart: always
|
||||
cpu_period: 100000 # Default is 100,000 microseconds (100ms)
|
||||
cpu_quota: 30000 # 5% of the total CPU time
|
||||
@@ -1,56 +0,0 @@
|
||||
<!doctypehtml>
|
||||
<html lang=EN-us>
|
||||
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta content="text/html; charset=utf-8" http-equiv=Content-Type>
|
||||
<title>raylib web game</title>
|
||||
<meta content="raylib web game" name=title>
|
||||
|
||||
</head>
|
||||
<style>
|
||||
html {
|
||||
/* width:fit-content; */
|
||||
width: 100vw;
|
||||
height:100vh;
|
||||
}
|
||||
body {
|
||||
margin: 0px;
|
||||
/* overflow: hidden; */
|
||||
/* background-color: black; */
|
||||
width:100%;
|
||||
height:100%;
|
||||
display:flex;
|
||||
cursor:none;
|
||||
}
|
||||
canvas {
|
||||
margin:auto;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<canvas id="canvas" width="640" height="544"></canvas>
|
||||
<p id="output" />
|
||||
<script>
|
||||
var Module = {
|
||||
print: (function() {
|
||||
var element = document.getElementById('output');
|
||||
if (element) element.value = ''; // clear browser cache
|
||||
return function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.log(text);
|
||||
if (element) {
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = element.scrollHeight; // focus on bottom
|
||||
}
|
||||
};
|
||||
})(),
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
return canvas;
|
||||
})()
|
||||
};
|
||||
</script>
|
||||
<script src=game.js async></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
<!doctypehtml>
|
||||
<html lang=EN-us>
|
||||
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta content="text/html; charset=utf-8" http-equiv=Content-Type>
|
||||
<title>Jelly Rescue</title>
|
||||
<meta content="Jelly Rescue" name=title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<style>
|
||||
html {
|
||||
width: 100vw;
|
||||
height:100vh;
|
||||
background: #0C0D14;
|
||||
}
|
||||
body {
|
||||
margin: 0px;
|
||||
width:100%;
|
||||
height:100%;
|
||||
display:flex;
|
||||
}
|
||||
canvas {
|
||||
margin:auto;
|
||||
cursor:none;
|
||||
background: black;
|
||||
}
|
||||
.media-player {
|
||||
margin:auto;
|
||||
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
|
||||
border-radius: 0.4rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: rgb(33, 34, 51);
|
||||
box-shadow: inset 0px 0px 10px rgba(0, 0, 0, 0.4);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.game-title {
|
||||
color:ivory;
|
||||
margin:0.3rem 0.5rem 0.8rem 0.5rem;
|
||||
font-size: larger;
|
||||
font-family: 'Press Start 2P', cursive;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.links {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin:1.2rem 0.5rem 0 0.4rem;
|
||||
}
|
||||
|
||||
a {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.bi-github {
|
||||
margin-top:0.1rem;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: white;
|
||||
}
|
||||
.bi-github:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
@media (max-width: 643px) {
|
||||
.media-player {
|
||||
width: 100%; /* Make media-player take full width */
|
||||
}
|
||||
canvas {
|
||||
width:100%;
|
||||
}
|
||||
.game-title {
|
||||
font-size:medium;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="media-player">
|
||||
<canvas id="canvas" width="640" height="544"></canvas>
|
||||
<div class="links">
|
||||
<span class="game-title">Jelly Rescue</span>
|
||||
<a href="https://github.com/Ninjaws/WebJelly-Rescue" class="github-link" target="_blank">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
|
||||
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<p id="output" />
|
||||
<script>
|
||||
var Module = {
|
||||
print: (function() {
|
||||
var element = document.getElementById('output');
|
||||
if (element) element.value = '';
|
||||
return function(text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.log(text);
|
||||
if (element) {
|
||||
element.value += text + "\n";
|
||||
element.scrollTop = element.scrollHeight;
|
||||
}
|
||||
};
|
||||
})(),
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
return canvas;
|
||||
})()
|
||||
};
|
||||
</script>
|
||||
<script src=game.js async></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
bool hit; // Whether a PBullet has hit the crate
|
||||
bool hit = false; // Whether a PBullet has hit the crate
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "services/BulletService.h"
|
||||
#include "entities/Text.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
class Game
|
||||
{
|
||||
@@ -49,6 +50,7 @@ public:
|
||||
this->crosshair = TextureWrapper(AssetService::getInstance().getSprite(ESprite::CROSSHAIR), {15, 15}, {0, 0}, {0, 0, 15, 15});
|
||||
|
||||
CollectableService::getInstance().initCollectables();
|
||||
std::cout << "Initting" << std::endl;
|
||||
|
||||
initHud();
|
||||
initPauseScreen();
|
||||
|
||||
@@ -10,13 +10,13 @@ class Jelly
|
||||
public:
|
||||
Jelly(){
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY),{32,32});
|
||||
AssetService::getInstance().playSound(ESound::JELLY_FREED);
|
||||
// AssetService::getInstance().playSound(ESound::JELLY_FREED);
|
||||
}
|
||||
Jelly(Vector2 startPos)
|
||||
{
|
||||
this->startPosition = startPos;
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY),{32,32},startPos);
|
||||
AssetService::getInstance().playSound(ESound::JELLY_FREED);
|
||||
// AssetService::getInstance().playSound(ESound::JELLY_FREED);
|
||||
}
|
||||
|
||||
void logic()
|
||||
|
||||
+13
-60
@@ -73,23 +73,16 @@ std::vector<Vector2i> Enemy::getCorners()
|
||||
float top = texture.getPosition().y + velocity.y;
|
||||
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
// Vector2i leftTop(Vector2i((int)left / tileSize, (int)(top + 5) / tileSize));
|
||||
// Vector2i leftBottom(Vector2i((int)left / tileSize, (int)(bottom - 5) / tileSize));
|
||||
Vector2i leftCenter = Vector2i((int)(left -(spriteAnimation.y == Left ? gunLeft.getSize().x*(2.0f/3.0f) : 0.0f)) / tileSize, (int)(bottom - texture.getSize().y / 2.0) / tileSize);
|
||||
// Vector2i rightTop(Vector2i((int)right / tileSize, (int)(top + 5) / tileSize));
|
||||
// Vector2i rightBottom(Vector2i((int)right / tileSize, (int)(bottom - 5) / tileSize));
|
||||
Vector2i rightCenter = Vector2i((int)(right+ (spriteAnimation.y == Right ? gunRight.getSize().x*(2.0f/3.0f) : 0.0f)) / tileSize, (int)(bottom - texture.getSize().y / 2.0) / tileSize);
|
||||
Vector2i leftCenter = Vector2i((int)(left - (spriteAnimation.y == Left ? gunLeft.getSize().x * (2.0f / 3.0f) : 0.0f)) / tileSize, (int)(bottom - texture.getSize().y / 2.0) / tileSize);
|
||||
Vector2i rightCenter = Vector2i((int)(right + (spriteAnimation.y == Right ? gunRight.getSize().x * (2.0f / 3.0f) : 0.0f)) / tileSize, (int)(bottom - texture.getSize().y / 2.0) / tileSize);
|
||||
|
||||
Vector2i bottomLeft(Vector2i((int)(left + 5) / tileSize, (int)bottom / tileSize)); // +5 to separate bottom from side
|
||||
Vector2i bottomRight(Vector2i((int)(right - 5) / tileSize, (int)bottom / tileSize)); // -5 to separate bottom from side
|
||||
Vector2i bottomLeft(Vector2i((int)(left + 5) / tileSize, (int)bottom / tileSize));
|
||||
Vector2i bottomRight(Vector2i((int)(right - 5) / tileSize, (int)bottom / tileSize));
|
||||
|
||||
std::vector<Vector2i> corners;
|
||||
|
||||
corners.push_back(leftCenter);
|
||||
corners.push_back(rightCenter);
|
||||
// corners.push_back(leftBottom);
|
||||
// corners.push_back(rightTop);
|
||||
// corners.push_back(rightBottom);
|
||||
|
||||
corners.push_back(bottomLeft);
|
||||
corners.push_back(bottomRight);
|
||||
@@ -105,7 +98,6 @@ void Enemy::animate()
|
||||
Rectangle sourceRect = this->texture.getSourceRect();
|
||||
sourceRect.x = spriteAnimation.x * this->texture.getSize().x;
|
||||
sourceRect.y = spriteAnimation.y * this->texture.getSize().y;
|
||||
// sourceRect.x = std::fmod(sourceRect.x, 3 * this->texture.getSize().x);
|
||||
this->texture.setSourceRect(sourceRect);
|
||||
prevFrame = GetTime();
|
||||
}
|
||||
@@ -154,7 +146,6 @@ void Enemy::fall()
|
||||
|
||||
void Enemy::detectPlayer()
|
||||
{
|
||||
// playerSpotted = false;
|
||||
Player &player = PlayerService::getInstance().getPlayer();
|
||||
if (this->health > 0)
|
||||
{
|
||||
@@ -168,8 +159,6 @@ void Enemy::detectPlayer()
|
||||
float gunRotationLeft = atan2(playerCenter.y - enemyCenter.y,
|
||||
enemyCenter.x - playerCenter.x);
|
||||
float target = -gunRotationLeft * 180 / M_PI;
|
||||
// float delta = target - this->gunLeft.getRotation();
|
||||
// float sign = std::copysign(1.0f, delta);
|
||||
this->gunLeft.setRotation(std::min(this->gunLeft.getRotation() + aimSpeed, target));
|
||||
}
|
||||
else if (spriteAnimation.y == Right && player.getTexture().getPosition().x - this->texture.getPosition().x <= spottingRange &&
|
||||
@@ -179,8 +168,6 @@ void Enemy::detectPlayer()
|
||||
float gunRotationRight = atan2(playerCenter.y - enemyCenter.y,
|
||||
playerCenter.x - enemyCenter.x);
|
||||
float target = gunRotationRight * 180 / M_PI;
|
||||
|
||||
// this->gunRight.setRotation(gunRotationRight * 180 / M_PI);
|
||||
this->gunRight.setRotation(std::max(this->gunRight.getRotation() - aimSpeed, target));
|
||||
}
|
||||
|
||||
@@ -195,8 +182,8 @@ void Enemy::detectPlayer()
|
||||
{
|
||||
this->playerSpotted = false;
|
||||
/** Slowly ease the gun back to default position */
|
||||
this->gunLeft.setRotation(std::max(this->gunLeft.getRotation() - aimSpeed/2.0f, 0.0f));
|
||||
this->gunRight.setRotation(std::min(this->gunRight.getRotation() + aimSpeed/2.0f, 0.0f));
|
||||
this->gunLeft.setRotation(std::max(this->gunLeft.getRotation() - aimSpeed / 2.0f, 0.0f));
|
||||
this->gunRight.setRotation(std::min(this->gunRight.getRotation() + aimSpeed / 2.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,49 +202,15 @@ void Enemy::shoot()
|
||||
float offsetDistance = this->gunLeft.getSize().x - this->gunLeft.getSize().x / 3;
|
||||
Vector2 playerCenter = {player.getTexture().getPosition().x + player.getTexture().getSize().x / 2.0f, player.getTexture().getPosition().y + player.getTexture().getSize().y / 2.0f};
|
||||
Vector2 enemyCenter = {texture.getPosition().x + texture.getSize().x / 2.0f, texture.getPosition().y + texture.getSize().y / 2.0f};
|
||||
|
||||
|
||||
// if (spriteAnimation.y == Left)
|
||||
// {
|
||||
float angleShot = atan2(playerCenter.y - enemyCenter.y,
|
||||
playerCenter.x - enemyCenter.x);
|
||||
|
||||
float angleShot = atan2(playerCenter.y - enemyCenter.y,
|
||||
playerCenter.x - enemyCenter.x);
|
||||
float offsetX = cos(angleShot) * offsetDistance;
|
||||
float offsetY = sin(angleShot) * offsetDistance;
|
||||
Vector2 bulletStartLocation = {this->texture.getPosition().x + this->texture.getSize().x / 2.0f + offsetX,
|
||||
this->texture.getPosition().y + this->texture.getSize().y / 2.0f + offsetY};
|
||||
|
||||
// float gunRotationRadians = this->gunLeft.getRotation() * (M_PI / 180.0f); // Convert degrees to radians
|
||||
float offsetX = cos(angleShot) * offsetDistance;
|
||||
float offsetY = sin(angleShot) * offsetDistance;
|
||||
Vector2 bulletStartLocation = {this->texture.getPosition().x + this->texture.getSize().x / 2.0f + offsetX,
|
||||
this->texture.getPosition().y + this->texture.getSize().y / 2.0f + offsetY};
|
||||
|
||||
BulletService::getInstance().addEnemyBullet(bulletStartLocation, angleShot);
|
||||
// }
|
||||
|
||||
// if ((player.getTexture().getPosition().x > this->texture.getPosition().x + this->gunLeft.getSize().x && spriteAnimation.y == Right) ||
|
||||
// (player.getTexture().getPosition().x + (this->gunLeft.getSize().x / 2) < this->texture.getPosition().x && spriteAnimation.y == Left))
|
||||
// {
|
||||
|
||||
// // float gunRotationRight = atan2(GameService::getInstance().getMouseWorldPos().y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0),
|
||||
// // GameService::getInstance().getMouseWorldPos().x - (this->texture.getPosition().x + this->texture.getSize().x / 2.0));
|
||||
// // this->gunRight.setRotation(gunRotationRight * 180 / M_PI);
|
||||
|
||||
// float angleShot = atan2(player.getTexture().getPosition().y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0),
|
||||
// player.getTexture().getPosition().x - (this->texture.getPosition().x + this->texture.getSize().x / 2.0));
|
||||
|
||||
// // this->gunRight.setRotation(angleShot * 180 / M_PI);
|
||||
// // this->gunLeft.setRotation(-angleShot * 180 / M_PI);
|
||||
// /** Making the bullet originate from the gun's mouth */
|
||||
// float offsetDistance = this->gunLeft.getSize().x - this->gunLeft.getSize().x / 3;
|
||||
// float offsetX = cos(angleShot) * offsetDistance;
|
||||
// float offsetY = sin(angleShot) * offsetDistance;
|
||||
// Vector2 bulletStartLocation = {this->texture.getPosition().x + this->texture.getSize().x / 2.0f + offsetX,
|
||||
// this->texture.getPosition().y + this->texture.getSize().y / 2.0f + offsetY};
|
||||
|
||||
// // BulletService::getInstance().addEnemyBullet(bulletStartLocation, angleShot);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // this->gunRight.setRotation(0);
|
||||
// // this->gunLeft.setRotation(0);
|
||||
// }
|
||||
BulletService::getInstance().addEnemyBullet(bulletStartLocation, angleShot);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ void PBullet::objCollision()
|
||||
this->position.y + this->size > crate.getObject().getPosition().y && this->position.y-this->size < crate.getObject().getPosition().y + crate.getObject().getSize().y) {
|
||||
crate.setHit(true);
|
||||
AssetService::getInstance().playSound(ESound::CRATE_BREAK);
|
||||
AssetService::getInstance().playSound(ESound::JELLY_FREED);
|
||||
this->hasCollided = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user