Zad3 - wip1

This commit is contained in:
Michał Leśniak 2021-12-20 18:54:21 +01:00
parent 86de1db6cb
commit 9674806687
17 changed files with 214 additions and 106 deletions

View File

@ -169,6 +169,7 @@
<ClCompile Include="KRect.cpp" />
<ClCompile Include="KCollider.cpp" />
<ClCompile Include="KRectPawn.cpp" />
<ClCompile Include="KSettings.cpp" />
<ClCompile Include="KTexture.cpp" />
<ClCompile Include="KWall.cpp" />
<ClCompile Include="Main.cpp" />
@ -199,6 +200,7 @@
<ClInclude Include="KRect.h" />
<ClInclude Include="KCollider.h" />
<ClInclude Include="KRectPawn.h" />
<ClInclude Include="KSettings.h" />
<ClInclude Include="KTexture.h" />
<ClInclude Include="KWall.h" />
<ClInclude Include="resource.h" />

View File

@ -66,9 +66,13 @@
<ClCompile Include="KFont.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="KSettings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="vcpkg.json" />
<None Include="config.json" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Utils.h">
@ -140,10 +144,39 @@
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="KSettings.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="2dgk_zad3.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="assets\textures\arrow.bmp">
<Filter>Resource Files</Filter>
</Image>
<Image Include="assets\textures\exit.bmp">
<Filter>Resource Files</Filter>
</Image>
<Image Include="assets\textures\P1.bmp">
<Filter>Resource Files</Filter>
</Image>
<Image Include="assets\textures\P2.bmp">
<Filter>Resource Files</Filter>
</Image>
<Image Include="assets\textures\wall.bmp">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<Font Include="assets\fonts\Roboto-Thin.ttf" />
</ItemGroup>
<ItemGroup>
<Text Include="assets\fonts\LICENSE.txt" />
<Text Include="assets\levels\level1.txt" />
<Text Include="assets\levels\level2.txt" />
<Text Include="assets\levels\level3.txt" />
</ItemGroup>
</Project>

View File

@ -1,7 +1,8 @@
#pragma once
namespace KapitanGame {
namespace Constants {
constexpr const char* WINDOW_TITLE = "2DGK - Zadanie 2 (Lab 7-8)";
constexpr const char* WINDOW_TITLE = "2DGK - Zadanie 3 (Lab 11-12)";
//Analog joystick dead zone
constexpr int JOYSTICK_DEAD_ZONE = 8000;
//Screen dimension constants
@ -13,8 +14,9 @@ namespace KapitanGame {
constexpr int TILE_HEIGHT = 32;
constexpr float SPEED = 200.f;
constexpr float SMOOTH = 0.4f;
constexpr float JUMP_SPEED = 200.f;
constexpr float JUMP_SHORT_SPEED = 100.f;
constexpr float GRAVITY = 200.f;
constexpr float JUMP_SPEED = 300.f;
constexpr float GRAVITY = 450.f;
constexpr float MAX_JUMP_VELOCITY = 1000.f;
constexpr float MAX_GRAVITY = 1000.f;
}
}

View File

@ -36,7 +36,7 @@ namespace KapitanGame
void KCamera::SetDebug(const SDL_FRect& map)
{
Viewport = { 0,0,Constants::SCREEN_WIDTH, Constants::SCREEN_HEIGHT };
Scale = Constants::SCREEN_RATIO > 1.f ? Constants::SCREEN_HEIGHT * 1.f / map.h : Constants::SCREEN_WIDTH * 1.f / map.w;
Scale = std::min(Constants::SCREEN_HEIGHT * 1.f / map.h, Constants::SCREEN_WIDTH * 1.f / map.w);
}
const SDL_FRect& KCamera::GetPlayArea() const

View File

@ -3,7 +3,7 @@
namespace KapitanGame
{
KCirclePawn::KCirclePawn(const KVector2D& position, const KTexture& texture,
const std::shared_ptr<KPlayerController>& playerController) : KPawn(position, texture, playerController),
const std::shared_ptr<KPlayerController>& playerController, KSettings* settings) : KPawn(position, texture, playerController, settings),
Collider(this, static_cast<float>(texture.GetWidth())/2.0f)
{
}

View File

@ -8,7 +8,7 @@ namespace KapitanGame
{
public:
KCirclePawn(const KVector2D& position, const KTexture& texture,
const std::shared_ptr<KPlayerController>& playerController);
const std::shared_ptr<KPlayerController>& playerController, KSettings* settings);
const KCollider* GetCollider() const override;
private:

View File

@ -48,7 +48,7 @@ namespace KapitanGame
KTexture KFont::GetTextTexture(const std::string& text, const SDL_Color textColor, SDL_Renderer* renderer) const
{
KTexture texture;
SDL_Surface* textSurface = TTF_RenderText_Blended(Font, text.c_str(), textColor);
SDL_Surface* textSurface = TTF_RenderText_Solid(Font, text.c_str(), textColor);
if (textSurface == nullptr)
{
printf("Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError());

View File

@ -29,6 +29,12 @@ namespace KapitanGame {
{
throw std::runtime_error(Utils::StringFormat("SDL could not initialize! SDL_Error: %s", SDL_GetError()));
}
#ifndef NDEBUG
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
#endif
//Set texture filtering to linear
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
{
@ -58,6 +64,7 @@ namespace KapitanGame {
}
//Initialize renderer color
SDL_SetRenderDrawColor(Renderer, 0, 0xFF, 0, 0xFF);
SDL_Log("KGame initialized...");
}
KGame::~KGame() {
@ -84,8 +91,8 @@ namespace KapitanGame {
{
bool success = true;
Objects.clear();
FreePositions.clear();
/*std::ifstream levelFile;
Pawns.clear();
std::ifstream levelFile;
levelFile.open("assets/levels/level" + std::to_string(LvlCounter) + ".txt");
if (levelFile.fail())
{
@ -96,6 +103,7 @@ namespace KapitanGame {
{
int y = 0;
float mapWidth = 0;
KVector2D startPosition{ 0.f, 0.f };
std::string line;
while (std::getline(levelFile, line)) {
if (mapWidth < static_cast<float>(line.length() * Constants::TILE_WIDTH))
@ -107,8 +115,8 @@ namespace KapitanGame {
case '#':
Objects.emplace(std::make_pair(static_cast<int>(i), y), std::make_shared<KWall>(position, Textures["wall.bmp"]));
break;
case ' ':
FreePositions.emplace_back(position);
case 'P':
startPosition = position;
break;
default:
break;
@ -119,18 +127,11 @@ namespace KapitanGame {
const auto mapHeight = static_cast<float>(y * Constants::TILE_HEIGHT);
levelFile.close();
Map = { 0,0,mapWidth,mapHeight };
}*/
Map = { 0,0,Constants::SCREEN_WIDTH,Constants::SCREEN_HEIGHT };
return success;
}
void KGame::LoadPlayerPawn()
{
Pawns.clear();
KVector2D StartPosition{ 0.f, 0.f };
Pawns.emplace_back(std::make_shared<KCirclePawn>(StartPosition, Textures["P1.bmp"], PlayerControllers[static_cast<int>(KPlayer::Player1)]));
Pawns.emplace_back(std::make_shared<KCirclePawn>(startPosition, Textures["P1.bmp"], PlayerControllers[static_cast<int>(KPlayer::Player1)], &Settings));
PlayerControllers[static_cast<int>(KPlayer::Player1)]->Possess(Pawns.back().get());
}
return success;
}
bool KGame::LoadMedia()
{
@ -161,7 +162,7 @@ namespace KapitanGame {
}
Fonts.emplace("PressStart2P-Regular", KFont());
if (!Fonts["PressStart2P-Regular"].LoadFromFile("assets/fonts/PressStart2P-Regular.ttf", 72))
if (!Fonts["PressStart2P-Regular"].LoadFromFile("assets/fonts/PressStart2P-Regular.ttf", 8))
{
printf("Failed to load PressStart2P-Regular font!\n");
Fonts.erase("PressStart2P-Regular");
@ -213,11 +214,13 @@ namespace KapitanGame {
KCamera debugCamera(Map);
debugCamera.SetDebug(Map);
bool debug = false;
char devMode = 0;
LoadPlayerPawn();
camera.Update(Pawns, Map);
VelocityTextureDirty = true;
GravityTextureDirty = true;
Time = PreviousTime = SDL_GetTicks();
printf("\n");
@ -246,12 +249,39 @@ namespace KapitanGame {
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_F1))
{
debug = !debug;
if (++devMode > 2) devMode = 0;
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Changed devMode to %d\n", devMode);
}
if (devMode >= 1) {
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_F2))
{
CollisionEnabled = !CollisionEnabled;
}
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_F3))
{
Settings.JumpVelocity -= 0.1f;
if (Settings.JumpVelocity < 0) Settings.JumpVelocity = 0;
VelocityTextureDirty = true;
}
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_F4))
{
Settings.JumpVelocity += 0.1f;
if (Settings.JumpVelocity > Constants::MAX_JUMP_VELOCITY) Settings.JumpVelocity = Constants::MAX_JUMP_VELOCITY;
VelocityTextureDirty = true;
}
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_F5))
{
Settings.Gravity -= 0.1f;
if (Settings.Gravity < 0) Settings.Gravity = 0;
GravityTextureDirty = true;
}
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_F6))
{
Settings.Gravity += 0.1f;
if (Settings.Gravity > Constants::MAX_GRAVITY) Settings.Gravity = Constants::MAX_GRAVITY;
GravityTextureDirty = true;
}
}
if (Playing) {
for (const auto& pc : PlayerControllers) {
@ -279,13 +309,21 @@ namespace KapitanGame {
camera.Update(Pawns, Map);
}
if (VelocityTextureDirty) {
Textures.insert_or_assign("Text_Velocity", Fonts["PressStart2P-Regular"].GetTextTexture(Utils::StringFormat("Velocity: %f", Settings.JumpVelocity), { 0,0,0,0xFF }, Renderer));
VelocityTextureDirty = false;
}
if (GravityTextureDirty) {
Textures.insert_or_assign("Text_Gravity", Fonts["PressStart2P-Regular"].GetTextTexture(Utils::StringFormat("Gravity: %f", Settings.Gravity), { 0,0,0,0xFF }, Renderer));
GravityTextureDirty = false;
}
if (!Playing)
{
if (Time > RestartTick)
{
LoadLevel();
LoadPlayerPawn();
debugCamera.SetDebug(Map);
camera.Update(Pawns, Map);
if (ShowWinner)
@ -308,12 +346,12 @@ namespace KapitanGame {
SDL_SetRenderDrawColor(Renderer, 66, 135, 245, 0xFF);
SDL_RenderClear(Renderer);
const auto& cameraInUse = debug ? debugCamera : camera;
const auto& cameraInUse = devMode >= 2 ? debugCamera : camera;
if (Playing) {
for (const auto& object : Objects)
object.second->Render(Renderer, cameraInUse);
for (const auto& [tile, obj] : Objects)
obj->Render(Renderer, cameraInUse);
for (const auto& pawn : Pawns) {
pawn->Render(Renderer, cameraInUse);
}
@ -329,8 +367,12 @@ namespace KapitanGame {
Textures["Text_Winner"].Render(Renderer, Constants::SCREEN_WIDTH / 2.f - Textures["Text_Winner"].GetWidth() / 2.f, 25.f);
}
Textures["Text_Score"].Render(Renderer, Constants::SCREEN_WIDTH / 2.f - Textures["Text_Score"].GetWidth() / 2.f, Constants::SCREEN_HEIGHT - 10.f - Textures["Text_Score"].GetHeight());
if (debug)
//Textures["Text_Score"].Render(Renderer, Constants::SCREEN_WIDTH / 2.f - Textures["Text_Score"].GetWidth() / 2.f, Constants::SCREEN_HEIGHT - 10.f - Textures["Text_Score"].GetHeight());
if (devMode >= 1) {
Textures["Text_Velocity"].Render(Renderer, 10.f, 25.f);
Textures["Text_Gravity"].Render(Renderer, 10.f, 30.f + Textures["Text_Velocity"].GetHeight());
}
if (devMode >= 2)
{
SDL_SetRenderDrawColor(Renderer, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderDrawLineF(Renderer, 0, Constants::SCREEN_HEIGHT / 2.f, Constants::SCREEN_WIDTH, Constants::SCREEN_HEIGHT / 2.f);

View File

@ -7,6 +7,7 @@
#include "KFont.h"
#include "KInput.h"
#include "KSettings.h"
#include "Utils.h"
@ -35,7 +36,6 @@ namespace KapitanGame {
std::vector<std::shared_ptr<KPlayerController>> PlayerControllers;
std::unordered_map<std::string, KTexture> Textures;
std::unordered_map<std::string, KFont> Fonts;
std::vector<KVector2D> FreePositions;
KInput Input;
uint32_t Time;
uint32_t PreviousTime;
@ -43,9 +43,11 @@ namespace KapitanGame {
bool CollisionEnabled = true;
bool ShowWinner = false;
std::weak_ptr<KObject> Exit;
KSettings Settings;
bool VelocityTextureDirty;
bool GravityTextureDirty;
bool LoadLevel();
void LoadPlayerPawn();
bool LoadMedia();
int LvlCounter = 1;

View File

@ -2,11 +2,11 @@
#include <memory>
#include <typeinfo>
#include <unordered_map>
#include "Constants.h"
#include "KPlayerController.h"
#include "KExit.h"
#include "KSettings.h"
namespace KapitanGame
{
@ -19,8 +19,9 @@ namespace KapitanGame
for (const auto& [oX, oY] : std::initializer_list<std::pair<int, int>>{ {0, 0}, {-1,0}, {1,0}, {0,-1}, {0,1}, {-1,-1}, {1,1}, {1,-1}, {-1,1} })
{
try {
const auto& other = objects.at({ xPos + oX, yPos + oY });
auto it = objects.find({ xPos + oX, yPos + oY });
if (it == objects.end()) continue;
const auto& other = it->second;
if (other->GetCollider() == nullptr) continue;
if (other->Id == Id) continue;
if (GetCollider()->IsCollision(other->GetCollider())) {
@ -33,24 +34,27 @@ namespace KapitanGame
const auto separationVector = GetCollider()->GetSeparationVector(other->GetCollider());
Position += separationVector;
if (separationVector.Y < 0)
if (GetPosition().Y - GetCollider()->GetHeight() / 2.f >= other->GetPosition().Y + other->GetCollider()->GetHeight() / 2.f)
{
Velocity.Y = 0;
Grounded = true;
}
}
}
catch (std::out_of_range&)
if (GetPosition().Y + GetCollider()->GetHeight() / 2.f <= other->GetPosition().Y - other->GetCollider()->GetHeight() / 2.f)
{
Velocity.Y = 0;
CanJump = true;
CanDoubleJump = true;
HasJumped = false;
}
}
}
}
void KPawn::MovementStep(const float& timeStep)
{
const float gravityScale = Velocity.Y > 0.f ? 3.f : 1.f;
Position.X += Velocity.X * timeStep;
Position.Y += Velocity.Y * timeStep + 1.f / 2.f * Constants::GRAVITY * timeStep * timeStep;
Velocity.Y += Constants::GRAVITY * timeStep;
Position.Y += Velocity.Y * timeStep + 1.f / 2.f * gravityScale * Settings->Gravity * timeStep * timeStep;
Velocity.Y += gravityScale * Settings->Gravity * timeStep;
}
void KPawn::CollisionDetectionWithMapStep(const SDL_FRect& map)
@ -60,7 +64,9 @@ namespace KapitanGame
if (separationVector.Y < 0)
{
Velocity.Y = 0;
Grounded = true;
CanJump = true;
CanDoubleJump = true;
HasJumped = false;
}
}
@ -70,16 +76,26 @@ namespace KapitanGame
}
void KPawn::StopJump() {
if (!Grounded) {
if (Velocity.Y < -Constants::JUMP_SHORT_SPEED)
Velocity.Y = -Constants::JUMP_SHORT_SPEED;
if (!CanJump) {
if (Velocity.Y < -Settings->ShortJumpVelocity())
Velocity.Y = -Settings->ShortJumpVelocity();
}
}
void KPawn::StartJump() {
if (Grounded) {
Grounded = false;
Velocity.Y = -Constants::JUMP_SPEED;
if (Velocity.Y != 0.f)
{
CanJump = false;
}
if (CanJump) {
CanJump = false;
HasJumped = true;
Velocity.Y = -Settings->JumpVelocity;
}
else if (HasJumped && CanDoubleJump)
{
CanDoubleJump = false;
Velocity.Y = -Settings->JumpVelocity;
}
}
}

View File

@ -7,17 +7,19 @@
namespace KapitanGame
{
struct KSettings;
class KPlayerController;
class KPawn : public KObject
{
public:
KPawn(const KVector2D& position, const KTexture& texture,
const std::shared_ptr<KPlayerController>& playerController)
const std::shared_ptr<KPlayerController>& playerController, KSettings* settings)
: KObject(position, texture),
PlayerController(playerController)
PlayerController(playerController), CanJump(false), CanDoubleJump(false), HasJumped(true), Settings(settings)
{
}
void CollisionDetectionStep(const std::unordered_map<std::pair<int, int>, std::shared_ptr<KObject>, Utils::PairHash>& objects);
void MovementStep(const float& timeStep);
void CollisionDetectionWithMapStep(const SDL_FRect& map);
@ -27,7 +29,10 @@ namespace KapitanGame
private:
const std::weak_ptr<KPlayerController> PlayerController;
KVector2D Velocity{ 0.f, 0.f };
bool Grounded;
bool CanJump;
bool CanDoubleJump;
bool HasJumped;
KSettings* Settings;
};
}

View File

@ -3,7 +3,7 @@
namespace KapitanGame
{
KRectPawn::KRectPawn(const KVector2D& position, const KTexture& texture,
const std::shared_ptr<KPlayerController>& playerController) : KPawn(position, texture, playerController),
const std::shared_ptr<KPlayerController>& playerController, KSettings* settings) : KPawn(position, texture, playerController, settings),
Collider(this, texture.GetWidth(), texture.GetHeight())
{
}

View File

@ -9,7 +9,7 @@ namespace KapitanGame
{
public:
KRectPawn(const KVector2D& position, const KTexture& texture,
const std::shared_ptr<KPlayerController>& playerController);
const std::shared_ptr<KPlayerController>& playerController, KSettings* settings);
const KCollider* GetCollider() const override;
private:

View File

@ -0,0 +1,9 @@
#include "KSettings.h"
namespace KapitanGame
{
float KSettings::ShortJumpVelocity() const
{
return JumpVelocity / 2.f;
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Constants.h"
namespace KapitanGame
{
struct KSettings
{
float Gravity = Constants::GRAVITY;
float JumpVelocity = Constants::JUMP_SPEED;
[[nodiscard]] float ShortJumpVelocity() const;
};
}

View File

@ -17,6 +17,7 @@ namespace KapitanGame {
KTexture& KTexture::operator=(KTexture&& other) noexcept {
if (this == &other)
return *this;
Free();
Texture = other.Texture;
Width = other.Width;
Height = other.Height;

View File

@ -1,33 +1,15 @@
#################################
# # # # # # #
# ######### # # ### # # ### ### #
# # # # # # # #
### ### ### ### # ### # # # #####
# # # # # # # # # # #
# # ### # # # # ####### # # ### #
# # # # # # # # # # # #
####### ### ### # ####### ### # #
# # # # # # # # # #
# # # ### ### # # # # ### # #####
# # # # # # # # # #
# # ### # ### # # ### # # ### # #
# # # # # # # # # # #
# # # ### ### # ### ### ### # # #
# # # # # # # # # # # #
# ### ##### ##### # ######### ###
# # # # # # #
##### ### # ### ####### # ##### #
# # # # # #
# ######### # # ####### ##### ###
# # # # # # # # #
### ### ### ########### ### # ###
# # # # # # #
# # ### # ### # ##### ### ### # #
# # # # # # # # #
# # ##### ### ### ### # ### # ###
# # # # # # # # # #
# ##### # # ##### # # ##### #####
# # # # # # # # # # # # #
# # ### ##### ####### # # # ### #
# # # # # #
#################################
#
# ##### ##
## ##
## ## ##
P ## ## ##
##################################################################
##################################################################