@@ -20,7 +20,8 @@
|
||||
"source=./scripts,target=/app/scripts,type=bind",
|
||||
"source=./dist,target=/app/dist,type=bind",
|
||||
"source=./assets,target=/app/assets,type=bind",
|
||||
"source=./include,target=/app/include,type=bind"
|
||||
"source=./include,target=/app/include,type=bind",
|
||||
"source=./.vscode,target=/app/.vscode,type=bind"
|
||||
],
|
||||
|
||||
"customizations": {
|
||||
@@ -29,7 +30,7 @@
|
||||
"extensions": [
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"jeff-hykin.better-cpp-syntax"
|
||||
"vadimcn.vscode-lldb"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
name: Jelly Rescue Deployment
|
||||
run-name: ${{ gitea.actor }} is deploying Jelly Rescue
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
JellyRescue Runner:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- run: docker compose up -d --build
|
||||
@@ -0,0 +1,13 @@
|
||||
name: Jelly Rescue Testing
|
||||
run-name: ${{ gitea.actor }} is testing Jelly Rescue
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
JellyRescue Runner:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: docker --version
|
||||
- run: docker compose version
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
# Run tests
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug with LLDB",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/dist/jelly_rescue",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"miDebuggerPath": "/usr/bin/lldb-mi",
|
||||
"preLaunchTask": "build jelly_rescue",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"charconv": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"variant": "cpp",
|
||||
"format": "cpp",
|
||||
"text_encoding": "cpp",
|
||||
"ratio": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"__verbose_abort": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"cstring": "cpp",
|
||||
"fstream": "cpp"
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build jelly_rescue",
|
||||
"type": "shell",
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"g++ -std=c++20 -g -O0 $(find src/ -name \"*.cpp\") -o dist/jelly_rescue -I./include -L$LD_LIBRARY_PATH -lraylib -lGL -lm -lpthread -ldl -lrt -lX11"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": ["$gcc"],
|
||||
"detail": "Compiling the jelly_rescue project"
|
||||
}
|
||||
]
|
||||
}
|
||||
+37
-2
@@ -8,7 +8,7 @@ RUN apt-get update \
|
||||
cmake \
|
||||
libasound2-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev \
|
||||
libglu1-mesa-dev libxcursor-dev libxinerama-dev libwayland-dev libxkbcommon-dev \
|
||||
sudo \
|
||||
sudo lldb \
|
||||
alsa-utils \
|
||||
&& rm -rf /var/cache/apt/*
|
||||
|
||||
@@ -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
|
||||
+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>
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef AMMO_PACK_H
|
||||
#define AMMO_PACK_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
|
||||
class AmmoPack {
|
||||
public:
|
||||
AmmoPack() {
|
||||
this->object = TextureWrapper(AssetService::getInstance().getSprite(ESprite::AMMOPACK),{32,32});
|
||||
}
|
||||
void logic(){
|
||||
}
|
||||
|
||||
void draw() {
|
||||
DrawTexture(object.getTexture(), object.getPosition().x, object.getPosition().y, WHITE);
|
||||
}
|
||||
|
||||
int getAmmoAmount() {
|
||||
return this->ammoAmount;
|
||||
}
|
||||
|
||||
void setPickedUp(bool pickedUp) {
|
||||
this->pickedUp = pickedUp;
|
||||
}
|
||||
|
||||
bool hasBeenPickedUp() {
|
||||
return this->pickedUp;
|
||||
}
|
||||
|
||||
TextureWrapper& getObject() {
|
||||
return this->object;
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper object;
|
||||
unsigned int ammoAmount = 10; // Amount of ammo replenished by the pack
|
||||
bool pickedUp; // When the player has picked up the pack
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -8,38 +8,43 @@
|
||||
#include "services/AssetService.h"
|
||||
#include "services/StateService.h"
|
||||
|
||||
class Background {
|
||||
public:
|
||||
Background() {
|
||||
|
||||
class Background
|
||||
{
|
||||
public:
|
||||
Background()
|
||||
{
|
||||
}
|
||||
Background(EBackground background){
|
||||
// Texture2D texture = AssetService::getInstance().getBackground(background);
|
||||
TextureWrapper wrapper = TextureWrapper(AssetService::getInstance().getBackground(background), StateService::getInstance().getScreenSize(), {0,0});
|
||||
wrapper.setSourceRect({0,0,wrapper.getSize().x, wrapper.getSize().y});
|
||||
textures.push_back(wrapper);
|
||||
Background(EBackground background)
|
||||
{
|
||||
TextureWrapper wrapper = TextureWrapper(AssetService::getInstance().getBackground(background), StateService::getInstance().getScreenSize(), {0, 0});
|
||||
wrapper.setSourceRect({0, 0, wrapper.getSize().x, wrapper.getSize().y});
|
||||
textures.push_back(wrapper);
|
||||
}
|
||||
Background(std::vector<TextureWrapper> backgrounds)
|
||||
{
|
||||
for (int i = 0; i < backgrounds.size(); i++)
|
||||
{
|
||||
this->textures.push_back(backgrounds[i]);
|
||||
}
|
||||
Background(std::vector<TextureWrapper> backgrounds){
|
||||
for(int i = 0; i < backgrounds.size(); i++) {
|
||||
this->textures.push_back(backgrounds[i]);
|
||||
}
|
||||
}
|
||||
~Background() {}
|
||||
void draw()
|
||||
{
|
||||
for (int i = 0; i < textures.size(); i++)
|
||||
{
|
||||
TextureWrapper texture = textures[i];
|
||||
DrawTextureRec(texture.getTexture(), texture.getSourceRect(), texture.getPosition(), WHITE);
|
||||
}
|
||||
~Background(){}
|
||||
// Vector2 getPosition();
|
||||
// void updatePosition(Vector2 deltaPos);
|
||||
// void setPosition(Vector2 position);
|
||||
void draw(){
|
||||
for(int i = 0; i < textures.size(); i++) {
|
||||
TextureWrapper texture = textures[i];
|
||||
// Rectangle sourceRect = {0, 0, texture.getSize().x, texture.getSize().y};
|
||||
DrawTextureRec(texture.getTexture(), texture.getSourceRect(), texture.getPosition(),WHITE);
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<TextureWrapper> textures;
|
||||
// Vector2 position;
|
||||
// Vector2 size;
|
||||
}
|
||||
|
||||
Vector2 getBackgroundSize()
|
||||
{
|
||||
TextureWrapper lastbg = this->textures[this->textures.size() - 1];
|
||||
return {lastbg.getPosition().x + lastbg.getSize().x, lastbg.getPosition().y + lastbg.getSize().y};
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<TextureWrapper> textures;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef BULLET_H
|
||||
#define BULLET_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "entities/Vector2i.h"
|
||||
#include <cmath>
|
||||
|
||||
class Bullet
|
||||
{
|
||||
public:
|
||||
Bullet() {}
|
||||
Bullet(Vector2 pos, float direction)
|
||||
{
|
||||
this->position = pos;
|
||||
this->direction = direction;
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
move();
|
||||
hasCollided = false;
|
||||
objCollision();
|
||||
envCollision();
|
||||
// // detectCollision();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
DrawCircleGradient(position.x, position.y, size, color, ORANGE);
|
||||
}
|
||||
|
||||
bool getHasCollided()
|
||||
{
|
||||
return this->hasCollided;
|
||||
}
|
||||
|
||||
protected:
|
||||
Color color = RED;
|
||||
Vector2 position;
|
||||
int size = 7;
|
||||
bool hasCollided = false;
|
||||
|
||||
private:
|
||||
float direction;
|
||||
float velocity = 15.0f;
|
||||
|
||||
void move()
|
||||
{
|
||||
position.x += velocity * cos(direction);
|
||||
position.y += velocity * sin(direction);
|
||||
}
|
||||
void envCollision();
|
||||
virtual void objCollision() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef CRATE_H
|
||||
#define CRATE_H
|
||||
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
|
||||
class Crate
|
||||
{
|
||||
public:
|
||||
Crate()
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::CRATE), {32, 32});
|
||||
}
|
||||
|
||||
Crate(Vector2 pos)
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::CRATE), {32, 32}, pos);
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
}
|
||||
|
||||
bool hasBeenHit()
|
||||
{
|
||||
return this->hit;
|
||||
}
|
||||
|
||||
void setHit(bool hit)
|
||||
{
|
||||
this->hit = hit;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
DrawTexture(this->texture.getTexture(), this->texture.getPosition().x, this->texture.getPosition().y, WHITE);
|
||||
}
|
||||
|
||||
TextureWrapper &getObject()
|
||||
{
|
||||
return this->texture;
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
bool hit = false; // Whether a PBullet has hit the crate
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef EBULLET_H
|
||||
#define EBULLET_H
|
||||
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/Bullet.h"
|
||||
#include <cstdint>
|
||||
|
||||
class EBullet : public Bullet
|
||||
{
|
||||
public:
|
||||
EBullet() {}
|
||||
EBullet(Vector2 pos, float angle) : Bullet(pos, angle)
|
||||
{
|
||||
this->color = RED;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t damage = 1;
|
||||
void objCollision() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef ENEMY_H
|
||||
#define ENEMY_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "entities/Vector2i.h"
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
class Enemy
|
||||
{
|
||||
public:
|
||||
Enemy()
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY), {32, 32});
|
||||
this->gunRight = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY_GUN_RIGHT), {97, 27});
|
||||
this->gunLeft = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY_GUN_LEFT), {97, 27});
|
||||
prevFrame = GetTime();
|
||||
lastShot = GetTime();
|
||||
|
||||
/** Randomizes between 0 and 1 (+1 to get Left and Right in directions), so they dont all move in the same direction */
|
||||
int randDir = (int)((int)(GetTime() * 1000000) % 2);
|
||||
spriteAnimation = {0, randDir + 1};
|
||||
health = maxHealth;
|
||||
}
|
||||
Enemy(Vector2 startPos)
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY), {32, 32}, startPos);
|
||||
prevFrame = GetTime();
|
||||
|
||||
int randDir = (int)((int)(GetTime() * 1000000) % 2);
|
||||
spriteAnimation = {0, randDir + 1};
|
||||
health = maxHealth;
|
||||
}
|
||||
|
||||
void logic();
|
||||
|
||||
void draw()
|
||||
{
|
||||
drawGun();
|
||||
drawHealthBar();
|
||||
DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), WHITE);
|
||||
}
|
||||
|
||||
TextureWrapper &getObject()
|
||||
{
|
||||
return this->texture;
|
||||
}
|
||||
|
||||
uint8_t getHealth()
|
||||
{
|
||||
return this->health;
|
||||
}
|
||||
|
||||
void takeDamage()
|
||||
{
|
||||
this->health = std::max(health - 1, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
TextureWrapper gunLeft;
|
||||
TextureWrapper gunRight;
|
||||
uint8_t health;
|
||||
uint8_t maxHealth = 5;
|
||||
Vector2 velocity = {0, 0};
|
||||
float spottingRange = 300; // From how far away enemies can spot the player
|
||||
float gravity = 0.6f;
|
||||
float moveSpeed = 1.5f;
|
||||
float animationDelay = 0.2f; // In seconds
|
||||
double prevFrame; // Time since the last frame
|
||||
bool hasCollided = false;
|
||||
Vector2i spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Enemy direction
|
||||
enum Direction
|
||||
{
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Up
|
||||
}; // Used in conjuction with spriteAnimation, makes sure sprite direction matches with enemy direction
|
||||
float shotsPerSecond = 8.0f;
|
||||
double lastShot;
|
||||
bool playerSpotted = false;
|
||||
float aimSpeed = 2.0f; // How quickly the enemy can angle its gun to match the player (and to return to default)
|
||||
|
||||
void walk();
|
||||
void checkForCollision();
|
||||
std::vector<Vector2i> getCorners();
|
||||
void animate();
|
||||
void drawHealthBar();
|
||||
void drawGun();
|
||||
void fall();
|
||||
void detectPlayer();
|
||||
void shoot();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef FLAG_H
|
||||
#define FLAG_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "services/StateService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
|
||||
class Flag
|
||||
{
|
||||
public:
|
||||
Flag()
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::FLAG), {40, 40});
|
||||
}
|
||||
Flag(Vector2 startPos)
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::FLAG), {40, 40}, startPos);
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
// if (touched)
|
||||
// {
|
||||
// // StateService::getInstance().setScreen(EScreen::VICTORY);
|
||||
// }
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
DrawTextureEx(texture.getTexture(), texture.getPosition(), 0.0f, texture.getSize().x/texture.getTexture().width, WHITE);
|
||||
}
|
||||
|
||||
TextureWrapper &getObject()
|
||||
{
|
||||
return this->texture;
|
||||
}
|
||||
|
||||
void setTouched(bool touched) {
|
||||
this->touched = touched;
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
bool touched = false; // Whether the player has touched the flag
|
||||
};
|
||||
|
||||
#endif
|
||||
+327
-27
@@ -7,19 +7,28 @@
|
||||
#include "services/AudioService.h"
|
||||
#include "services/MapService.h"
|
||||
#include "services/InputService.h"
|
||||
#include "entities/Player.h"
|
||||
#include "services/GameService.h"
|
||||
#include "services/CollectableService.h"
|
||||
#include "services/EnemyService.h"
|
||||
#include "services/PlayerService.h"
|
||||
#include "services/BulletService.h"
|
||||
#include "entities/Text.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
Game()
|
||||
{
|
||||
TextureWrapper wrapper1 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME1), {GetScreenWidth()*2.0f,(float)GetScreenHeight()}, {0,0});
|
||||
wrapper1.setSourceRect({0,0,wrapper1.getSize().x, wrapper1.getSize().y});
|
||||
TextureWrapper wrapper2 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME2), {864.0f,(float)GetScreenHeight()}, {wrapper1.getSize().x,0.0});
|
||||
wrapper2.setSourceRect({0,200,wrapper2.getSize().x, 200+wrapper2.getSize().y});
|
||||
TextureWrapper wrapper3 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME3), {1792.0f,(float)GetScreenHeight()}, {wrapper1.getSize().x+wrapper2.getSize().x,0.0});
|
||||
wrapper3.setSourceRect({64,200,64+wrapper3.getSize().x, 200+wrapper3.getSize().y});
|
||||
GameService::getInstance().resetGame();
|
||||
|
||||
TextureWrapper wrapper1 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME1), {GetScreenWidth() * 2.0f, (float)GetScreenHeight()}, {0, 0});
|
||||
wrapper1.setSourceRect({0, 0, wrapper1.getSize().x, wrapper1.getSize().y});
|
||||
TextureWrapper wrapper2 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME2), {864.0f, (float)GetScreenHeight()}, {wrapper1.getSize().x, 0.0});
|
||||
wrapper2.setSourceRect({0, 200, wrapper2.getSize().x, 200 + wrapper2.getSize().y});
|
||||
TextureWrapper wrapper3 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME3), {1728.0f, (float)GetScreenHeight()}, {wrapper1.getSize().x + wrapper2.getSize().x, 0.0});
|
||||
wrapper3.setSourceRect({64, 200, 64 + wrapper3.getSize().x, 200 + wrapper3.getSize().y});
|
||||
|
||||
std::vector<TextureWrapper> wrappers;
|
||||
wrappers.push_back(wrapper1);
|
||||
@@ -35,56 +44,347 @@ public:
|
||||
camera.target = (Vector2){screenSize.x / 2.0f, screenSize.y / 2.0f}; // Initially at the center of the world
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
this->camera = camera;
|
||||
GameService::getInstance().setCamera(camera);
|
||||
BulletService::getInstance().initBullets();
|
||||
PlayerService::getInstance().initPlayer();
|
||||
this->crosshair = TextureWrapper(AssetService::getInstance().getSprite(ESprite::CROSSHAIR), {15, 15}, {0, 0}, {0, 0, 15, 15});
|
||||
|
||||
this->player = Player();
|
||||
this->player.getTexture().setPosition({200,350});
|
||||
CollectableService::getInstance().initCollectables();
|
||||
std::cout << "Initting" << std::endl;
|
||||
|
||||
InputService::getInstance().setKeysToWatch({KEY_SPACE, KEY_A, KEY_D}, {MOUSE_BUTTON_LEFT});
|
||||
initHud();
|
||||
initPauseScreen();
|
||||
initGameOverScreen();
|
||||
EnemyService::getInstance().initEnemies();
|
||||
|
||||
InputService::getInstance().setKeysToWatch({KEY_A, KEY_W, KEY_S, KEY_D, KEY_ENTER}, {MOUSE_BUTTON_LEFT});
|
||||
AudioService::getInstance().setMusic(EMusic::GAME);
|
||||
AudioService::getInstance().playMusic();
|
||||
}
|
||||
|
||||
~Game()
|
||||
{
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
// this->camera.offset.x -= 1.5;
|
||||
this->player.logic();
|
||||
if(this->player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f)) {
|
||||
this->camera.offset = {(StateService::getInstance().getScreenSize().x / 2.0f) +((StateService::getInstance().getScreenSize().x / 2.0f) - this->player.getTexture().getPosition().x), StateService::getInstance().getScreenSize().y / 2.0f};
|
||||
this->crosshair.setPosition(InputService::getInstance().getMousePos());
|
||||
|
||||
if (GameService::getInstance().isPaused())
|
||||
{
|
||||
pausedLogic();
|
||||
return;
|
||||
}
|
||||
else if (GameService::getInstance().isGameOver())
|
||||
{
|
||||
gameOverLogic();
|
||||
return;
|
||||
}
|
||||
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER))
|
||||
{
|
||||
GameService::getInstance().setPaused(true);
|
||||
return;
|
||||
}
|
||||
|
||||
BulletService::getInstance().bulletLogic();
|
||||
CollectableService::getInstance().collectableLogic();
|
||||
EnemyService::getInstance().enemyLogic();
|
||||
|
||||
auto &player = PlayerService::getInstance().getPlayer();
|
||||
player.logic();
|
||||
if (player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f) &&
|
||||
player.getTexture().getPosition().x + (StateService::getInstance().getScreenSize().x / 2.0f) < background.getBackgroundSize().x)
|
||||
{
|
||||
GameService::getInstance().getCamera().offset = {(StateService::getInstance().getScreenSize().x / 2.0f) + ((StateService::getInstance().getScreenSize().x / 2.0f) - player.getTexture().getPosition().x), StateService::getInstance().getScreenSize().y / 2.0f};
|
||||
}
|
||||
if (player.isFinishReached())
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::VICTORY);
|
||||
}
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
BeginDrawing();
|
||||
BeginMode2D(this->camera);
|
||||
BeginMode2D(GameService::getInstance().getCamera());
|
||||
|
||||
this->background.draw();
|
||||
|
||||
BulletService::getInstance().drawBullets();
|
||||
this->map.draw();
|
||||
this->player.draw();
|
||||
CollectableService::getInstance().drawCollectables();
|
||||
EnemyService::getInstance().drawEnemies();
|
||||
PlayerService::getInstance().getPlayer().draw();
|
||||
|
||||
EndMode2D();
|
||||
|
||||
drawHud();
|
||||
if (GameService::getInstance().isPaused())
|
||||
{
|
||||
drawPaused();
|
||||
}
|
||||
else if (GameService::getInstance().isGameOver())
|
||||
{
|
||||
drawGameOver();
|
||||
}
|
||||
else
|
||||
{
|
||||
drawCrosshair();
|
||||
}
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
private:
|
||||
Camera2D camera;
|
||||
Background background;
|
||||
Map map;
|
||||
Player player;
|
||||
// std::vector<Enemy> enemies
|
||||
// std::vector<Create> crates
|
||||
// std::vector<PBullet> playerBullets
|
||||
// std::vector<EBullet> enemyBullets
|
||||
// std::vector<Jelly> jellies
|
||||
// std::vector<Ammo> ammo
|
||||
// std::vector<Healthpack> healthpacks
|
||||
// Powerup powerup
|
||||
TextureWrapper crosshair;
|
||||
std::vector<Enemy> enemies;
|
||||
|
||||
std::vector<Text> pauseScreenButtons;
|
||||
int hoveredPauseScreenButton = 0;
|
||||
|
||||
Text gameOverText;
|
||||
std::vector<Text> gameOverScreenButtons;
|
||||
int hoveredGameOverScreenButton = 0;
|
||||
|
||||
Text hudJellyText;
|
||||
TextureWrapper hudJellyTexture;
|
||||
|
||||
void initHud()
|
||||
{
|
||||
hudJellyTexture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY), {32, 32}, {500, 5});
|
||||
hudJellyText = Text("0/3", EFont::SANSATION, 30, 0, RED, {hudJellyTexture.getPosition().x + hudJellyTexture.getSize().x * 1.5f, hudJellyTexture.getPosition().y + 5});
|
||||
}
|
||||
|
||||
void initPauseScreen()
|
||||
{
|
||||
#if defined(PLATFORM_WEB)
|
||||
const int TOP_GAP = 100;
|
||||
const int BOTTOM_GAP = 100;
|
||||
const int AMNT_OF_BUTTONS = 2;
|
||||
#else
|
||||
const int TOP_GAP = 100;
|
||||
const int BOTTOM_GAP = 50;
|
||||
const int AMNT_OF_BUTTONS = 4;
|
||||
#endif
|
||||
|
||||
const int TOTAL_SPACE = GetScreenHeight() - (TOP_GAP + BOTTOM_GAP);
|
||||
const int SPACE_PER_ITEM = TOTAL_SPACE / AMNT_OF_BUTTONS;
|
||||
|
||||
for (int i = 0; i < AMNT_OF_BUTTONS; i++)
|
||||
{
|
||||
Text txt = Text("Continue", EFont::SANSATION, 30, 0, WHITE);
|
||||
pauseScreenButtons.push_back(txt);
|
||||
}
|
||||
pauseScreenButtons[0].setColor(RED);
|
||||
|
||||
#if defined(PLATFORM_WEB)
|
||||
pauseScreenButtons[1].setText("Quit to Main Menu");
|
||||
#else
|
||||
pauseScreenButtons[1].setText("Save Game");
|
||||
pauseScreenButtons[2].setText("Quit to Main Menu");
|
||||
pauseScreenButtons[3].setText("Quit to Desktop");
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < AMNT_OF_BUTTONS; i++)
|
||||
{
|
||||
#if defined(PLATFORM_WEB)
|
||||
pauseScreenButtons[i].setPosition({(float)(GetScreenWidth() - pauseScreenButtons[i].getDimensions().x) / 2.0f, (float)TOP_GAP + SPACE_PER_ITEM * i + SPACE_PER_ITEM / 2.0f});
|
||||
|
||||
#else
|
||||
pauseScreenButtons[i].setPosition({(float)(GetScreenWidth() - pauseScreenButtons[i].getDimensions().x) / 2.0f, (float)TOP_GAP + SPACE_PER_ITEM * i});
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void initGameOverScreen()
|
||||
{
|
||||
this->gameOverText = Text("Game Over", EFont::SANSATION, 60, 0, WHITE);
|
||||
this->gameOverText.setPosition({(float)(GetScreenWidth() - gameOverText.getDimensions().x) / 2.0f, (float)(GetScreenHeight() - gameOverText.getDimensions().y) / 3.0f});
|
||||
|
||||
const int TOP_POS = GetScreenHeight() / 1.8;
|
||||
const int X_GAP = 90;
|
||||
const int AMNT_OF_BUTTONS = 2;
|
||||
const int TOTAL_SPACE = GetScreenWidth() - (X_GAP + X_GAP);
|
||||
const int SPACE_PER_ITEM = TOTAL_SPACE / AMNT_OF_BUTTONS;
|
||||
for (int i = 0; i < AMNT_OF_BUTTONS; i++)
|
||||
{
|
||||
Text txt = Text("Play Again", EFont::SANSATION, 30, 0, BLACK);
|
||||
gameOverScreenButtons.push_back(txt);
|
||||
}
|
||||
gameOverScreenButtons[0].setColor(WHITE);
|
||||
gameOverScreenButtons[1].setText("Quit to Main Menu");
|
||||
for (int i = 0; i < AMNT_OF_BUTTONS; i++)
|
||||
{
|
||||
gameOverScreenButtons[i].setPosition({(float)X_GAP + SPACE_PER_ITEM * i, (float)TOP_POS});
|
||||
}
|
||||
}
|
||||
|
||||
void pausedLogic()
|
||||
{
|
||||
if (InputService::getInstance().isKeyPressed(KEY_S) || InputService::getInstance().isKeyPressed(KEY_W))
|
||||
{
|
||||
pauseScreenButtons[hoveredPauseScreenButton].setColor(WHITE);
|
||||
/** Move up or down depending on the pressed button. +4 is used so that -1 becomes 3 (the last button) */
|
||||
hoveredPauseScreenButton = ((hoveredPauseScreenButton - (InputService::getInstance().isKeyPressed(KEY_S) ? -1 : 1)) + pauseScreenButtons.size()) % pauseScreenButtons.size();
|
||||
pauseScreenButtons[hoveredPauseScreenButton].setColor(RED);
|
||||
}
|
||||
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER))
|
||||
{
|
||||
|
||||
std::string selectedButton = pauseScreenButtons[hoveredPauseScreenButton].getText();
|
||||
|
||||
if (selectedButton == "Continue")
|
||||
{
|
||||
GameService::getInstance().setPaused(false);
|
||||
AudioService::getInstance().playMusic();
|
||||
}
|
||||
else if (selectedButton == "Save Game")
|
||||
{
|
||||
}
|
||||
else if (selectedButton == "Quit to Main Menu")
|
||||
StateService::getInstance().setScreen(EScreen::MAIN);
|
||||
else if (selectedButton == "Quit to Desktop")
|
||||
StateService::getInstance().setScreen(EScreen::CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
void gameOverLogic()
|
||||
{
|
||||
if (InputService::getInstance().isKeyPressed(KEY_D) || InputService::getInstance().isKeyPressed(KEY_A))
|
||||
{
|
||||
gameOverScreenButtons[hoveredGameOverScreenButton].setColor(BLACK);
|
||||
/** Move up or down depending on the pressed button. +4 is used so that -1 becomes 3 (the last button) */
|
||||
hoveredGameOverScreenButton = ((hoveredGameOverScreenButton - (InputService::getInstance().isKeyPressed(KEY_D) ? -1 : 1)) + gameOverScreenButtons.size()) % gameOverScreenButtons.size();
|
||||
gameOverScreenButtons[hoveredGameOverScreenButton].setColor(WHITE);
|
||||
}
|
||||
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER))
|
||||
{
|
||||
std::string selectedButton = gameOverScreenButtons[hoveredGameOverScreenButton].getText();
|
||||
|
||||
if (selectedButton == "Play Again")
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::GAME);
|
||||
}
|
||||
else if (selectedButton == "Quit to Main Menu")
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::MAIN);
|
||||
}
|
||||
GameService::getInstance().setGameOver(false);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPaused()
|
||||
{
|
||||
// 100, 100, 255, 60
|
||||
DrawRectangle(0, 0, StateService::getInstance().getScreenSize().x, StateService::getInstance().getScreenSize().y, {0, 0, 0, 200});
|
||||
if (pauseScreenButtons.size() > 0)
|
||||
{
|
||||
for (int i = 0; i < pauseScreenButtons.size(); i++)
|
||||
{
|
||||
pauseScreenButtons[i].draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawGameOver()
|
||||
{
|
||||
DrawRectangle(0, 0, StateService::getInstance().getScreenSize().x, StateService::getInstance().getScreenSize().y, {100, 0, 0, 200});
|
||||
|
||||
gameOverText.draw();
|
||||
|
||||
for (int i = 0; i < gameOverScreenButtons.size(); i++)
|
||||
{
|
||||
gameOverScreenButtons[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void drawCrosshair()
|
||||
{
|
||||
DrawTextureEx(
|
||||
this->crosshair.getTexture(),
|
||||
{InputService::getInstance().getMousePos().x - this->crosshair.getSize().x / 2.0f, InputService::getInstance().getMousePos().y - this->crosshair.getSize().y / 2.0f},
|
||||
0,
|
||||
1.2f,
|
||||
RED);
|
||||
}
|
||||
|
||||
void drawHud()
|
||||
{
|
||||
drawHudHealth();
|
||||
drawHudBullets();
|
||||
drawHudJellies();
|
||||
}
|
||||
|
||||
void drawHudBullets()
|
||||
{
|
||||
Vector2i pixel_pos = Vector2i(5, 40);
|
||||
Texture2D ammoSprite = AssetService::getInstance().getSprite(ESprite::HUD_AMMO);
|
||||
Vector2i display_pos;
|
||||
for (int i = 0; i < PlayerService::getInstance().getPlayer().getAmmo(); i++)
|
||||
{
|
||||
if (i <= 49)
|
||||
{
|
||||
display_pos = Vector2i(pixel_pos.x + ammoSprite.width * i, pixel_pos.y);
|
||||
}
|
||||
if (i > 49 && i <= 99)
|
||||
{
|
||||
display_pos = Vector2i(pixel_pos.x + ammoSprite.width * (i - (50)), pixel_pos.y + ammoSprite.height);
|
||||
}
|
||||
else if (i > 99 && i <= 149)
|
||||
{
|
||||
display_pos = Vector2i(pixel_pos.x + ammoSprite.width * (i - (100)), pixel_pos.y + ammoSprite.height * 2);
|
||||
}
|
||||
else if (i > 149 && i <= 199)
|
||||
{
|
||||
display_pos = Vector2i(pixel_pos.x + ammoSprite.width * (i - (150)), pixel_pos.y + ammoSprite.height * 3);
|
||||
}
|
||||
else if (i > 199 && i <= 249)
|
||||
{
|
||||
display_pos = Vector2i(pixel_pos.x + ammoSprite.width * (i - (200)), pixel_pos.y + ammoSprite.height * 4);
|
||||
}
|
||||
DrawTexture(ammoSprite, display_pos.x, display_pos.y, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void drawHudHealth()
|
||||
{
|
||||
Vector2i pixel_pos = Vector2i(5, 5);
|
||||
Texture2D noHealthSprite = AssetService::getInstance().getSprite(ESprite::HUD_HEART_EMPTY);
|
||||
Texture2D healthSprite = AssetService::getInstance().getSprite(ESprite::HUD_HEART);
|
||||
// sVector2f coord_pos = GetWindow().mapPixelToCoords(pixel_pos);
|
||||
for (int i = 0; i < PlayerService::getInstance().getPlayer().getMaxHealth(); i++)
|
||||
{
|
||||
Vector2i pos = Vector2i(pixel_pos.x + noHealthSprite.width * i, pixel_pos.y);
|
||||
// noHealthSprite[i].setPosition(coord_pos.x + noHealthTexture.getSize().x * i, coord_pos.y);
|
||||
DrawTexture(noHealthSprite, pos.x, pos.y, WHITE);
|
||||
}
|
||||
for (int i = 0; i < PlayerService::getInstance().getPlayer().getHealth(); i++)
|
||||
{
|
||||
// healthSprite[i].setPosition(coord_pos.x + healthTexture.getSize().x * i, coord_pos.y);
|
||||
// DrawTexture(ammoSprite, display_pos.x, display_pos.y, WHITE);
|
||||
Vector2i pos = Vector2i(pixel_pos.x + healthSprite.width * i, pixel_pos.y);
|
||||
// noHealthSprite[i].setPosition(coord_pos.x + noHealthTexture.getSize().x * i, coord_pos.y);
|
||||
DrawTexture(healthSprite, pos.x, pos.y, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void drawHudJellies()
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream.clear();
|
||||
stream << CollectableService::getInstance().getAmountOfJelliesFreed();
|
||||
stream << "/";
|
||||
stream << CollectableService::getInstance().getMaxAmountOfJellies();
|
||||
hudJellyText.setText(stream.str());
|
||||
|
||||
DrawTexture(hudJellyTexture.getTexture(), hudJellyTexture.getPosition().x, hudJellyTexture.getPosition().y, WHITE);
|
||||
hudJellyText.draw();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef HEALTH_PACK_H
|
||||
#define HEALTH_PACK_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
|
||||
class HealthPack {
|
||||
public:
|
||||
HealthPack() {
|
||||
this->object = TextureWrapper(AssetService::getInstance().getSprite(ESprite::HEALTHPACK),{32,32});
|
||||
}
|
||||
void logic(){
|
||||
}
|
||||
|
||||
void draw() {
|
||||
DrawTexture(object.getTexture(), object.getPosition().x, object.getPosition().y, WHITE);
|
||||
}
|
||||
|
||||
int getHealAmount() {
|
||||
return this->healAmount;
|
||||
}
|
||||
|
||||
void setPickedUp(bool pickedUp) {
|
||||
this->pickedUp = pickedUp;
|
||||
}
|
||||
|
||||
bool hasBeenPickedUp() {
|
||||
return this->pickedUp;
|
||||
}
|
||||
|
||||
TextureWrapper& getObject() {
|
||||
return this->object;
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper object;
|
||||
unsigned int healAmount = 2; // Amount of health replenished by the pack
|
||||
bool pickedUp; // When the player has picked up the pack
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef JELLY_H
|
||||
#define JELLY_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
|
||||
class Jelly
|
||||
{
|
||||
public:
|
||||
Jelly(){
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY),{32,32});
|
||||
// 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);
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
if (texture.getPosition().y >= startPosition.y)
|
||||
{
|
||||
velocity.y = -jumpSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.y += gravity;
|
||||
}
|
||||
|
||||
texture.move(velocity);
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
DrawTexture(texture.getTexture(), texture.getPosition().x, texture.getPosition().y, WHITE);
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
float jumpSpeed = 7.0f;
|
||||
float gravity = 0.6f;
|
||||
Vector2 velocity = {0, 0};
|
||||
Vector2 startPosition = {0,0};
|
||||
};
|
||||
|
||||
#endif
|
||||
+12
-3
@@ -1,9 +1,10 @@
|
||||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include <vector>
|
||||
#include "raylib.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "entities/Vector2i.h"
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
/**
|
||||
@@ -18,12 +19,20 @@ public:
|
||||
void draw();
|
||||
|
||||
/** Checks and returns which corners of the object have been collided with */
|
||||
std::unordered_map<ECorner, bool> checkForCollision(TextureWrapper texture);
|
||||
// std::unordered_map<ECorner, bool> checkForCollision(TextureWrapper texture);
|
||||
|
||||
int getTileSize() {
|
||||
return this->tileSize;
|
||||
}
|
||||
|
||||
std::vector<std::vector<int>> getColMap() {
|
||||
return this->colMap;
|
||||
}
|
||||
|
||||
void updateColmapTile(Vector2i tile, bool collision) {
|
||||
this->colMap[tile.y][tile.x] = collision ? 1 : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
/** Holds the number for every single tile, which refers to a certain sprite in the tileset */
|
||||
std::vector<std::vector<Vector2>> map;
|
||||
@@ -41,7 +50,7 @@ private:
|
||||
/**
|
||||
* Converts the corners of the object to the matching tiles, so that they can be checked for collision
|
||||
*/
|
||||
std::unordered_map<ECorner, Vector2> cornersToTilePos(std::unordered_map<ECorner, Vector2> corners);
|
||||
// std::unordered_map<ECorner, Vector2> cornersToTilePos(std::unordered_map<ECorner, Vector2> corners);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef PBULLET_H
|
||||
#define PBULLET_H
|
||||
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/Bullet.h"
|
||||
|
||||
class PBullet : public Bullet
|
||||
{
|
||||
public:
|
||||
PBullet() {}
|
||||
PBullet(Vector2 pos, float angle) : Bullet(pos, angle)
|
||||
{
|
||||
this->color = YELLOW;
|
||||
}
|
||||
|
||||
private:
|
||||
void objCollision() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
+94
-81
@@ -2,36 +2,54 @@
|
||||
#define PLAYER_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include <unordered_map>
|
||||
#include "services/AssetService.h"
|
||||
#include "services/MapService.h"
|
||||
#include "services/InputService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "enums/ECorner.h"
|
||||
#include "enums/ESound.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "entities/Vector2i.h"
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
class PBullet;
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
Player()
|
||||
{
|
||||
TextureWrapper wrapper = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER), {32, 32}, {200, 200});
|
||||
wrapper.setSourceRect({0, 0, 32, 32});
|
||||
this->texture = wrapper;
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER), {32, 32}, {200, 200});
|
||||
prevFrame = GetTime();
|
||||
spriteAnimation = {0, Right};
|
||||
this->gunRight = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER_GUN_RIGHT), {58, 29}, {0, 0});
|
||||
this->gunLeft = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER_GUN_LEFT), {58, 29}, {0, 0});
|
||||
this->ammo = max_ammo;
|
||||
this->prevShot = GetTime();
|
||||
this->health = max_health;
|
||||
}
|
||||
|
||||
~Player()
|
||||
{
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
gravity();
|
||||
/** Fall out of the map when the jelly has been killed */
|
||||
if(this->health == 0) {
|
||||
fall();
|
||||
return;
|
||||
}
|
||||
rotateGun();
|
||||
shoot();
|
||||
movement();
|
||||
handleCollision();
|
||||
outofboundsCheck();
|
||||
consumableCollision();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), WHITE);
|
||||
drawGun();
|
||||
DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), gainedPowerup ? RED : WHITE);
|
||||
}
|
||||
|
||||
TextureWrapper &getTexture()
|
||||
@@ -39,85 +57,80 @@ public:
|
||||
return this->texture;
|
||||
}
|
||||
|
||||
void setPosition(Vector2 pos)
|
||||
{
|
||||
this->texture.setPosition(pos);
|
||||
}
|
||||
|
||||
int getAmmo()
|
||||
{
|
||||
return this->ammo;
|
||||
}
|
||||
|
||||
uint8_t getHealth()
|
||||
{
|
||||
return this->health;
|
||||
}
|
||||
|
||||
uint8_t getMaxHealth()
|
||||
{
|
||||
return this->max_health;
|
||||
}
|
||||
|
||||
void takeDamage(uint8_t damage) {
|
||||
this->health = std::max(health - damage, 0);
|
||||
}
|
||||
|
||||
bool isFinishReached() {
|
||||
return this->finishReached;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
TextureWrapper gunLeft;
|
||||
TextureWrapper gunRight;
|
||||
Vector2 velocity = {0, 0};
|
||||
float jumpPower = 7.2f;
|
||||
float moveSpeed = 5.0f;
|
||||
float gravity = 0.6f;
|
||||
float animationDelay = 0.2f; // In seconds
|
||||
double prevFrame; // Time since the last frame
|
||||
Vector2i spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Player direction
|
||||
enum Direction
|
||||
{
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Up
|
||||
}; // Used in conjuction with spriteAnimation, makes sure sprite direction matches with player direction
|
||||
|
||||
std::vector<Vector2i> tiles; // Holds eight points of the player for accurate collision
|
||||
std::vector<unsigned int> timesCollision; // Holds the amount of times the player has collided with a tile, and which corner of the player is touching a tile
|
||||
bool groundCollision; // Keeps track of whether or not the player has collided with the ground
|
||||
bool crateTopCollision;
|
||||
/**
|
||||
* Holds the corners of the player
|
||||
* Is used for precise collision detection
|
||||
*/
|
||||
bool crateTopCollision; // Whether the player is standing on top of a crate
|
||||
|
||||
void gravity()
|
||||
{
|
||||
if (!groundCollision)
|
||||
{
|
||||
velocity.y += 0.6f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// velocity.y = 0.0f;
|
||||
}
|
||||
}
|
||||
uint8_t ammo; // Current ammo of the player
|
||||
uint8_t max_ammo = 100; // Max ammo of the player
|
||||
float firingRate = 0.2f; // Delay in seconds
|
||||
double prevShot; // The last time the player fired a bullet
|
||||
uint8_t health; // Current health of the player
|
||||
uint8_t max_health = 10; // Max health of the player
|
||||
bool gainedPowerup = false;
|
||||
bool finishReached = false;
|
||||
|
||||
void movement()
|
||||
{
|
||||
velocity.x = 0.0f;
|
||||
if (InputService::getInstance().isKeyDown(KEY_A))
|
||||
{
|
||||
velocity.x -= 5.0f;
|
||||
}
|
||||
else if (InputService::getInstance().isKeyDown(KEY_D))
|
||||
{
|
||||
velocity.x += 5.0f;
|
||||
}
|
||||
|
||||
if (InputService::getInstance().isKeyPressed(KEY_SPACE) && groundCollision)
|
||||
{
|
||||
velocity.y -= 7.2f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the current position
|
||||
* Applies the current velocity
|
||||
* Checks for collision, and removes all velocities that are causing collisions
|
||||
* Set the object exactly against the object it is colliding with position
|
||||
*/
|
||||
void handleCollision()
|
||||
{
|
||||
Vector2 tempPos = this->texture.getPosition();
|
||||
this->texture.move(velocity);
|
||||
|
||||
groundCollision = false;
|
||||
std::unordered_map<ECorner, bool> collisions = MapService::getInstance().getMap().checkForCollision(this->texture);
|
||||
|
||||
if (collisions[ECorner::BOTTOM_LEFT] || collisions[ECorner::BOTTOM_RIGHT])
|
||||
{
|
||||
velocity.y = 0.0f;
|
||||
groundCollision = true;
|
||||
this->texture.setPosition({this->texture.getPosition().x, floorf(this->texture.getPosition().y / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize()});
|
||||
}
|
||||
if (collisions[ECorner::LEFT_TOP] && collisions[ECorner::LEFT_BOTTOM])
|
||||
{
|
||||
velocity.x = 0.0f;
|
||||
this->texture.setPosition({ceilf(this->texture.getPosition().x / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize(), this->texture.getPosition().y});
|
||||
}
|
||||
if (collisions[ECorner::TOP_LEFT] || collisions[ECorner::TOP_RIGHT])
|
||||
{
|
||||
velocity.y = 0.0f;
|
||||
this->texture.setPosition({this->texture.getPosition().x, (ceilf(this->texture.getPosition().y / MapService::getInstance().getMap().getTileSize())) * MapService::getInstance().getMap().getTileSize()});
|
||||
}
|
||||
if (collisions[ECorner::RIGHT_TOP] && collisions[ECorner::RIGHT_BOTTOM])
|
||||
{
|
||||
velocity.x = 0.0f;
|
||||
this->texture.setPosition({floorf(this->texture.getPosition().x / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize(), this->texture.getPosition().y});
|
||||
}
|
||||
}
|
||||
void applyGravity();
|
||||
void movement();
|
||||
void move(Vector2 velocity);
|
||||
void animate();
|
||||
void positionUpdates();
|
||||
void handleCollision();
|
||||
void consumableCollision();
|
||||
void outofboundsCheck();
|
||||
void rotateGun();
|
||||
void drawGun();
|
||||
void shoot();
|
||||
void fall(); // Lets the player fall out of the map when he dies
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef POWERUP_H
|
||||
#define POWERUP_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include <cstdint>
|
||||
|
||||
class Powerup {
|
||||
public:
|
||||
Powerup() {
|
||||
this->object = TextureWrapper(AssetService::getInstance().getSprite(ESprite::POWERUP),{50,55});
|
||||
}
|
||||
void logic(){
|
||||
animate();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
DrawTextureRec(object.getTexture(), object.getSourceRect(), object.getPosition(), WHITE);
|
||||
}
|
||||
|
||||
float getExtraJumpPower() {
|
||||
return this->extraJumpPower;
|
||||
}
|
||||
|
||||
void setPickedUp(bool pickedUp) {
|
||||
this->pickedUp = pickedUp;
|
||||
}
|
||||
|
||||
bool hasBeenPickedUp() {
|
||||
return this->pickedUp;
|
||||
}
|
||||
|
||||
TextureWrapper& getObject() {
|
||||
return this->object;
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper object;
|
||||
float extraJumpPower = 2.0f; // Jump power gained by grabbing the powerup
|
||||
bool pickedUp = false; // When the player has picked up the pack
|
||||
float animationDelay = 0.08f; // How long to wait in between animation frames (in seconds)
|
||||
double lastFrame; // Time since the last frame
|
||||
uint8_t currentFrame = 0; // Current frame of the animation
|
||||
uint8_t amountOfFrames = 8; // Total amount of animation frames
|
||||
|
||||
void animate() {
|
||||
if(GetTime() - lastFrame > animationDelay) {
|
||||
currentFrame ++;
|
||||
currentFrame %= amountOfFrames;
|
||||
|
||||
object.setSourceRect({(float)currentFrame * 81 + 16, 10,object.getSize().x, object.getSize().y});
|
||||
lastFrame = GetTime();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
+37
-30
@@ -3,46 +3,53 @@
|
||||
|
||||
#include "raylib.h"
|
||||
#include "enums/EFont.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "services/AssetService.h"
|
||||
#include <string>
|
||||
|
||||
class Text {
|
||||
public:
|
||||
Text(std::string text, EFont font, int fontSize = 30, int spacing = 0, Color color = WHITE, Vector2 position = {100,100});
|
||||
~Text(){}
|
||||
class Text
|
||||
{
|
||||
public:
|
||||
Text() {}
|
||||
Text(std::string text, EFont font, int fontSize = 30, int spacing = 0, Color color = WHITE, Vector2 position = {100, 100});
|
||||
~Text() {
|
||||
}
|
||||
|
||||
Vector2 getDimensions();
|
||||
Vector2 getDimensions();
|
||||
|
||||
void setPosition(Vector2 position) {
|
||||
this->position = position;
|
||||
}
|
||||
void setPosition(Vector2 position)
|
||||
{
|
||||
this->position = position;
|
||||
}
|
||||
|
||||
void setColor(Color color) {
|
||||
this->color = color;
|
||||
}
|
||||
void setColor(Color color)
|
||||
{
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
void setText(std::string text) {
|
||||
this->text = text;
|
||||
}
|
||||
void setText(std::string text)
|
||||
{
|
||||
this->text = text;
|
||||
}
|
||||
|
||||
Vector2 getPosition() {
|
||||
return position;
|
||||
}
|
||||
Vector2 getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
std::string getText() {
|
||||
return this->text;
|
||||
}
|
||||
std::string getText()
|
||||
{
|
||||
return this->text;
|
||||
}
|
||||
|
||||
void draw();
|
||||
void draw();
|
||||
|
||||
private:
|
||||
std::string text;
|
||||
Font font;
|
||||
int fontSize;
|
||||
int spacing;
|
||||
Color color;
|
||||
Vector2 position;
|
||||
private:
|
||||
std::string text;
|
||||
Font font;
|
||||
int fontSize;
|
||||
int spacing;
|
||||
Color color;
|
||||
Vector2 position;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "raylib.h"
|
||||
#include "enums/ECorner.h"
|
||||
#include <unordered_map>
|
||||
|
||||
class TextureWrapper {
|
||||
public:
|
||||
@@ -12,9 +11,9 @@ class TextureWrapper {
|
||||
this->texture = texture;
|
||||
this->size = size;
|
||||
this->position = position;
|
||||
this->sourceRect = sourceRect;
|
||||
}
|
||||
~TextureWrapper() {
|
||||
|
||||
}
|
||||
|
||||
Texture2D getTexture() {
|
||||
@@ -33,6 +32,10 @@ class TextureWrapper {
|
||||
return this->position;
|
||||
}
|
||||
|
||||
float getRotation() {
|
||||
return this->rotation;
|
||||
}
|
||||
|
||||
void setSourceRect(Rectangle rect) {
|
||||
this->sourceRect = rect;
|
||||
}
|
||||
@@ -41,28 +44,12 @@ class TextureWrapper {
|
||||
this->position = position;
|
||||
}
|
||||
|
||||
void move(Vector2 deltaPos) {
|
||||
this->position = {this->position.x + deltaPos.x, this->position.y + deltaPos.y};
|
||||
void setRotation(float rot) {
|
||||
this->rotation = rot;
|
||||
}
|
||||
|
||||
/** Returns the 4 corners of the texture */
|
||||
std::unordered_map<ECorner, Vector2> getCorners() {
|
||||
std::unordered_map<ECorner, Vector2> corners;
|
||||
float top = this->position.y;
|
||||
float right = this->position.x+this->size.x;
|
||||
float bottom = this->position.y + this->size.y;
|
||||
float left = this->position.x;
|
||||
float margin = 8; // Space to the corner
|
||||
corners[ECorner::TOP_LEFT] = {left+margin, top};
|
||||
corners[ECorner::TOP_RIGHT] = {right-margin, top};
|
||||
corners[ECorner::RIGHT_TOP] = {right, top+margin};
|
||||
corners[ECorner::RIGHT_BOTTOM] = {right, bottom-margin};
|
||||
corners[ECorner::BOTTOM_RIGHT] = {right-margin, bottom};
|
||||
corners[ECorner::BOTTOM_LEFT] = {left+margin, bottom};
|
||||
corners[ECorner::LEFT_BOTTOM] = {left, bottom-margin};
|
||||
corners[ECorner::LEFT_TOP] = {left, top+margin};
|
||||
|
||||
return corners;
|
||||
void move(Vector2 deltaPos) {
|
||||
this->position = {this->position.x + deltaPos.x, this->position.y + deltaPos.y};
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -70,6 +57,7 @@ class TextureWrapper {
|
||||
Rectangle sourceRect;
|
||||
Vector2 size;
|
||||
Vector2 position;
|
||||
float rotation;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef VECTOR2I_H
|
||||
#define VECTOR2I_H
|
||||
|
||||
class Vector2i {
|
||||
public:
|
||||
Vector2i(){}
|
||||
Vector2i (int x, int y) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef ESOUND_H
|
||||
#define ESOUND_H
|
||||
|
||||
enum class ESound {
|
||||
SHOOT,
|
||||
NO_AMMO,
|
||||
CRATE_BREAK,
|
||||
JELLY_FREED,
|
||||
HEAL_PICKUP,
|
||||
AMMO_PICKUP,
|
||||
POWERUP,
|
||||
PLAYER_DAMAGE,
|
||||
ENEMY_DEFEATED,
|
||||
VICTORY,
|
||||
PLAYER_SPOTTED
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -15,7 +15,9 @@ enum class ESprite {
|
||||
POWERUP,
|
||||
HUD_HEART,
|
||||
HUD_HEART_EMPTY,
|
||||
HUD_AMMO
|
||||
HUD_AMMO,
|
||||
CROSSHAIR,
|
||||
FLAG,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,8 @@ class Screen
|
||||
{
|
||||
public:
|
||||
Screen(){}
|
||||
~Screen() {}
|
||||
~Screen() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all logic for this frame
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef VICTORY_SCREEN_H
|
||||
#define VICTORY_SCREEN_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "screens/Screen.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "entities/Text.h"
|
||||
#include "entities/Background.h"
|
||||
#include <vector>
|
||||
|
||||
class VictoryScreen : public Screen
|
||||
{
|
||||
|
||||
public:
|
||||
VictoryScreen();
|
||||
~VictoryScreen() {
|
||||
}
|
||||
void logic() override;
|
||||
void draw() override;
|
||||
|
||||
private:
|
||||
std::vector<Text> text;
|
||||
std::vector<TextureWrapper> textures;
|
||||
std::vector<Text> buttons;
|
||||
int hoveredButton = 0;
|
||||
Background background;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "enums/EBackground.h"
|
||||
#include "enums/EMap.h"
|
||||
#include "enums/ESprite.h"
|
||||
#include "enums/ESound.h"
|
||||
#include "services/Service.h"
|
||||
|
||||
class AssetService: public Service<AssetService>
|
||||
@@ -32,6 +33,10 @@ public:
|
||||
return this->sprites[sprite];
|
||||
}
|
||||
|
||||
void playSound(ESound sound) {
|
||||
PlaySound(sounds[sound]);
|
||||
}
|
||||
|
||||
protected:
|
||||
AssetService();
|
||||
|
||||
@@ -41,7 +46,7 @@ private:
|
||||
|
||||
std::string assetDir;
|
||||
std::unordered_map<EFont, std::string> fonts;
|
||||
std::vector<Sound> sounds;
|
||||
std::unordered_map<ESound, Sound> sounds;
|
||||
std::unordered_map<EMusic, Music> music;
|
||||
std::unordered_map<EBackground, Texture2D> backgrounds;
|
||||
std::unordered_map<EMap, std::string> maps;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef BULLET_SERVICE_H
|
||||
#define BULLET_SERVICE_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/Service.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/Bullet.h"
|
||||
#include "entities/PBullet.h"
|
||||
#include "entities/EBullet.h"
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
|
||||
class BulletService : public Service<BulletService>
|
||||
{
|
||||
public:
|
||||
void initBullets()
|
||||
{
|
||||
this->bullets.clear();
|
||||
}
|
||||
|
||||
void bulletLogic()
|
||||
{
|
||||
for (auto it = this->bullets.begin(); it != this->bullets.end();)
|
||||
{
|
||||
(*it)->logic();
|
||||
if ((*it)->getHasCollided())
|
||||
it = this->bullets.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void drawBullets()
|
||||
{
|
||||
for (auto it = this->bullets.begin(); it != this->bullets.end();)
|
||||
{
|
||||
(*it)->draw();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void addPlayerBullet(Vector2 position, float direction)
|
||||
{
|
||||
this->bullets.push_back(std::make_unique<PBullet>(position, direction));
|
||||
}
|
||||
|
||||
void addEnemyBullet(Vector2 position, float direction)
|
||||
{
|
||||
this->bullets.push_back(std::make_unique<EBullet>(position, direction));
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::vector<std::unique_ptr<Bullet>> bullets;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef COLLECTABLE_SERVICE_H
|
||||
#define COLLECTABLE_SERVICE_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/Service.h"
|
||||
#include "entities/Vector2i.h"
|
||||
#include "entities/Crate.h"
|
||||
#include "entities/Jelly.h"
|
||||
#include "entities/AmmoPack.h"
|
||||
#include "entities/HealthPack.h"
|
||||
#include "entities/Powerup.h"
|
||||
#include "entities/Flag.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Service that manages the collectables (jellies), consumables (Ammo, health, powerups), and the finish flag
|
||||
*/
|
||||
class CollectableService : public Service<CollectableService>
|
||||
{
|
||||
public:
|
||||
void initCollectables()
|
||||
{
|
||||
initCrates();
|
||||
initJellies();
|
||||
initAmmoPacks();
|
||||
initHealthPacks();
|
||||
initPowerups();
|
||||
initFlag();
|
||||
}
|
||||
|
||||
void collectableLogic()
|
||||
{
|
||||
crateLogic();
|
||||
jellyLogic();
|
||||
ammoPackLogic();
|
||||
healthPackLogic();
|
||||
powerupLogic();
|
||||
flag.logic();
|
||||
}
|
||||
|
||||
void drawCollectables()
|
||||
{
|
||||
drawCrates();
|
||||
drawJellies();
|
||||
drawAmmoPacks();
|
||||
drawHealthpacks();
|
||||
drawPowerups();
|
||||
flag.draw();
|
||||
}
|
||||
|
||||
std::vector<Crate> &getCrates()
|
||||
{
|
||||
return this->crates;
|
||||
}
|
||||
|
||||
std::vector<AmmoPack> &getAmmoPacks()
|
||||
{
|
||||
return this->ammoPacks;
|
||||
}
|
||||
|
||||
std::vector<HealthPack> &getHealthPacks()
|
||||
{
|
||||
return this->healthPacks;
|
||||
}
|
||||
|
||||
std::vector<Powerup> &getPowerups() {
|
||||
return this->powerUps;
|
||||
}
|
||||
|
||||
Flag& getFlag() {
|
||||
return this->flag;
|
||||
}
|
||||
|
||||
int getMaxAmountOfJellies()
|
||||
{
|
||||
return this->amountOfCrates;
|
||||
}
|
||||
|
||||
int getAmountOfJelliesFreed()
|
||||
{
|
||||
return this->jellies.size();
|
||||
}
|
||||
|
||||
private:
|
||||
int amountOfCrates = 3;
|
||||
int amountOfAmmoPacks = 4;
|
||||
int amountOfHealthPacks = 4;
|
||||
int amountOfPowerups = 1;
|
||||
std::vector<Crate> crates;
|
||||
std::vector<AmmoPack> ammoPacks;
|
||||
std::vector<HealthPack> healthPacks;
|
||||
std::vector<Jelly> jellies;
|
||||
std::vector<Powerup> powerUps;
|
||||
Flag flag;
|
||||
|
||||
void initCrates();
|
||||
void initJellies();
|
||||
void initAmmoPacks();
|
||||
void initHealthPacks();
|
||||
void initPowerups();
|
||||
void initFlag();
|
||||
void crateLogic();
|
||||
void jellyLogic();
|
||||
void ammoPackLogic();
|
||||
void healthPackLogic();
|
||||
void powerupLogic();
|
||||
void drawCrates();
|
||||
void drawJellies();
|
||||
void drawAmmoPacks();
|
||||
void drawHealthpacks();
|
||||
void drawPowerups();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef ENEMY_SERVICE_H
|
||||
#define ENEMY_SERVICE_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/Service.h"
|
||||
#include "entities/Enemy.h"
|
||||
#include <optional>
|
||||
|
||||
class EnemyService : public Service<EnemyService>
|
||||
{
|
||||
public:
|
||||
void initEnemies();
|
||||
void enemyLogic();
|
||||
void drawEnemies();
|
||||
std::vector<Enemy> &getEnemies();
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::vector<Enemy> enemies;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef GAME_SERVICE_H
|
||||
#define GAME_SERVICE_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/Service.h"
|
||||
#include "services/AudioService.h"
|
||||
#include "services/InputService.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
class GameService : public Service<GameService>
|
||||
{
|
||||
public:
|
||||
bool isPaused()
|
||||
{
|
||||
return this->paused;
|
||||
}
|
||||
|
||||
bool isGameOver()
|
||||
{
|
||||
return this->gameOver;
|
||||
}
|
||||
|
||||
void setPaused(bool paused)
|
||||
{
|
||||
this->paused = paused;
|
||||
if (this->paused)
|
||||
AudioService::getInstance().pauseMusic();
|
||||
}
|
||||
|
||||
void setGameOver(bool gameOver)
|
||||
{
|
||||
this->gameOver = gameOver;
|
||||
if (this->gameOver)
|
||||
{
|
||||
AudioService::getInstance().setMusic(EMusic::GAME_OVER);
|
||||
AudioService::getInstance().playMusic();
|
||||
}
|
||||
}
|
||||
|
||||
void setCamera(Camera2D camera)
|
||||
{
|
||||
this->camera = camera;
|
||||
}
|
||||
|
||||
Camera2D &getCamera()
|
||||
{
|
||||
return this->camera;
|
||||
}
|
||||
|
||||
Vector2 getMouseWorldPos()
|
||||
{
|
||||
Vector2 mouseWorldPos = {InputService::getInstance().getMousePos().x + camera.target.x - camera.offset.x,
|
||||
InputService::getInstance().getMousePos().y};
|
||||
return mouseWorldPos;
|
||||
}
|
||||
|
||||
Vector2 toWorldPos(Vector2i pixelPos)
|
||||
{
|
||||
Vector2 worldPos = {(float)pixelPos.x + camera.target.x - camera.offset.x, (float)pixelPos.y};
|
||||
return worldPos;
|
||||
}
|
||||
|
||||
void resetGame()
|
||||
{
|
||||
paused = false;
|
||||
gameOver = false;
|
||||
// playerBullets.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
bool paused = false;
|
||||
bool gameOver = false;
|
||||
Camera2D camera;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef INPUT_SERVICE_H
|
||||
#define INPUT_SERVICE_H
|
||||
|
||||
#include "Service.h"
|
||||
#include "raylib.h"
|
||||
#include "Service.h"
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
@@ -57,13 +57,26 @@ public:
|
||||
for (auto button : watchedMouseButtons)
|
||||
{
|
||||
mouseButtonsPressed[button] = false;
|
||||
mouseButtonsDown[button] = false;
|
||||
if (IsMouseButtonPressed(button))
|
||||
{
|
||||
mouseButtonsPressed[button] = true;
|
||||
}
|
||||
if (IsMouseButtonDown(button))
|
||||
{
|
||||
mouseButtonsDown[button] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkMousePos() {
|
||||
this->mousePosition = GetMousePosition();
|
||||
}
|
||||
|
||||
Vector2 getMousePos() {
|
||||
return this->mousePosition;
|
||||
}
|
||||
|
||||
bool isKeyPressed(KeyboardKey key)
|
||||
{
|
||||
return keysPressed[key];
|
||||
@@ -78,22 +91,30 @@ public:
|
||||
return mouseButtonsPressed[button];
|
||||
}
|
||||
|
||||
bool isMouseButtonDown(MouseButton button) {
|
||||
return mouseButtonsDown[button];
|
||||
}
|
||||
|
||||
private:
|
||||
Vector2 mousePosition {0,0};
|
||||
std::unordered_set<KeyboardKey> watchedKeys;
|
||||
std::unordered_map<KeyboardKey, bool> keysPressed;
|
||||
std::unordered_map<KeyboardKey, bool> keysDown;
|
||||
std::unordered_set<MouseButton> watchedMouseButtons;
|
||||
std::unordered_map<MouseButton, bool> mouseButtonsPressed;
|
||||
std::unordered_map<MouseButton, bool> mouseButtonsDown;
|
||||
|
||||
void setMouseButtonsToWatch(std::vector<MouseButton> mouseButtonsToWatch)
|
||||
{
|
||||
this->watchedMouseButtons.clear();
|
||||
this->mouseButtonsPressed.clear();
|
||||
this->mouseButtonsDown.clear();
|
||||
|
||||
for (int i = 0; i < mouseButtonsToWatch.size(); i++)
|
||||
{
|
||||
this->watchedMouseButtons.insert(mouseButtonsToWatch[i]);
|
||||
this->mouseButtonsPressed[mouseButtonsToWatch[i]] = false;
|
||||
this->mouseButtonsDown[mouseButtonsToWatch[i]] = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef PLAYER_SERVICE_H
|
||||
#define PLAYER_SERVICE_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/Service.h"
|
||||
#include "entities/Player.h"
|
||||
#include <memory>
|
||||
|
||||
class PlayerService : public Service<PlayerService>
|
||||
{
|
||||
public:
|
||||
void initPlayer()
|
||||
{
|
||||
this->player = std::make_unique<Player>();
|
||||
this->player->setPosition({200, 350});
|
||||
}
|
||||
|
||||
Player& getPlayer() {
|
||||
return *this->player;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::unique_ptr<Player> player;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,16 +1,17 @@
|
||||
#ifndef STATE_SERVICE_H
|
||||
#define STATE_SERVICE_H
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include "services/Service.h"
|
||||
#include "screens/Screen.h"
|
||||
#include "enums/EScreen.h"
|
||||
#include "raylib.h"
|
||||
#include "enums/EScreen.h"
|
||||
#include "services/Service.h"
|
||||
#include "services/InputService.h"
|
||||
#include "screens/Screen.h"
|
||||
#include <memory>
|
||||
|
||||
#if defined(PLATFORM_WEB)
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
// #include <emscripten/html5.h>
|
||||
|
||||
/**
|
||||
* Handles switching between screens
|
||||
@@ -32,30 +33,23 @@ public:
|
||||
* Start the game loop
|
||||
*/
|
||||
void startGame();
|
||||
|
||||
static void staticStep()
|
||||
{
|
||||
if (IsKeyPressed(KEY_ENTER) || IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
std::cout << "Input!" << std::endl;
|
||||
}
|
||||
// Access the singleton instance and call step
|
||||
getInstance().step();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Screen> currentScreen;
|
||||
|
||||
bool gameRunning = true;
|
||||
|
||||
Vector2 screenSize;
|
||||
|
||||
/**
|
||||
* One step of the gameloop
|
||||
*/
|
||||
void step();
|
||||
|
||||
void handleMusic();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/bin/bash
|
||||
clear
|
||||
# g++ src/main.cpp -o dist/jelly_rescue -L$LD_LIBRARY_PATH -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
g++ $(find src/ -name "*.cpp") -o dist/jelly_rescue -I./include -L$LD_LIBRARY_PATH -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
# g++ -std=c++20 $(find src/ -name "*.cpp") -o dist/jelly_rescue -I./include -L$LD_LIBRARY_PATH -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
g++ -std=c++20 -g -O0 $(find src/ -name "*.cpp") -o dist/jelly_rescue -I./include -L$LD_LIBRARY_PATH -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
|
||||
# g++ src/main.cpp -o dist/jelly_rescue -L$LD_LIBRARY_PATH -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
./dist/jelly_rescue
|
||||
gdb dist/jelly_rescue
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# emcc src/main.cpp -o dist/game.js -Wno-missing-braces -I/app/libs/raylib/build/raylib/include -L/app/libs/raylib/src /app/libs/raylib/src/libraylib.a -s USE_GLFW=3 -DPLATFORM_WEB
|
||||
|
||||
|
||||
emcc $(find src/ -name "*.cpp") -o dist/game.js -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=268435456 -s MAXIMUM_MEMORY=4294967296 -s --preload-file assets@/assets -s USE_GLFW=3 -DPLATFORM_WEB
|
||||
# emcc $(find src/ -name "*.cpp") -o dist/game.js -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=268435456 -s MAXIMUM_MEMORY=4294967296 -s --preload-file assets@/assets -s USE_GLFW=3 -DPLATFORM_WEB
|
||||
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
|
||||
# -I./include
|
||||
# -L$LD_LIBRARY_PATH
|
||||
# -I.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "entities/Bullet.h"
|
||||
#include "services/MapService.h"
|
||||
|
||||
void Bullet::envCollision()
|
||||
{
|
||||
if (position.x < 0 || position.y < 0 || position.y > GetScreenHeight())
|
||||
{
|
||||
hasCollided = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
Vector2i tilePos = Vector2i((int)this->position.x / tileSize, (int)this->position.y / tileSize);
|
||||
if (MapService::getInstance().getMap().getColMap()[tilePos.y][tilePos.x] == 1)
|
||||
{
|
||||
hasCollided = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "entities/EBullet.h"
|
||||
#include "services/PlayerService.h"
|
||||
|
||||
void EBullet::objCollision()
|
||||
{
|
||||
Player& player = PlayerService::getInstance().getPlayer();
|
||||
|
||||
/** If the player is already falling of the map, dont allow bullets to hit it anymore */
|
||||
if(player.getHealth() == 0)
|
||||
return;
|
||||
|
||||
if(this->position.x + this->size > player.getTexture().getPosition().x && this->position.x-this->size < player.getTexture().getPosition().x + player.getTexture().getSize().x &&
|
||||
this->position.y + this->size > player.getTexture().getPosition().y && this->position.y-this->size < player.getTexture().getPosition().y + player.getTexture().getSize().y) {
|
||||
player.takeDamage(this->damage);
|
||||
AssetService::getInstance().playSound(ESound::PLAYER_DAMAGE);
|
||||
this->hasCollided = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "entities/Enemy.h"
|
||||
#include "services/PlayerService.h"
|
||||
#include "services/MapService.h"
|
||||
#include "services/BulletService.h"
|
||||
#include <cmath>
|
||||
|
||||
void Enemy::logic()
|
||||
{
|
||||
if (health == 0)
|
||||
{
|
||||
fall();
|
||||
}
|
||||
else
|
||||
{
|
||||
detectPlayer();
|
||||
if (playerSpotted)
|
||||
{
|
||||
shoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
walk();
|
||||
checkForCollision();
|
||||
animate();
|
||||
}
|
||||
}
|
||||
texture.move(velocity);
|
||||
}
|
||||
|
||||
void Enemy::walk()
|
||||
{
|
||||
if (spriteAnimation.y == Left)
|
||||
{
|
||||
velocity.x = -moveSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.x = moveSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::checkForCollision()
|
||||
{
|
||||
std::vector corners = getCorners();
|
||||
std::vector<std::vector<int>> colMap = MapService::getInstance().getMap().getColMap();
|
||||
hasCollided = false;
|
||||
|
||||
if (colMap[corners[2].y][corners[2].x] == 0 || colMap[corners[3].y][corners[3].x] == 0) // No ground below enemy
|
||||
{
|
||||
hasCollided = true;
|
||||
}
|
||||
else if (colMap[corners[0].y][corners[0].x] == 1 || colMap[corners[1].y][corners[1].x] == 1)
|
||||
{
|
||||
hasCollided = true;
|
||||
}
|
||||
|
||||
if (hasCollided)
|
||||
{
|
||||
if (spriteAnimation.y == Left)
|
||||
spriteAnimation.y = Right;
|
||||
else
|
||||
spriteAnimation.y = Left;
|
||||
|
||||
velocity.x *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vector2i> Enemy::getCorners()
|
||||
{
|
||||
float bottom = texture.getPosition().y + texture.getSize().y + velocity.y;
|
||||
float left = texture.getPosition().x + velocity.x;
|
||||
float right = texture.getPosition().x + texture.getSize().x + velocity.x;
|
||||
float top = texture.getPosition().y + velocity.y;
|
||||
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
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));
|
||||
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(bottomLeft);
|
||||
corners.push_back(bottomRight);
|
||||
return corners;
|
||||
}
|
||||
|
||||
void Enemy::animate()
|
||||
{
|
||||
if (GetTime() - prevFrame > animationDelay || hasCollided)
|
||||
{
|
||||
spriteAnimation.x = std::fmod(spriteAnimation.x + 1, 3);
|
||||
|
||||
Rectangle sourceRect = this->texture.getSourceRect();
|
||||
sourceRect.x = spriteAnimation.x * this->texture.getSize().x;
|
||||
sourceRect.y = spriteAnimation.y * this->texture.getSize().y;
|
||||
this->texture.setSourceRect(sourceRect);
|
||||
prevFrame = GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::drawHealthBar()
|
||||
{
|
||||
float barLength = (this->texture.getSize().x / maxHealth) * health;
|
||||
DrawRectangle(this->texture.getPosition().x, this->texture.getPosition().y - 12.0f, barLength, 3, RED);
|
||||
}
|
||||
|
||||
void Enemy::drawGun()
|
||||
{
|
||||
if (this->spriteAnimation.y == Right)
|
||||
{
|
||||
DrawTexturePro(
|
||||
this->gunRight.getTexture(),
|
||||
{0, 0, this->gunRight.getSize().x, this->gunRight.getSize().y},
|
||||
{this->texture.getPosition().x + this->texture.getSize().x / 2.0f,
|
||||
this->texture.getPosition().y + this->texture.getSize().y / 2.0f,
|
||||
this->gunRight.getSize().x,
|
||||
this->gunRight.getSize().y},
|
||||
{this->gunRight.getSize().x / 3.0f, this->gunRight.getSize().y / 2.0f},
|
||||
this->gunRight.getRotation(),
|
||||
WHITE);
|
||||
}
|
||||
else if (this->spriteAnimation.y == Left)
|
||||
{
|
||||
DrawTexturePro(
|
||||
this->gunLeft.getTexture(),
|
||||
{0, 0, this->gunLeft.getSize().x, this->gunLeft.getSize().y},
|
||||
{this->texture.getPosition().x + this->texture.getSize().x / 2.0f,
|
||||
this->texture.getPosition().y + this->texture.getSize().y / 2.0f,
|
||||
this->gunLeft.getSize().x,
|
||||
this->gunLeft.getSize().y},
|
||||
{this->gunLeft.getSize().x - this->gunLeft.getSize().x / 3.0f, this->gunLeft.getSize().y / 2.0f},
|
||||
this->gunLeft.getRotation(),
|
||||
WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::fall()
|
||||
{
|
||||
velocity.y += gravity;
|
||||
}
|
||||
|
||||
void Enemy::detectPlayer()
|
||||
{
|
||||
Player &player = PlayerService::getInstance().getPlayer();
|
||||
if (this->health > 0)
|
||||
{
|
||||
bool spotted = false;
|
||||
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 (this->spriteAnimation.y == Left && this->texture.getPosition().x - player.getTexture().getPosition().x <= spottingRange &&
|
||||
this->texture.getPosition().x - player.getTexture().getPosition().x > 55 && this->texture.getPosition().y + this->texture.getSize().y >= player.getTexture().getPosition().y)
|
||||
{
|
||||
spotted = true;
|
||||
float gunRotationLeft = atan2(playerCenter.y - enemyCenter.y,
|
||||
enemyCenter.x - playerCenter.x);
|
||||
float target = -gunRotationLeft * 180 / M_PI;
|
||||
this->gunLeft.setRotation(std::min(this->gunLeft.getRotation() + aimSpeed, target));
|
||||
}
|
||||
else if (spriteAnimation.y == Right && player.getTexture().getPosition().x - this->texture.getPosition().x <= spottingRange &&
|
||||
player.getTexture().getPosition().x - this->texture.getPosition().x > 55 && this->texture.getPosition().y + this->texture.getSize().y >= player.getTexture().getPosition().y)
|
||||
{
|
||||
spotted = true;
|
||||
float gunRotationRight = atan2(playerCenter.y - enemyCenter.y,
|
||||
playerCenter.x - enemyCenter.x);
|
||||
float target = gunRotationRight * 180 / M_PI;
|
||||
this->gunRight.setRotation(std::max(this->gunRight.getRotation() - aimSpeed, target));
|
||||
}
|
||||
|
||||
/** Don't set it again if the detection continues */
|
||||
if (spotted && !this->playerSpotted)
|
||||
{
|
||||
AssetService::getInstance().playSound(ESound::PLAYER_SPOTTED);
|
||||
this->playerSpotted = true;
|
||||
velocity.x = 0.0f;
|
||||
}
|
||||
else if (!spotted)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::shoot()
|
||||
{
|
||||
Player &player = PlayerService::getInstance().getPlayer();
|
||||
/** Stop shooting if the player is dead (and falling out of the map) */
|
||||
if (player.getHealth() > 0 && playerSpotted && GetTime() - this->lastShot >= (1 / this->shotsPerSecond))
|
||||
{
|
||||
|
||||
this->lastShot = GetTime();
|
||||
// Play shooting sound
|
||||
AssetService::getInstance().playSound(ESound::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};
|
||||
|
||||
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};
|
||||
|
||||
BulletService::getInstance().addEnemyBullet(bulletStartLocation, angleShot);
|
||||
}
|
||||
}
|
||||
+1
-48
@@ -1,10 +1,8 @@
|
||||
#include "entities/Map.h"
|
||||
#include "services/AssetService.h"
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/Map.h"
|
||||
|
||||
Map::Map()
|
||||
{
|
||||
@@ -114,19 +112,6 @@ void Map::loadTileset()
|
||||
this->tileset = AssetService::getInstance().loadTexture("Textures/tileset.png");
|
||||
}
|
||||
|
||||
std::unordered_map<ECorner, Vector2> Map::cornersToTilePos(std::unordered_map<ECorner, Vector2> corners)
|
||||
{
|
||||
// std::cout << "Starting converting" << std::endl;
|
||||
std::unordered_map<ECorner, Vector2> cornersTilePos;
|
||||
for (const auto &pair : corners)
|
||||
{
|
||||
// std::cout << "Foreach pair" << std::endl;
|
||||
Vector2 original = corners[pair.first];
|
||||
cornersTilePos[pair.first] = {floorf(original.x / this->tileSize), floorf(original.y / this->tileSize)};
|
||||
}
|
||||
return cornersTilePos;
|
||||
}
|
||||
|
||||
void Map::draw()
|
||||
{
|
||||
for (int i = 0; i < map.size(); i++)
|
||||
@@ -146,35 +131,3 @@ void Map::draw()
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<ECorner, bool> Map::checkForCollision(TextureWrapper texture)
|
||||
{
|
||||
// std::cout << "Converting.." << std::endl;
|
||||
std::unordered_map<ECorner, Vector2> cornersTilePos = cornersToTilePos(texture.getCorners());
|
||||
// std::cout << "Done with converting" << std::endl;
|
||||
|
||||
std::unordered_map<ECorner, bool> cornerCollisions;
|
||||
|
||||
for (const auto &pair : cornersTilePos)
|
||||
{
|
||||
// std::cout << "foreach collision check" << std::endl;
|
||||
Vector2 pos = cornersTilePos[pair.first];
|
||||
// std::cout << pos.x << " " << pos.y << std::endl;
|
||||
if(colMap[pos.y][pos.x] == 1) {
|
||||
cornerCollisions[pair.first] = true;
|
||||
} else {
|
||||
cornerCollisions[pair.first] = false;
|
||||
}
|
||||
}
|
||||
// std::cout << "Finished collision checks" << std::endl;
|
||||
|
||||
return cornerCollisions;
|
||||
|
||||
// for (int i = 0; i < tiles.size(); i++)
|
||||
// {
|
||||
// if (colMap[tiles[i].y][tiles[i].x] == 1)
|
||||
// {
|
||||
// timesCollision.push_back(i);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "entities/PBullet.h"
|
||||
#include "services/CollectableService.h"
|
||||
#include "services/EnemyService.h"
|
||||
|
||||
void PBullet::objCollision()
|
||||
{
|
||||
/** Check for collisions with creates */
|
||||
for (auto &crate : CollectableService::getInstance().getCrates())
|
||||
{
|
||||
if(this->position.x + this->size > crate.getObject().getPosition().x && this->position.x-this->size < crate.getObject().getPosition().x + crate.getObject().getSize().x &&
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &enemy : EnemyService::getInstance().getEnemies())
|
||||
{
|
||||
/** If the enemy is already falling of the map, dont allow bullets to hit it anymore */
|
||||
if(enemy.getHealth() == 0)
|
||||
continue;
|
||||
|
||||
if(this->position.x + this->size > enemy.getObject().getPosition().x && this->position.x-this->size < enemy.getObject().getPosition().x + enemy.getObject().getSize().x &&
|
||||
this->position.y + this->size > enemy.getObject().getPosition().y && this->position.y-this->size < enemy.getObject().getPosition().y + enemy.getObject().getSize().y) {
|
||||
enemy.takeDamage();
|
||||
if(enemy.getHealth() == 0) {
|
||||
AssetService::getInstance().playSound(ESound::ENEMY_DEFEATED);
|
||||
}
|
||||
this->hasCollided = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
#include "entities/Player.h"
|
||||
#include "services/BulletService.h"
|
||||
#include "services/GameService.h"
|
||||
#include "services/CollectableService.h"
|
||||
#include "services/InputService.h"
|
||||
#include "services/MapService.h"
|
||||
|
||||
void Player::applyGravity()
|
||||
{
|
||||
if (!groundCollision)
|
||||
{
|
||||
velocity.y += gravity;
|
||||
}
|
||||
else
|
||||
{
|
||||
// velocity.y = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::movement()
|
||||
{
|
||||
if (InputService::getInstance().isKeyDown(KEY_A))
|
||||
{
|
||||
spriteAnimation.y = Left;
|
||||
velocity.x = -moveSpeed;
|
||||
animate();
|
||||
}
|
||||
else if (InputService::getInstance().isKeyDown(KEY_D))
|
||||
{
|
||||
spriteAnimation.y = Right;
|
||||
velocity.x = moveSpeed;
|
||||
animate();
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.x = 0.0f;
|
||||
}
|
||||
positionUpdates();
|
||||
handleCollision();
|
||||
|
||||
if (!groundCollision)
|
||||
{
|
||||
velocity.y += gravity;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.y = 0.0f;
|
||||
}
|
||||
|
||||
if (InputService::getInstance().isKeyPressed(KEY_W) && groundCollision)
|
||||
{
|
||||
velocity.y -= jumpPower;
|
||||
}
|
||||
move(velocity);
|
||||
}
|
||||
|
||||
void Player::move(Vector2 velocity)
|
||||
{
|
||||
this->texture.move(velocity);
|
||||
}
|
||||
|
||||
void Player::animate()
|
||||
{
|
||||
if (GetTime() - prevFrame > animationDelay)
|
||||
{
|
||||
spriteAnimation.x = std::fmod(spriteAnimation.x + 1, 3);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void Player::positionUpdates()
|
||||
{
|
||||
const Vector2 pos = this->texture.getPosition();
|
||||
const Vector2 size = this->texture.getSize();
|
||||
const int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
|
||||
const float bottom = pos.y + size.y + velocity.y;
|
||||
const float left = pos.x + velocity.x;
|
||||
const float right = pos.x + size.x + velocity.x;
|
||||
const float top = pos.y + velocity.y;
|
||||
|
||||
Vector2i topLeft(Vector2i((int)(left + 5) / tileSize, (int)top / tileSize)); // +5 to separate top from side
|
||||
Vector2i topRight(Vector2i((int)(right - 5) / tileSize, (int)top / tileSize)); // -5 to separate top from side
|
||||
|
||||
Vector2i leftTop(Vector2i((int)left / tileSize, (int)(top + 5) / tileSize));
|
||||
Vector2i leftBottom(Vector2i((int)left / tileSize, (int)(bottom - 5) / tileSize));
|
||||
Vector2i rightTop(Vector2i((int)right / tileSize, (int)(top + 5) / tileSize));
|
||||
Vector2i rightBottom(Vector2i((int)right / tileSize, (int)(bottom - 5) / 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
|
||||
|
||||
tiles.clear();
|
||||
|
||||
tiles.push_back(topLeft);
|
||||
tiles.push_back(topRight);
|
||||
|
||||
tiles.push_back(leftTop);
|
||||
tiles.push_back(leftBottom);
|
||||
tiles.push_back(rightTop);
|
||||
tiles.push_back(rightBottom);
|
||||
|
||||
tiles.push_back(bottomLeft);
|
||||
tiles.push_back(bottomRight);
|
||||
}
|
||||
|
||||
void Player::handleCollision()
|
||||
{
|
||||
|
||||
timesCollision.clear();
|
||||
|
||||
for (int i = 0; i < tiles.size(); i++)
|
||||
{
|
||||
if (MapService::getInstance().getMap().getColMap()[tiles[i].y][tiles[i].x] == 1)
|
||||
{
|
||||
timesCollision.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
groundCollision = false;
|
||||
|
||||
if (timesCollision.size() > 0)
|
||||
{
|
||||
for (int i = 0; i < timesCollision.size(); i++)
|
||||
{
|
||||
if (timesCollision[i] == 0 || timesCollision[i] == 1) // Topleft and Topright
|
||||
{
|
||||
velocity.y = 0;
|
||||
}
|
||||
else if (timesCollision[i] == 2 || timesCollision[i] == 3 || // Lefttop and Leftbottom
|
||||
timesCollision[i] == 4 || timesCollision[i] == 5) // Righttop and Lefttop
|
||||
{
|
||||
velocity.x = 0;
|
||||
}
|
||||
else if (timesCollision[i] == 6 || timesCollision[i] == 7) // Bottomleft and Bottomright
|
||||
{
|
||||
groundCollision = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::consumableCollision()
|
||||
{
|
||||
/** Check for collisions with ammo packs */
|
||||
for (auto &ammoPack : CollectableService::getInstance().getAmmoPacks())
|
||||
{
|
||||
if (this->texture.getPosition().x + this->texture.getSize().x > ammoPack.getObject().getPosition().x &&
|
||||
this->texture.getPosition().x<ammoPack.getObject().getPosition().x + ammoPack.getObject().getSize().x &&this->texture.getPosition().y + this->texture.getSize().y> ammoPack.getObject().getPosition().y &&
|
||||
this->texture.getPosition().y < ammoPack.getObject().getPosition().y + ammoPack.getObject().getSize().y)
|
||||
{
|
||||
ammoPack.setPickedUp(true);
|
||||
AssetService::getInstance().playSound(ESound::AMMO_PICKUP);
|
||||
ammo += ammoPack.getAmmoAmount();
|
||||
}
|
||||
}
|
||||
|
||||
/** Check for collisions with health packs */
|
||||
for (auto &healthPack : CollectableService::getInstance().getHealthPacks())
|
||||
{
|
||||
if (this->texture.getPosition().x + this->texture.getSize().x > healthPack.getObject().getPosition().x &&
|
||||
this->texture.getPosition().x<healthPack.getObject().getPosition().x + healthPack.getObject().getSize().x &&this->texture.getPosition().y + this->texture.getSize().y> healthPack.getObject().getPosition().y &&
|
||||
this->texture.getPosition().y < healthPack.getObject().getPosition().y + healthPack.getObject().getSize().y)
|
||||
{
|
||||
if (health < max_health)
|
||||
{
|
||||
healthPack.setPickedUp(true);
|
||||
AssetService::getInstance().playSound(ESound::HEAL_PICKUP);
|
||||
health = std::min(health + healthPack.getHealAmount(), (int)max_health);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks for collisions with powerups */
|
||||
for (auto &powerup : CollectableService::getInstance().getPowerups())
|
||||
{
|
||||
if (this->texture.getPosition().x + this->texture.getSize().x > powerup.getObject().getPosition().x &&
|
||||
this->texture.getPosition().x<powerup.getObject().getPosition().x + powerup.getObject().getSize().x &&this->texture.getPosition().y + this->texture.getSize().y> powerup.getObject().getPosition().y &&
|
||||
this->texture.getPosition().y < powerup.getObject().getPosition().y + powerup.getObject().getSize().y)
|
||||
{
|
||||
// if(health < max_health) {
|
||||
powerup.setPickedUp(true);
|
||||
AssetService::getInstance().playSound(ESound::POWERUP);
|
||||
jumpPower += powerup.getExtraJumpPower();
|
||||
gainedPowerup = true;
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks for collisions with the finish flag */
|
||||
auto &flag = CollectableService::getInstance().getFlag();
|
||||
if (this->texture.getPosition().x + this->texture.getSize().x > flag.getObject().getPosition().x &&
|
||||
this->texture.getPosition().x<flag.getObject().getPosition().x + flag.getObject().getSize().x &&this->texture.getPosition().y + this->texture.getSize().y> flag.getObject().getPosition().y &&
|
||||
this->texture.getPosition().y < flag.getObject().getPosition().y + flag.getObject().getSize().y)
|
||||
{
|
||||
flag.setTouched(true);
|
||||
finishReached = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::shoot()
|
||||
{
|
||||
if (InputService::getInstance().isMouseButtonDown(MOUSE_BUTTON_LEFT) && GetTime() - prevShot > firingRate && groundCollision)
|
||||
{
|
||||
prevShot = GetTime();
|
||||
if (this->ammo == 0 || (GameService::getInstance().getMouseWorldPos().x > (this->texture.getPosition().x - this->gunLeft.getSize().x / 2.0f) && spriteAnimation.y == Left) ||
|
||||
(GameService::getInstance().getMouseWorldPos().x < (this->texture.getPosition().x + this->texture.getSize().x + gunLeft.getSize().x / 2.0f) && spriteAnimation.y == Right))
|
||||
{
|
||||
// Play empty gun sound
|
||||
AssetService::getInstance().playSound(ESound::NO_AMMO);
|
||||
return;
|
||||
}
|
||||
// Play shooting sound
|
||||
AssetService::getInstance().playSound(ESound::SHOOT);
|
||||
ammo--;
|
||||
|
||||
Vector2 mouseWorldPos = GameService::getInstance().getMouseWorldPos();
|
||||
|
||||
if (mouseWorldPos.x > this->texture.getPosition().x + (this->gunLeft.getSize().x) && spriteAnimation.y == Right ||
|
||||
mouseWorldPos.x + (this->gunLeft.getSize().x / 2) < this->texture.getPosition().x && spriteAnimation.y == Left)
|
||||
{
|
||||
|
||||
float angleShot = atan2(mouseWorldPos.y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0),
|
||||
mouseWorldPos.x - (this->texture.getPosition().x + this->texture.getSize().x / 2.0));
|
||||
|
||||
/** Making the bullet originate from the gun's mouth */
|
||||
float offsetDistance = this->gunLeft.getSize().x / 2;
|
||||
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().addPlayerBullet(bulletStartLocation, angleShot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::outofboundsCheck()
|
||||
{
|
||||
if (this->texture.getPosition().y > StateService::getInstance().getScreenSize().y)
|
||||
{
|
||||
this->health = 0;
|
||||
GameService::getInstance().setGameOver(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::rotateGun()
|
||||
{
|
||||
if (GameService::getInstance().getMouseWorldPos().x > this->texture.getPosition().x + (this->gunLeft.getSize().x) && spriteAnimation.y == Right)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if (GameService::getInstance().getMouseWorldPos().x + (this->gunLeft.getSize().x / 2) < this->texture.getPosition().x && spriteAnimation.y == Left)
|
||||
{
|
||||
float gunRotationLeft = atan2(GameService::getInstance().getMouseWorldPos().y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0),
|
||||
(this->texture.getPosition().x + this->texture.getSize().x / 2.0) - GameService::getInstance().getMouseWorldPos().x);
|
||||
this->gunLeft.setRotation(-gunRotationLeft * 180 / M_PI);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::drawGun()
|
||||
{
|
||||
if (GameService::getInstance().getMouseWorldPos().x > this->texture.getPosition().x + this->gunLeft.getSize().x && spriteAnimation.y == Right)
|
||||
{
|
||||
// + this->texture.getSize().x / 2.0f
|
||||
// + this->texture.getSize().y / 2.0f
|
||||
DrawTexturePro(
|
||||
this->gunRight.getTexture(),
|
||||
{0, 0, this->gunRight.getSize().x, this->gunRight.getSize().y},
|
||||
{this->texture.getPosition().x + this->texture.getSize().x / 2.0f,
|
||||
this->texture.getPosition().y + this->texture.getSize().y / 2.0f,
|
||||
this->gunRight.getSize().x,
|
||||
this->gunRight.getSize().y},
|
||||
{this->gunRight.getSize().x / 2.0f, this->gunRight.getSize().y / 2.0f},
|
||||
this->gunRight.getRotation(),
|
||||
WHITE);
|
||||
}
|
||||
else if (GameService::getInstance().getMouseWorldPos().x + (this->gunLeft.getSize().x / 2) < this->texture.getPosition().x && spriteAnimation.y == Left)
|
||||
{
|
||||
DrawTexturePro(
|
||||
this->gunLeft.getTexture(),
|
||||
{0, 0, this->gunLeft.getSize().x, this->gunLeft.getSize().y},
|
||||
{this->texture.getPosition().x + this->texture.getSize().x / 2.0f,
|
||||
this->texture.getPosition().y + this->texture.getSize().y / 2.0f,
|
||||
this->gunLeft.getSize().x,
|
||||
this->gunLeft.getSize().y},
|
||||
{this->gunLeft.getSize().x / 2.0f, this->gunLeft.getSize().y / 2.0f},
|
||||
this->gunLeft.getRotation(),
|
||||
WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::fall()
|
||||
{
|
||||
outofboundsCheck();
|
||||
velocity.y += gravity;
|
||||
move(velocity);
|
||||
}
|
||||
@@ -1,66 +1,9 @@
|
||||
#include "raylib.h"
|
||||
// #include "screens/Screen.h"
|
||||
// #include "screens/TitleScreen.h"
|
||||
#include "services/StateService.h"
|
||||
// #include <iostream>
|
||||
|
||||
// #if defined(PLATFORM_WEB)
|
||||
// #include <emscripten/emscripten.h>
|
||||
// #endif
|
||||
|
||||
// void step();
|
||||
// static void gameloop();
|
||||
|
||||
int main()
|
||||
{
|
||||
StateService& stateService = StateService::getInstance();
|
||||
stateService.setScreenSize({640,544});
|
||||
stateService.startGame();
|
||||
// std::cout << "StateService instance: " << service << std::endl;
|
||||
|
||||
// InitWindow(640, 544, "Jelly Rescue");
|
||||
// // SetTargetFPS(60);
|
||||
|
||||
// // setScreen(EScreen::TITLE);
|
||||
|
||||
// #if defined(PLATFORM_WEB)
|
||||
// emscripten_set_main_loop(step, 0, 1);
|
||||
// #else
|
||||
|
||||
// while (!WindowShouldClose())
|
||||
// {
|
||||
// step();
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// CloseWindow();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static void gameloop()
|
||||
// {
|
||||
// // InitAudioDevice();
|
||||
// InitWindow(640, 544, "Jelly Rescue");
|
||||
// // SetTargetFPS(60);
|
||||
|
||||
// // setScreen(EScreen::TITLE);
|
||||
|
||||
// #if defined(PLATFORM_WEB)
|
||||
// emscripten_set_main_loop(step, 0, 1);
|
||||
// #else
|
||||
|
||||
// while (!WindowShouldClose())
|
||||
// {
|
||||
// step();
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// CloseWindow();
|
||||
// // CloseAudioDevice();
|
||||
// }
|
||||
|
||||
// void step()
|
||||
// {
|
||||
// ClearBackground(BLACK);
|
||||
// }
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "screens/GameScreen.h"
|
||||
#include "entities/Map.h"
|
||||
#include "services/StateService.h"
|
||||
#include "services/GameService.h"
|
||||
|
||||
GameScreen::GameScreen()
|
||||
{
|
||||
@@ -12,6 +13,7 @@ GameScreen::GameScreen()
|
||||
// this->map = Map();
|
||||
|
||||
this->game = Game();
|
||||
// GameService::getInstance().setGame(this->game);
|
||||
// this->camera = camera;
|
||||
}
|
||||
|
||||
|
||||
+22
-14
@@ -1,14 +1,21 @@
|
||||
#include "screens/MainScreen.h"
|
||||
#include "raylib.h"
|
||||
#include "services/AudioService.h"
|
||||
#include "services/StateService.h"
|
||||
#include "raylib.h"
|
||||
#include "services/InputService.h"
|
||||
|
||||
MainScreen::MainScreen()
|
||||
{
|
||||
#if defined(PLATFORM_WEB)
|
||||
const int TOP_GAP = 100;
|
||||
const int BOTTOM_GAP = 100;
|
||||
const int AMNT_OF_BUTTONS = 2;
|
||||
#else
|
||||
const int TOP_GAP = 100;
|
||||
const int BOTTOM_GAP = 50;
|
||||
const int AMNT_OF_BUTTONS = 4;
|
||||
#endif
|
||||
|
||||
const int TOTAL_SPACE = GetScreenHeight() - (TOP_GAP + BOTTOM_GAP);
|
||||
const int SPACE_PER_ITEM = TOTAL_SPACE / AMNT_OF_BUTTONS;
|
||||
|
||||
@@ -18,13 +25,22 @@ MainScreen::MainScreen()
|
||||
buttons.push_back(txt);
|
||||
}
|
||||
buttons[0].setColor(RED);
|
||||
#if defined(PLATFORM_WEB)
|
||||
buttons[1].setText("tutorial");
|
||||
#else
|
||||
buttons[1].setText("load game");
|
||||
buttons[2].setText("tutorial");
|
||||
buttons[3].setText("quit");
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < AMNT_OF_BUTTONS; i++)
|
||||
{
|
||||
#if defined(PLATFORM_WEB)
|
||||
buttons[i].setPosition({(float)(GetScreenWidth() - buttons[i].getDimensions().x) / 2.0f, (float)TOP_GAP + SPACE_PER_ITEM * i + SPACE_PER_ITEM / 2.0f});
|
||||
|
||||
#else
|
||||
buttons[i].setPosition({(float)(GetScreenWidth() - buttons[i].getDimensions().x) / 2.0f, (float)TOP_GAP + SPACE_PER_ITEM * i});
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Will be ignored if already active (like when coming from the TitleScreen) */
|
||||
@@ -35,24 +51,16 @@ MainScreen::MainScreen()
|
||||
AudioService::getInstance().playMusic();
|
||||
}
|
||||
|
||||
InputService::getInstance().setKeysToWatch({KEY_ENTER, KEY_UP, KEY_DOWN}, {MOUSE_BUTTON_LEFT});
|
||||
InputService::getInstance().setKeysToWatch({KEY_ENTER, KEY_W, KEY_S}, {});
|
||||
}
|
||||
|
||||
void MainScreen::logic()
|
||||
{
|
||||
// Vector2 mouseD = GetMouseDelta();
|
||||
// std::cout << mouseD.y <<std::endl;
|
||||
// if (mouseD.x != 0.0f && mouseD.y != 0.0f)
|
||||
// {
|
||||
mouseLogic();
|
||||
// }
|
||||
|
||||
keyboardLogic();
|
||||
|
||||
clickLogic();
|
||||
}
|
||||
|
||||
|
||||
void MainScreen::mouseLogic()
|
||||
{
|
||||
for (int i = 0; i < buttons.size(); i++)
|
||||
@@ -67,7 +75,7 @@ void MainScreen::mouseLogic()
|
||||
Vector2 pos = buttons[i].getPosition();
|
||||
Rectangle rect = {pos.x, pos.y, dim.x, dim.y};
|
||||
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
Vector2 mousePos = InputService::getInstance().getMousePos();
|
||||
// mousePos.x >= rect.x && mousePos.x <= (rect.x+rect.width) &&
|
||||
if ((mousePos.x + textPadding) >= rect.x && mousePos.x <= (rect.x + rect.width + textPadding) && (mousePos.y + textPadding) >= rect.y && mousePos.y <= (rect.y + rect.height + textPadding))
|
||||
{
|
||||
@@ -81,18 +89,18 @@ void MainScreen::mouseLogic()
|
||||
|
||||
void MainScreen::keyboardLogic()
|
||||
{
|
||||
if (InputService::getInstance().isKeyPressed(KEY_DOWN) || InputService::getInstance().isKeyPressed(KEY_UP))
|
||||
if (InputService::getInstance().isKeyPressed(KEY_S) || InputService::getInstance().isKeyPressed(KEY_W))
|
||||
{
|
||||
buttons[hoveredButton].setColor(WHITE);
|
||||
/** Move up or down depending on the pressed button. +4 is used so that -1 becomes 3 (the last button) */
|
||||
hoveredButton = ((hoveredButton - (InputService::getInstance().isKeyPressed(KEY_DOWN) ? -1 : 1)) + 4) % 4;
|
||||
hoveredButton = ((hoveredButton - (InputService::getInstance().isKeyPressed(KEY_S) ? -1 : 1)) + buttons.size()) % buttons.size();
|
||||
buttons[hoveredButton].setColor(RED);
|
||||
}
|
||||
}
|
||||
|
||||
void MainScreen::clickLogic()
|
||||
{
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER) || InputService::getInstance().isMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER))
|
||||
{
|
||||
std::string selectedButton = buttons[hoveredButton].getText();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "services/StateService.h"
|
||||
#include "enums/EFont.h"
|
||||
#include "services/AudioService.h"
|
||||
#include <iostream>
|
||||
#include "services/InputService.h"
|
||||
|
||||
TitleScreen::TitleScreen()
|
||||
@@ -34,7 +33,6 @@ TitleScreen::TitleScreen()
|
||||
|
||||
void TitleScreen::logic()
|
||||
{
|
||||
// std::cout << "Next screen!" << std::endl;
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER) || InputService::getInstance().isMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::MAIN);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "screens/TutorialScreen.h"
|
||||
|
||||
#include "services/StateService.h"
|
||||
#include "enums/EFont.h"
|
||||
#include "enums/EScreen.h"
|
||||
#include "enums/EFont.h"
|
||||
#include "services/StateService.h"
|
||||
#include "services/InputService.h"
|
||||
|
||||
TutorialScreen::TutorialScreen() {
|
||||
@@ -13,12 +12,12 @@ TutorialScreen::TutorialScreen() {
|
||||
|
||||
this->background = Background(EBackground::TUTORIAL);
|
||||
|
||||
InputService::getInstance().setKeysToWatch({KEY_ENTER}, {MOUSE_BUTTON_LEFT});
|
||||
InputService::getInstance().setKeysToWatch({KEY_ENTER},{});
|
||||
}
|
||||
|
||||
void TutorialScreen::logic()
|
||||
{
|
||||
if ( InputService::getInstance().isKeyPressed(KEY_ENTER) || InputService::getInstance().isMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||
if ( InputService::getInstance().isKeyPressed(KEY_ENTER))
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::MAIN);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#include "screens/VictoryScreen.h"
|
||||
#include "services/InputService.h"
|
||||
#include "services/AudioService.h"
|
||||
#include "services/CollectableService.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
VictoryScreen::VictoryScreen()
|
||||
{
|
||||
AudioService::getInstance().stopMusic();
|
||||
AssetService::getInstance().playSound(ESound::VICTORY);
|
||||
|
||||
Text victory = Text("victory", EFont::GTEK, 50, 0, {255, 0, 0, 255});
|
||||
victory.setPosition({(float)(GetScreenWidth() - victory.getDimensions().x) / 2.0f,
|
||||
(float)(GetScreenHeight() - victory.getDimensions().y) / 2.5f});
|
||||
|
||||
int amntOfJelliesRescued = CollectableService::getInstance().getAmountOfJelliesFreed();
|
||||
int maxAmntOfJellies = CollectableService::getInstance().getMaxAmountOfJellies();
|
||||
std::string rescuedString;
|
||||
if (amntOfJelliesRescued == maxAmntOfJellies)
|
||||
{
|
||||
rescuedString = "You have rescued all of the jellies!";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "You have rescued ";
|
||||
stream << amntOfJelliesRescued;
|
||||
stream << " of the ";
|
||||
stream << maxAmntOfJellies;
|
||||
stream << " jellies";
|
||||
rescuedString = stream.str();
|
||||
}
|
||||
|
||||
Text rescued = Text(rescuedString, EFont::SANSATION, 30, 0, WHITE);
|
||||
rescued.setPosition({(float)(GetScreenWidth() - rescued.getDimensions().x) / 2.0f,
|
||||
(float)(GetScreenHeight() - rescued.getDimensions().y) / 1.5f});
|
||||
|
||||
this->text.push_back(victory);
|
||||
this->text.push_back(rescued);
|
||||
|
||||
|
||||
const int TOP_POS = GetScreenHeight()/1.2;
|
||||
const int X_GAP = 70;
|
||||
const int AMNT_OF_BUTTONS = 2;
|
||||
const int TOTAL_SPACE = GetScreenWidth() - X_GAP * 2;
|
||||
const int SPACE_PER_ITEM = TOTAL_SPACE / AMNT_OF_BUTTONS;
|
||||
|
||||
for (int i = 0; i < AMNT_OF_BUTTONS; i++)
|
||||
{
|
||||
Text txt = Text("Play Again", EFont::SANSATION, 30, 0, WHITE);
|
||||
buttons.push_back(txt);
|
||||
}
|
||||
buttons[0].setColor(RED);
|
||||
buttons[1].setText("Return to Main Menu");
|
||||
buttons[0].setPosition({(float)X_GAP, (float)TOP_POS});
|
||||
buttons[1].setPosition({(float)GetScreenWidth() - X_GAP - buttons[1].getDimensions().x, (float)TOP_POS});
|
||||
|
||||
const int x_gap = 50;
|
||||
const int available_space = GetScreenWidth() - x_gap * 2;
|
||||
const int space_per_jelly = available_space / maxAmntOfJellies;
|
||||
for (int i = 0; i < amntOfJelliesRescued; i++)
|
||||
{
|
||||
TextureWrapper wrapper = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY), {32, 32});
|
||||
wrapper.setPosition({(float)x_gap + space_per_jelly * i + space_per_jelly / 2.0f - wrapper.getSize().x / 2.0f, GetScreenHeight() / 2.0f});
|
||||
textures.push_back(wrapper);
|
||||
}
|
||||
|
||||
this->background = Background(EBackground::VICTORY);
|
||||
|
||||
InputService::getInstance().setKeysToWatch({KEY_ENTER, KEY_A, KEY_D}, {});
|
||||
}
|
||||
|
||||
void VictoryScreen::logic()
|
||||
{
|
||||
if (InputService::getInstance().isKeyPressed(KEY_D) || InputService::getInstance().isKeyPressed(KEY_A))
|
||||
{
|
||||
buttons[hoveredButton].setColor(WHITE);
|
||||
hoveredButton = ((hoveredButton - (InputService::getInstance().isKeyPressed(KEY_D) ? -1 : 1)) + buttons.size()) % buttons.size();
|
||||
buttons[hoveredButton].setColor(RED);
|
||||
}
|
||||
|
||||
if (InputService::getInstance().isKeyPressed(KEY_ENTER))
|
||||
{
|
||||
std::string selectedButton = buttons[hoveredButton].getText();
|
||||
|
||||
if (selectedButton == "Play Again")
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::GAME);
|
||||
}
|
||||
else if (selectedButton == "Return to Main Menu")
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::MAIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VictoryScreen::draw()
|
||||
{
|
||||
BeginDrawing();
|
||||
this->background.draw();
|
||||
|
||||
for (int t = 0; t < text.size(); t++)
|
||||
{
|
||||
text[t].draw();
|
||||
}
|
||||
|
||||
for (int t = 0; t < buttons.size(); t++)
|
||||
{
|
||||
buttons[t].draw();
|
||||
}
|
||||
|
||||
for (int t = 0; t < textures.size(); t++)
|
||||
{
|
||||
DrawTexture(textures[t].getTexture(), textures[t].getPosition().x, textures[t].getPosition().y, WHITE);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "services/AssetService.h"
|
||||
#include <iostream>
|
||||
AssetService::AssetService()
|
||||
{
|
||||
setAssetDir("assets/");
|
||||
@@ -17,9 +16,22 @@ void AssetService::setAssets()
|
||||
|
||||
music[EMusic::MAIN] = loadMusic("Audio/Music/Crash_WarpRoomTheme.ogg", true);
|
||||
music[EMusic::GAME] = loadMusic("Audio/Music/GameTheme_2.ogg", true);
|
||||
music[EMusic::GAME_OVER] = loadMusic("Audio/Music/gameOverTheme.ogg", false);
|
||||
music[EMusic::GAME_OVER] = loadMusic("Audio/Music/gameOverTheme_2.ogg", false);
|
||||
/** Todo: set volume */
|
||||
|
||||
sounds[ESound::SHOOT] = loadSound("Audio/Sounds/gunShot.wav");
|
||||
SetSoundVolume(sounds[ESound::SHOOT], 0.4f);
|
||||
sounds[ESound::NO_AMMO] = loadSound("Audio/Sounds/outOfAmmo.wav");
|
||||
sounds[ESound::CRATE_BREAK] = loadSound("Audio/Sounds/crateBreak.wav");
|
||||
sounds[ESound::JELLY_FREED] = loadSound("Audio/Sounds/jellyFreed.wav");
|
||||
sounds[ESound::HEAL_PICKUP] = loadSound("Audio/Sounds/healmag.wav");
|
||||
sounds[ESound::AMMO_PICKUP] = loadSound("Audio/Sounds/shotgunReload.wav");
|
||||
sounds[ESound::POWERUP] = loadSound("Audio/Sounds/powerUpSound.wav");
|
||||
sounds[ESound::VICTORY] = loadSound("Audio/Sounds/victorySound.wav");
|
||||
sounds[ESound::PLAYER_DAMAGE] = loadSound("Audio/Sounds/WaterBalloon.wav");
|
||||
sounds[ESound::ENEMY_DEFEATED] = loadSound("Audio/Sounds/pain.wav");
|
||||
sounds[ESound::PLAYER_SPOTTED] = loadSound("Audio/Sounds/playerSpotted.wav");
|
||||
|
||||
backgrounds[EBackground::TUTORIAL] = loadTexture("Textures/TutorialBackground2.png");
|
||||
backgrounds[EBackground::GAME1] = loadTexture("Textures/GameBackground_1.png");
|
||||
backgrounds[EBackground::GAME2] = loadTexture("Textures/GameBackground_2.jpg");
|
||||
@@ -43,6 +55,8 @@ void AssetService::setAssets()
|
||||
sprites[ESprite::HUD_HEART] = loadTexture("Textures/heart.png");
|
||||
sprites[ESprite::HUD_HEART_EMPTY] = loadTexture("Textures/heart_empty.png");
|
||||
sprites[ESprite::HUD_AMMO] = loadTexture("Textures/bullet_hud.png");
|
||||
sprites[ESprite::CROSSHAIR] = loadTexture("Textures/crosshair_3.png");
|
||||
sprites[ESprite::FLAG] = loadTexture("Textures/flag.png");
|
||||
}
|
||||
|
||||
Font AssetService::getFont(EFont font, int fontSize)
|
||||
|
||||
@@ -13,6 +13,7 @@ void AudioService::setMusic(EMusic music)
|
||||
if (currentTrack == music)
|
||||
return;
|
||||
|
||||
stopMusic(); // Makes sure it doesn't continue where it left off
|
||||
this->currentTrack = music;
|
||||
this->music = AssetService::getInstance().getMusic(music);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "services/CollectableService.h"
|
||||
#include "services/MapService.h"
|
||||
|
||||
void CollectableService::initCrates()
|
||||
{
|
||||
crates.clear();
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
for (int i = 0; i < amountOfCrates; i++)
|
||||
{
|
||||
crates.push_back(Crate());
|
||||
}
|
||||
crates[0].getObject().setPosition({38.0f * tileSize, 9.0f * tileSize});
|
||||
crates[1].getObject().setPosition({41.0f * tileSize, 5.0f * tileSize});
|
||||
crates[2].getObject().setPosition({68.0f * tileSize, 4.0f * tileSize});
|
||||
|
||||
for (int i = 0; i < crates.size(); i++)
|
||||
{
|
||||
Vector2i crateTilePos = Vector2i(crates[i].getObject().getPosition().x / tileSize, crates[i].getObject().getPosition().y / tileSize);
|
||||
MapService::getInstance().getMap().updateColmapTile(crateTilePos, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::initJellies()
|
||||
{
|
||||
jellies.clear();
|
||||
}
|
||||
|
||||
void CollectableService::initAmmoPacks()
|
||||
{
|
||||
ammoPacks.clear();
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
for (int i = 0; i < amountOfAmmoPacks; i++)
|
||||
{
|
||||
ammoPacks.push_back(AmmoPack());
|
||||
}
|
||||
ammoPacks[0].getObject().setPosition({32.0f * tileSize, 9.0f * tileSize});
|
||||
ammoPacks[1].getObject().setPosition({48.0f * tileSize, 5.0f * tileSize});
|
||||
ammoPacks[2].getObject().setPosition({88.0f * tileSize, 9.0f * tileSize});
|
||||
ammoPacks[3].getObject().setPosition({105.0f * tileSize, 15.0f * tileSize});
|
||||
}
|
||||
|
||||
void CollectableService::initHealthPacks()
|
||||
{
|
||||
healthPacks.clear();
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
for (int i = 0; i < amountOfHealthPacks; i++)
|
||||
{
|
||||
healthPacks.push_back(HealthPack());
|
||||
}
|
||||
healthPacks[0].getObject().setPosition({28.0f * tileSize, 10.0f * tileSize});
|
||||
healthPacks[1].getObject().setPosition({64.0f * tileSize, 6.0f * tileSize});
|
||||
healthPacks[2].getObject().setPosition({118.0f * tileSize, 11.0f * tileSize});
|
||||
healthPacks[3].getObject().setPosition({74.0f * tileSize, 8.0f * tileSize});
|
||||
}
|
||||
|
||||
void CollectableService::initPowerups()
|
||||
{
|
||||
powerUps.clear();
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
for (int i = 0; i < amountOfPowerups; i++)
|
||||
{
|
||||
powerUps.push_back(Powerup());
|
||||
}
|
||||
powerUps[0].getObject().setPosition({41.0f * tileSize + 8, 10.0f * tileSize - 25});
|
||||
}
|
||||
|
||||
void CollectableService::initFlag()
|
||||
{
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
this->flag = Flag({118.0f * tileSize - tileSize / 2.0f, 3.0f * tileSize - 8});
|
||||
}
|
||||
|
||||
void CollectableService::crateLogic()
|
||||
{
|
||||
for (auto it = crates.begin(); it != crates.end();)
|
||||
{
|
||||
auto &crate = *it;
|
||||
/**
|
||||
* If the crate has been hit:
|
||||
* 1. Create a Jelly on the location of the crate
|
||||
* 2. Remove the collision tile from the collision map
|
||||
* 3. Remove the crate
|
||||
*/
|
||||
if (crate.hasBeenHit())
|
||||
{
|
||||
Vector2 pos = crate.getObject().getPosition();
|
||||
|
||||
jellies.push_back(Jelly(pos));
|
||||
|
||||
Vector2i tilePos = Vector2i(pos.x / MapService::getInstance().getMap().getTileSize(), pos.y / MapService::getInstance().getMap().getTileSize());
|
||||
MapService::getInstance().getMap().updateColmapTile(tilePos, false);
|
||||
it = crates.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::jellyLogic()
|
||||
{
|
||||
for (int i = 0; i < jellies.size(); i++)
|
||||
{
|
||||
jellies[i].logic();
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::ammoPackLogic()
|
||||
{
|
||||
for (auto it = ammoPacks.begin(); it != ammoPacks.end();)
|
||||
{
|
||||
auto &ammoPack = *it;
|
||||
if (ammoPack.hasBeenPickedUp())
|
||||
{
|
||||
it = ammoPacks.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::healthPackLogic()
|
||||
{
|
||||
for (auto it = healthPacks.begin(); it != healthPacks.end();)
|
||||
{
|
||||
auto &healthPack = *it;
|
||||
if (healthPack.hasBeenPickedUp())
|
||||
{
|
||||
it = healthPacks.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::powerupLogic()
|
||||
{
|
||||
for (auto it = powerUps.begin(); it != powerUps.end();)
|
||||
{
|
||||
auto &powerUp = *it;
|
||||
if (powerUp.hasBeenPickedUp())
|
||||
{
|
||||
it = powerUps.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
powerUp.logic();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::drawCrates()
|
||||
{
|
||||
for (int i = 0; i < crates.size(); i++)
|
||||
{
|
||||
crates[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::drawJellies()
|
||||
{
|
||||
for (int i = 0; i < jellies.size(); i++)
|
||||
{
|
||||
jellies[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::drawAmmoPacks()
|
||||
{
|
||||
for (int i = 0; i < ammoPacks.size(); i++)
|
||||
{
|
||||
ammoPacks[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::drawHealthpacks()
|
||||
{
|
||||
for (int i = 0; i < healthPacks.size(); i++)
|
||||
{
|
||||
healthPacks[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CollectableService::drawPowerups()
|
||||
{
|
||||
for (int i = 0; i < powerUps.size(); i++)
|
||||
{
|
||||
powerUps[i].draw();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "services/EnemyService.h"
|
||||
#include "services/MapService.h"
|
||||
|
||||
void EnemyService::initEnemies()
|
||||
{
|
||||
this->enemies.clear();
|
||||
const int AMNT_OF_ENEMIES = 8;
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
for (int i = 0; i < AMNT_OF_ENEMIES; i++)
|
||||
{
|
||||
enemies.push_back(Enemy());
|
||||
}
|
||||
this->enemies[0].getObject().setPosition({31.0f * tileSize, 15.0f * tileSize});
|
||||
this->enemies[1].getObject().setPosition({51.0f * tileSize, 10.0f * tileSize});
|
||||
this->enemies[2].getObject().setPosition({56.0f * tileSize, 5.0f * tileSize});
|
||||
this->enemies[3].getObject().setPosition({78.0f * tileSize, 10.0f * tileSize});
|
||||
this->enemies[4].getObject().setPosition({82.0f * tileSize, 15.0f * tileSize});
|
||||
this->enemies[5].getObject().setPosition({88.0f * tileSize, 4.0f * tileSize});
|
||||
this->enemies[6].getObject().setPosition({98.0f * tileSize, 11.0f * tileSize});
|
||||
this->enemies[7].getObject().setPosition({103.0f * tileSize, 15.0f * tileSize});
|
||||
}
|
||||
|
||||
void EnemyService::enemyLogic()
|
||||
{
|
||||
for (auto it = enemies.begin(); it != enemies.end();)
|
||||
{
|
||||
auto &enemy = *it;
|
||||
if (enemy.getObject().getPosition().y < 0)
|
||||
{
|
||||
it = enemies.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
enemy.logic();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnemyService::drawEnemies()
|
||||
{
|
||||
for (int i = 0; i < enemies.size(); i++)
|
||||
{
|
||||
enemies[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Enemy> &EnemyService::getEnemies()
|
||||
{
|
||||
return this->enemies;
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "services/StateService.h"
|
||||
#include "raylib.h"
|
||||
#include "services/StateService.h"
|
||||
#include "services/AudioService.h"
|
||||
#include "services/InputService.h"
|
||||
#include "screens/TitleScreen.h"
|
||||
#include "screens/MainScreen.h"
|
||||
#include "screens/TutorialScreen.h"
|
||||
#include "screens/GameScreen.h"
|
||||
#include "screens/VictoryScreen.h"
|
||||
#include <optional>
|
||||
#include "services/AudioService.h"
|
||||
#include "services/InputService.h"
|
||||
|
||||
void StateService::setScreen(EScreen state)
|
||||
{
|
||||
@@ -24,6 +25,9 @@ void StateService::setScreen(EScreen state)
|
||||
case EScreen::GAME:
|
||||
currentScreen = std::make_unique<GameScreen>();
|
||||
break;
|
||||
case EScreen::VICTORY:
|
||||
currentScreen = std::make_unique<VictoryScreen>();
|
||||
break;
|
||||
case EScreen::CLOSE:
|
||||
gameRunning = false;
|
||||
break;
|
||||
@@ -44,17 +48,10 @@ void StateService::startGame()
|
||||
InitAudioDevice();
|
||||
// InitWindow(640,544, "Jelly Rescue");
|
||||
InitWindow(screenSize.x, screenSize.y, "Jelly Rescue");
|
||||
SetTargetFPS(60);
|
||||
|
||||
// #if defined(PLATFORM_WEB)
|
||||
// emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_CANVAS, nullptr, 1, staticStep);
|
||||
// #endif
|
||||
|
||||
// #if defined(PLATFORM_WEB)
|
||||
// emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_CANVAS, nullptr, 1, [](const EmscriptenFocusEvent* event) {
|
||||
// std::cout << "Canvas Focused!" << std::endl;
|
||||
// });
|
||||
// #endif
|
||||
SetTargetFPS(45);
|
||||
#if not defined(PLATFORM_WEB)
|
||||
HideCursor();
|
||||
#endif
|
||||
|
||||
setScreen(EScreen::TITLE);
|
||||
|
||||
@@ -62,7 +59,6 @@ void StateService::startGame()
|
||||
emscripten_set_main_loop(StateService::staticStep, 0, 1);
|
||||
#else
|
||||
|
||||
// while (!WindowShouldClose() && instance->gameRunning)
|
||||
while (!WindowShouldClose() && gameRunning)
|
||||
{
|
||||
step();
|
||||
@@ -85,6 +81,7 @@ void StateService::handleMusic()
|
||||
void StateService::step()
|
||||
{
|
||||
InputService::getInstance().checkKeys();
|
||||
InputService::getInstance().checkMousePos();
|
||||
|
||||
handleMusic();
|
||||
currentScreen->draw();
|
||||
|
||||
Reference in New Issue
Block a user