Laboratorium 5 done
This commit is contained in:
parent
9af453e459
commit
aec76c7378
@ -154,11 +154,12 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="KCircle.cpp" />
|
||||
<ClCompile Include="KGame.cpp" />
|
||||
<ClCompile Include="KInput.cpp" />
|
||||
<ClCompile Include="KTexture.cpp" />
|
||||
<ClCompile Include="KTile.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="vcpkg.json" />
|
||||
@ -166,10 +167,10 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Constants.h" />
|
||||
<ClInclude Include="GamePad.h" />
|
||||
<ClInclude Include="KCircle.h" />
|
||||
<ClInclude Include="KGame.h" />
|
||||
<ClInclude Include="KInput.h" />
|
||||
<ClInclude Include="KTexture.h" />
|
||||
<ClInclude Include="KTile.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="KVector2d.h" />
|
||||
</ItemGroup>
|
||||
|
@ -18,9 +18,6 @@
|
||||
<ClCompile Include="Main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KTile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KTexture.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -30,6 +27,12 @@
|
||||
<ClCompile Include="KInput.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KCircle.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="vcpkg.json" />
|
||||
@ -44,9 +47,6 @@
|
||||
<ClInclude Include="KVector2d.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KTile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KTexture.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -59,5 +59,8 @@
|
||||
<ClInclude Include="KInput.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KCircle.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
namespace KapitanGame {
|
||||
namespace Constants {
|
||||
constexpr const char* WINDOW_TITLE = "2DGK - Zadanie 5";
|
||||
constexpr const char* WINDOW_TITLE = "2DGK - Zadanie 7-8";
|
||||
//Analog joystick dead zone
|
||||
constexpr int JOYSTICK_DEAD_ZONE = 8000;
|
||||
//Screen dimension constants
|
||||
@ -13,5 +13,6 @@ namespace KapitanGame {
|
||||
constexpr int TILE_HEIGHT = 32;
|
||||
constexpr float SPEED = 0.16f;
|
||||
constexpr float SMOOTH = 0.4f;
|
||||
constexpr int CIRCLES_COUNT = 100;
|
||||
}
|
||||
}
|
||||
|
78
2dgk_6/2dgk_6/KCircle.cpp
Normal file
78
2dgk_6/2dgk_6/KCircle.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "KCircle.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "Constants.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace KapitanGame {
|
||||
std::atomic<int> KCircle::IdCounter{ 0 };
|
||||
|
||||
KCircle::KCircle(const KVector2D& position, const KVector2D& velocity, const float& radius, const KTexture& texture) : Id(++IdCounter),
|
||||
Position(position),
|
||||
Velocity(velocity),
|
||||
Radius(radius),
|
||||
Texture(texture) {
|
||||
}
|
||||
|
||||
void KCircle::CollisionDetectionStep(const std::vector<KCircle>& circles, const bool& shouldSeparate, const bool& shouldReflect) {
|
||||
for (auto& other : circles) {
|
||||
if (other.Id == Id) continue;
|
||||
if (IsCollision(other)) {
|
||||
auto separationVector = GetSeparationVector(other);
|
||||
if (shouldSeparate)
|
||||
Position += separationVector;
|
||||
if (shouldReflect)
|
||||
{
|
||||
separationVector.Normalize();
|
||||
Velocity = Velocity.Reflect(separationVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KCircle::MovementStep(const float& timeStep) {
|
||||
//Velocity.Normalize();
|
||||
//Velocity *= 100;
|
||||
Position += Velocity * timeStep;
|
||||
}
|
||||
|
||||
bool KCircle::IsCollision(const KCircle& other) const {
|
||||
return (Position - other.Position).Length() < Radius + other.Radius;
|
||||
}
|
||||
|
||||
KVector2D KCircle::GetSeparationVector(const KCircle& other) const {
|
||||
const KVector2D centerDiff = Position - other.Position;
|
||||
const float centerDiffLength = centerDiff.Length();
|
||||
return centerDiff / centerDiffLength * (Radius + other.Radius - centerDiffLength);
|
||||
}
|
||||
|
||||
void KCircle::Render(SDL_Renderer* renderer) const {
|
||||
Texture.Render(renderer, static_cast<int>(Position.X) - Texture.GetWidth() / 2, static_cast<int>(Position.Y) - Texture.GetHeight() / 2);
|
||||
}
|
||||
|
||||
void KCircle::CollisionDetectionWithMapStep(const SDL_Rect& map) {
|
||||
|
||||
if (Position.X - map.x - Radius < 0)
|
||||
{
|
||||
Position.X += -(Position.X - map.x - Radius);
|
||||
Velocity = Velocity.Reflect({ -1.f, 0.f });
|
||||
}
|
||||
if (Position.X + Radius - map.w > 0)
|
||||
{
|
||||
Velocity = Velocity.Reflect({ 1.f, 0.f });
|
||||
Position.X += -(Position.X - map.w + Radius);
|
||||
}
|
||||
if (Position.Y - Radius - map.y < 0) {
|
||||
Position.Y += -(Position.Y - map.y - Radius);
|
||||
Velocity = Velocity.Reflect({ 0.f, 1.f });
|
||||
}
|
||||
if (Position.Y + Radius - map.h > 0) {
|
||||
Position.Y += -(Position.Y - map.h + Radius);
|
||||
Velocity = Velocity.Reflect({ 0.f, -1.f });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
31
2dgk_6/2dgk_6/KCircle.h
Normal file
31
2dgk_6/2dgk_6/KCircle.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <SDL_render.h>
|
||||
#include <vector>
|
||||
|
||||
#include "KTexture.h"
|
||||
#include "KVector2d.h"
|
||||
|
||||
namespace KapitanGame {
|
||||
class KCircle
|
||||
{
|
||||
public:
|
||||
KCircle(const KVector2D& position, const KVector2D& velocity, const float& radius, const KTexture& texture);
|
||||
|
||||
void CollisionDetectionStep(const std::vector<KCircle>& circles, const bool& shouldSeparate, const bool& shouldReflect);
|
||||
void MovementStep(const float& timeStep);
|
||||
bool IsCollision(const KCircle& other) const;
|
||||
KVector2D GetSeparationVector(const KCircle& other) const;
|
||||
void Render(SDL_Renderer* renderer) const;
|
||||
void CollisionDetectionWithMapStep(const SDL_Rect& map);
|
||||
const int Id;
|
||||
static std::atomic<int> IdCounter;
|
||||
private:
|
||||
KVector2D Position{ 0.f, 0.f };
|
||||
KVector2D Velocity{ 0.f, 0.f };
|
||||
float Radius{ 1.f };
|
||||
const KTexture& Texture;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "KVector2d.h"
|
||||
|
||||
namespace KapitanGame {
|
||||
KGame::KGame() {
|
||||
KGame::KGame() : HasSeparation(true), HasCollision(true) {
|
||||
//Initialize SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||
{
|
||||
@ -45,11 +45,8 @@ namespace KapitanGame {
|
||||
|
||||
KGame::~KGame() {
|
||||
//Free loaded images
|
||||
for (int i = 0; i <= static_cast<int>(TileType::Dot); ++i)
|
||||
TileTextures[i].Free();
|
||||
|
||||
PlayerTexture.Free();
|
||||
PlayerTexture2.Free();
|
||||
CircleTexture.Free();
|
||||
|
||||
Input.Free();
|
||||
|
||||
@ -68,64 +65,11 @@ namespace KapitanGame {
|
||||
//Loading success flag
|
||||
bool success = true;
|
||||
|
||||
if (!PlayerTexture.LoadFromFile("textures/player.bmp", Renderer))
|
||||
if (!CircleTexture.LoadFromFile("textures/00.bmp", Renderer))
|
||||
{
|
||||
printf("Failed to load player texture image!\n");
|
||||
success = false;
|
||||
}
|
||||
if (!PlayerTexture2.LoadFromFile("textures/player2.bmp", Renderer))
|
||||
{
|
||||
printf("Failed to load player texture image!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
for (int i = static_cast<int>(TileType::Default); i <= static_cast<int>(TileType::Dot); ++i)
|
||||
{
|
||||
if (!TileTextures[i].LoadFromFile("textures/0" + std::to_string(i) + ".bmp", Renderer))
|
||||
{
|
||||
printf("Failed to load 0%d texture image!\n", i);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
Tiles.clear();
|
||||
std::ifstream levelFile;
|
||||
levelFile.open("level.txt");
|
||||
if (levelFile.fail())
|
||||
{
|
||||
printf("Failed to load level.txt!\n");
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int y = 0;
|
||||
std::string line;
|
||||
while (std::getline(levelFile, line)) {
|
||||
if (MapWidth < static_cast<int>(line.length() * Constants::TILE_WIDTH))
|
||||
MapWidth = static_cast<int>(line.length()) * Constants::TILE_WIDTH;
|
||||
for (auto i = 0ull; i < line.length(); ++i) {
|
||||
auto type = TileType::Default;
|
||||
switch (line[i])
|
||||
{
|
||||
case '|':
|
||||
type = TileType::VerticalWall;
|
||||
break;
|
||||
case '-':
|
||||
type = TileType::HorizontalWall;
|
||||
break;
|
||||
case '.':
|
||||
type = TileType::Dot;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
Tiles.emplace_back(i * Constants::TILE_WIDTH, y * Constants::TILE_HEIGHT, type);
|
||||
}
|
||||
++y;
|
||||
}
|
||||
MapHeight = y * Constants::TILE_HEIGHT;
|
||||
levelFile.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -170,51 +114,21 @@ namespace KapitanGame {
|
||||
//Event handler
|
||||
SDL_Event e;
|
||||
|
||||
SDL_Rect viewport;
|
||||
viewport.x = Constants::SCREEN_WIDTH / 2;
|
||||
viewport.y = Constants::SCREEN_HEIGHT / 2;
|
||||
viewport.w = Constants::SCREEN_WIDTH;
|
||||
viewport.h = Constants::SCREEN_HEIGHT;
|
||||
SDL_Rect map{ 0,0,Constants::SCREEN_WIDTH, Constants::SCREEN_HEIGHT };
|
||||
|
||||
KVector2D playerOnePosition(0, 0);
|
||||
KVector2D playerOneInput(0, 0);
|
||||
KVector2D playerOneVelocity(0, 0);
|
||||
|
||||
KVector2D playerTwoPosition(0, 0);
|
||||
KVector2D playerTwoInput(0, 0);
|
||||
KVector2D playerTwoVelocity(0, 0);
|
||||
|
||||
SDL_Rect playerAreaModeGauntlet;
|
||||
playerAreaModeGauntlet.x = 0;
|
||||
playerAreaModeGauntlet.y = 0;
|
||||
playerAreaModeGauntlet.w = Constants::SCREEN_WIDTH - Constants::WINDOW_DEAD_ZONE;
|
||||
playerAreaModeGauntlet.h = Constants::SCREEN_HEIGHT - Constants::WINDOW_DEAD_ZONE;
|
||||
|
||||
|
||||
SDL_Rect playerAreaModeZoom;
|
||||
playerAreaModeZoom.x = 0;
|
||||
playerAreaModeZoom.y = 0;
|
||||
playerAreaModeZoom.w = (MapWidth <= MapHeight ? MapWidth : static_cast<int>(static_cast<float>(MapHeight) * Constants::SCREEN_RATIO)) - Constants::WINDOW_DEAD_ZONE;
|
||||
playerAreaModeZoom.h = (MapHeight <= MapWidth ? MapHeight : static_cast<int>(static_cast<float>(MapWidth) / Constants::SCREEN_RATIO)) - Constants::WINDOW_DEAD_ZONE;
|
||||
|
||||
float scale = 1.f;
|
||||
|
||||
//Normalized direction
|
||||
int xDir = 0;
|
||||
int yDir = 0;
|
||||
|
||||
uint32_t time, previousTime;
|
||||
time = previousTime = SDL_GetTicks();
|
||||
for (int i = 0; i < Constants::CIRCLES_COUNT; ++i) {
|
||||
KVector2D position(Utils::RandomNumber() * (Constants::SCREEN_WIDTH - 2 * CircleTexture.GetWidth()) + CircleTexture.GetWidth(), Utils::RandomNumber() * (Constants::SCREEN_HEIGHT - 2 * CircleTexture.GetHeight()) + CircleTexture.GetHeight());
|
||||
Circles.emplace_back(position, KVector2D(100.f, 100.f), CircleTexture.GetWidth() / 2, CircleTexture);
|
||||
}
|
||||
uint32_t previousTime;
|
||||
uint32_t time = previousTime = SDL_GetTicks();
|
||||
printf("\n");
|
||||
bool zoom = false;
|
||||
|
||||
//While application is running
|
||||
while (!quit)
|
||||
{
|
||||
previousTime = time;
|
||||
time = SDL_GetTicks();
|
||||
playerOneInput.X = 0;
|
||||
playerOneInput.Y = 0;
|
||||
|
||||
Input.HandleInputPreEvents();
|
||||
|
||||
@ -231,123 +145,31 @@ namespace KapitanGame {
|
||||
}
|
||||
Input.HandleInputPostEvents();
|
||||
|
||||
playerTwoInput.X = Input.GetControllerAxis(Controllers::Controller1, SDL_CONTROLLER_AXIS_LEFTX);
|
||||
playerTwoInput.Y = Input.GetControllerAxis(Controllers::Controller1, SDL_CONTROLLER_AXIS_LEFTY);
|
||||
|
||||
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_W))
|
||||
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_S) || Input.IsControllerButtonPressed(Controllers::Controller1, SDL_CONTROLLER_BUTTON_START))
|
||||
{
|
||||
playerOneInput.Y = -1;
|
||||
HasSeparation = !HasSeparation;
|
||||
}
|
||||
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_S))
|
||||
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_C) || Input.IsControllerButtonPressed(Controllers::Controller1, SDL_CONTROLLER_BUTTON_BACK))
|
||||
{
|
||||
playerOneInput.Y = 1;
|
||||
}
|
||||
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_A))
|
||||
{
|
||||
playerOneInput.X = -1;
|
||||
}
|
||||
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_D))
|
||||
{
|
||||
playerOneInput.X = 1;
|
||||
HasCollision = !HasCollision;
|
||||
}
|
||||
|
||||
playerOneInput.Normalize();
|
||||
playerOneVelocity = playerOneInput * Constants::SPEED * (1 - Constants::SMOOTH) + playerOneVelocity * Constants::SMOOTH;
|
||||
|
||||
playerOnePosition += playerOneVelocity;
|
||||
for (auto& circle : Circles)
|
||||
circle.CollisionDetectionStep(Circles, HasSeparation, HasCollision);
|
||||
|
||||
if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_F))
|
||||
{
|
||||
zoom = !zoom;
|
||||
}
|
||||
|
||||
const auto& playerArea = zoom ? playerAreaModeZoom : playerAreaModeGauntlet;
|
||||
|
||||
|
||||
// keep player one near player two
|
||||
if (playerOnePosition.X < playerTwoPosition.X - playerArea.w) playerOnePosition.X = playerTwoPosition.X - playerArea.w;
|
||||
if (playerOnePosition.X > playerTwoPosition.X + playerArea.w) playerOnePosition.X = playerTwoPosition.X + playerArea.w;
|
||||
if (playerOnePosition.Y < playerTwoPosition.Y - playerArea.h) playerOnePosition.Y = playerTwoPosition.Y - playerArea.h;
|
||||
if (playerOnePosition.Y > playerTwoPosition.Y + playerArea.h) playerOnePosition.Y = playerTwoPosition.Y + playerArea.h;
|
||||
|
||||
// keep player one in map
|
||||
if (playerOnePosition.X < 0) playerOnePosition.X = 0;
|
||||
if (playerOnePosition.X > MapWidth - PlayerTexture.GetWidth()) playerOnePosition.X = (MapWidth - PlayerTexture.GetWidth());
|
||||
if (playerOnePosition.Y < 0) playerOnePosition.Y = (0);
|
||||
if (playerOnePosition.Y > MapHeight - PlayerTexture.GetHeight()) playerOnePosition.Y = (MapHeight - PlayerTexture.GetHeight());
|
||||
|
||||
//playerTwoInput.Normalize();
|
||||
//printf("\r \rX:%f, Y:%f", playerTwoInput.x, playerTwoInput.y);
|
||||
playerTwoVelocity = playerTwoInput * Constants::SPEED * (1 - Constants::SMOOTH) + playerTwoVelocity * Constants::SMOOTH;
|
||||
|
||||
playerTwoPosition += playerTwoVelocity;
|
||||
|
||||
|
||||
if (playerTwoPosition.X < playerOnePosition.X - static_cast<float>(playerArea.w)) playerTwoPosition.X = playerOnePosition.X - playerArea.w;
|
||||
if (playerTwoPosition.X > playerOnePosition.X + playerArea.w) playerTwoPosition.X = playerOnePosition.X + playerArea.w;
|
||||
if (playerTwoPosition.Y < playerOnePosition.Y - playerArea.h) playerTwoPosition.Y = playerOnePosition.Y - playerArea.h;
|
||||
if (playerTwoPosition.Y > playerOnePosition.Y + playerArea.h) playerTwoPosition.Y = playerOnePosition.Y + playerArea.h;
|
||||
|
||||
if (playerTwoPosition.X < 0) playerTwoPosition.X = 0;
|
||||
if (playerTwoPosition.X > MapWidth - PlayerTexture.GetWidth()) playerTwoPosition.X = MapWidth - PlayerTexture.GetWidth();
|
||||
if (playerTwoPosition.Y < 0) playerTwoPosition.Y = 0;
|
||||
if (playerTwoPosition.Y > MapHeight - PlayerTexture.GetHeight()) playerTwoPosition.Y = MapHeight - PlayerTexture.GetHeight();
|
||||
|
||||
|
||||
scale = 1.f;
|
||||
if (zoom)
|
||||
{
|
||||
float xDist = std::abs(playerTwoPosition.X - playerOnePosition.X) - playerAreaModeGauntlet.w;
|
||||
float yDist = std::abs(playerTwoPosition.Y - playerOnePosition.Y) - playerAreaModeGauntlet.h;
|
||||
float xMaxDist = playerAreaModeZoom.w - playerAreaModeGauntlet.w;
|
||||
float yMaxDist = playerAreaModeZoom.h - playerAreaModeGauntlet.h;
|
||||
float t1 = Utils::Clamp(xDist / xMaxDist);
|
||||
float t2 = Utils::Clamp(yDist / yMaxDist);
|
||||
float t = std::max(std::max(t1, 0.f), std::max(t2, 0.f));
|
||||
scale = Utils::Lerp(scale, std::max(Constants::SCREEN_WIDTH * 1.0f / MapWidth, Constants::SCREEN_HEIGHT * 1.0f / MapHeight), t);
|
||||
//printf("\rscale: %f, t1: %f, t2: %f, t: %f", scale, t1, t2, t);
|
||||
}
|
||||
|
||||
KVector2D focusPoint = (playerOnePosition + playerTwoPosition + KVector2D(PlayerTexture.GetWidth(), PlayerTexture.GetHeight())+KVector2D(Constants::WINDOW_DEAD_ZONE, Constants::WINDOW_DEAD_ZONE)/2)*scale/2;
|
||||
if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_Q))
|
||||
{
|
||||
focusPoint = KVector2D(MapWidth / 2.f, MapHeight / 2.f);
|
||||
}
|
||||
|
||||
//viewport.x += clamp((time - previous_time) * .05f) * (focusPoint.x - SCREEN_WIDTH / 2 - viewport.x);
|
||||
viewport.x = Utils::Lerp(viewport.x, static_cast<int>(focusPoint.X - Constants::SCREEN_WIDTH / 2.f), static_cast<float>(time - previousTime) * .05f);
|
||||
if ((focusPoint.X - Constants::SCREEN_WIDTH / 2.f) - static_cast<float>(viewport.x) <= 0.005f)
|
||||
{
|
||||
viewport.x = static_cast<int>(focusPoint.X - Constants::SCREEN_WIDTH / 2.f)/scale;
|
||||
}
|
||||
viewport.y = Utils::Lerp(viewport.y, static_cast<int>(focusPoint.Y - Constants::SCREEN_HEIGHT / 2.f), static_cast<float>(time - previousTime) * .05f);
|
||||
if (focusPoint.Y - static_cast<float>(Constants::SCREEN_HEIGHT) / 2.0f - static_cast<float>(viewport.y) <= 0.005f)
|
||||
{
|
||||
viewport.y = static_cast<int>(focusPoint.Y - Constants::SCREEN_HEIGHT / 2.f) / scale;
|
||||
}
|
||||
if (viewport.x < 0)
|
||||
viewport.x = 0;
|
||||
if (viewport.y < 0)
|
||||
viewport.y = 0;
|
||||
if (viewport.x > MapWidth - static_cast<int>(static_cast<float>(viewport.w) / scale))
|
||||
viewport.x = MapWidth - static_cast<int>(static_cast<float>(viewport.w) / scale);
|
||||
if (viewport.y > MapHeight - static_cast<int>(static_cast<float>(viewport.h) / scale))
|
||||
viewport.y = MapHeight - static_cast<int>(static_cast<float>(viewport.h) / scale);
|
||||
|
||||
//printf("\rp1(%f, %f), p2(%f, %f), viewport:(%d, %d, %d, %d), map(%d, %d), focus(%f, %f)", playerOnePosition.X * scale, playerOnePosition.Y * scale, playerTwoPosition.X * scale, playerTwoPosition.Y * scale, static_cast<int>(viewport.x * scale), static_cast<int>(viewport.y * scale), static_cast<int>(static_cast<float>(viewport.w) / scale), static_cast<int>(static_cast<float>(viewport.h) / scale), MapWidth, MapHeight, focusPoint.X, focusPoint.Y);
|
||||
for (auto& circle : Circles)
|
||||
circle.CollisionDetectionWithMapStep(map);
|
||||
|
||||
for (auto& circle : Circles)
|
||||
circle.MovementStep(static_cast<float>(time - previousTime) / 1000.f);
|
||||
|
||||
//Clear screen
|
||||
SDL_SetRenderDrawColor(Renderer, 0, 0xFF, 0, 0xFF);
|
||||
SDL_RenderClear(Renderer);
|
||||
|
||||
|
||||
|
||||
for (auto& tile : Tiles)
|
||||
tile.Render(Renderer, TileTextures, viewport, scale);
|
||||
|
||||
PlayerTexture.Render(Renderer, playerOnePosition.X - viewport.x, playerOnePosition.Y - viewport.y, nullptr, scale);
|
||||
PlayerTexture2.Render(Renderer, playerTwoPosition.X - viewport.x, playerTwoPosition.Y - viewport.y, nullptr, scale);
|
||||
for (auto& circle : Circles)
|
||||
circle.Render(Renderer);
|
||||
|
||||
//Update screen
|
||||
SDL_RenderPresent(Renderer);
|
||||
|
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
#include "KTexture.h"
|
||||
#include <vector>
|
||||
#include <SDL_joystick.h>
|
||||
#include <SDL_render.h>
|
||||
|
||||
#include "KCircle.h"
|
||||
#include "KInput.h"
|
||||
|
||||
|
||||
namespace KapitanGame {
|
||||
class KTile;
|
||||
|
||||
class KGame
|
||||
{
|
||||
@ -24,15 +24,13 @@ namespace KapitanGame {
|
||||
|
||||
SDL_Renderer* Renderer = nullptr;
|
||||
|
||||
KTexture TileTextures[4];
|
||||
KTexture PlayerTexture;
|
||||
KTexture PlayerTexture2;
|
||||
std::vector<KTile> Tiles;
|
||||
KTexture CircleTexture;
|
||||
|
||||
int MapHeight = -1;
|
||||
int MapWidth = -1;
|
||||
std::vector<KCircle> Circles;
|
||||
KInput Input;
|
||||
|
||||
bool HasSeparation;
|
||||
bool HasCollision;
|
||||
private:
|
||||
bool LoadMedia();
|
||||
|
||||
SDL_Texture* LoadTexture(const std::string& path) const;
|
||||
|
@ -9,6 +9,11 @@ namespace KapitanGame {
|
||||
KVector2D(const float x, const float y) : X(x), Y(y) {}
|
||||
|
||||
float Length() const { return sqrt(X * X + Y * Y); }
|
||||
float Length2() const { return X * X + Y * Y; }
|
||||
|
||||
bool operator==(const KVector2D& v2) const {
|
||||
return (*this - v2).Length2() < FLT_EPSILON * FLT_EPSILON;
|
||||
}
|
||||
|
||||
KVector2D operator+(const KVector2D& v2) const {
|
||||
return { X + v2.X, Y + v2.Y };
|
||||
@ -49,6 +54,12 @@ namespace KapitanGame {
|
||||
Y /= scalar;
|
||||
return *this;
|
||||
}
|
||||
float DotProduct(const KVector2D& v2) const {
|
||||
return DotProduct(*this, v2);
|
||||
}
|
||||
KVector2D Reflect(const KVector2D& normal) const {
|
||||
return Reflect(normal, *this);
|
||||
}
|
||||
|
||||
void Normalize() {
|
||||
const float l = Length();
|
||||
@ -56,6 +67,14 @@ namespace KapitanGame {
|
||||
(*this) *= 1 / l;
|
||||
}
|
||||
}
|
||||
|
||||
static KVector2D Reflect(const KVector2D& normal, const KVector2D& vector) {
|
||||
const float dn = 2 * vector.DotProduct(normal);
|
||||
return vector - normal * dn;
|
||||
}
|
||||
static float DotProduct(const KVector2D& v1, const KVector2D& v2) {
|
||||
return v1.X * v2.X + v1.Y * v2.Y ;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
16
2dgk_6/2dgk_6/Utils.cpp
Normal file
16
2dgk_6/2dgk_6/Utils.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <random>
|
||||
|
||||
namespace KapitanGame {
|
||||
namespace Utils {
|
||||
double RandomNumber() {
|
||||
// Making rng static ensures that it stays the same
|
||||
// Between different invocations of the function
|
||||
static std::default_random_engine rng(make_default_random_engine());
|
||||
|
||||
std::uniform_real_distribution<double> dist(0.0, 1.0);
|
||||
return dist(rng);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <random>
|
||||
namespace KapitanGame {
|
||||
namespace Utils {
|
||||
|
||||
@ -16,15 +17,37 @@ namespace KapitanGame {
|
||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
||||
}
|
||||
template <class T>
|
||||
constexpr const T& Clamp(const T& x)
|
||||
constexpr const T& Clamp01(const T& x)
|
||||
{
|
||||
return std::max(std::min(1.f, x), 0.f);
|
||||
return Clamp(x, 0.f, 1.f);
|
||||
}
|
||||
template <class T>
|
||||
constexpr const T& Clamp(const T& x, const T& min, const T& max)
|
||||
{
|
||||
return std::max(std::min(max, x), min);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr const T& Lerp(const T& a, const T& b, const float& t)
|
||||
{
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
static std::default_random_engine make_default_random_engine()
|
||||
{
|
||||
// This gets a source of actual, honest-to-god randomness
|
||||
std::random_device source;
|
||||
|
||||
// Here, we fill an array of random data from the source
|
||||
unsigned int random_data[10];
|
||||
for (auto& elem : random_data) {
|
||||
elem = source();
|
||||
}
|
||||
|
||||
// this creates the random seed sequence out of the random data
|
||||
std::seed_seq seq(random_data + 0, random_data + 10);
|
||||
return std::default_random_engine{ seq };
|
||||
}
|
||||
|
||||
double RandomNumber();
|
||||
}
|
||||
}
|
BIN
2dgk_6/2dgk_6/textures/00.bmp
(Stored with Git LFS)
BIN
2dgk_6/2dgk_6/textures/00.bmp
(Stored with Git LFS)
Binary file not shown.
BIN
2dgk_6/2dgk_6/textures/01.bmp
(Stored with Git LFS)
BIN
2dgk_6/2dgk_6/textures/01.bmp
(Stored with Git LFS)
Binary file not shown.
BIN
2dgk_6/2dgk_6/textures/02.bmp
(Stored with Git LFS)
BIN
2dgk_6/2dgk_6/textures/02.bmp
(Stored with Git LFS)
Binary file not shown.
BIN
2dgk_6/2dgk_6/textures/03.bmp
(Stored with Git LFS)
BIN
2dgk_6/2dgk_6/textures/03.bmp
(Stored with Git LFS)
Binary file not shown.
BIN
2dgk_6/2dgk_6/textures/player.bmp
(Stored with Git LFS)
BIN
2dgk_6/2dgk_6/textures/player.bmp
(Stored with Git LFS)
Binary file not shown.
BIN
2dgk_6/2dgk_6/textures/player2.bmp
(Stored with Git LFS)
BIN
2dgk_6/2dgk_6/textures/player2.bmp
(Stored with Git LFS)
Binary file not shown.
Loading…
Reference in New Issue
Block a user