added seminar factory

master
nihonium 2 years ago
parent 70f4290b3c
commit 611dca5dcc
No known key found for this signature in database
GPG Key ID: 0251623741027CFC

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 2.8.0)
project(skilltree)
# Найдём библиотеку SFML в системе
find_package(SFML 2.5 REQUIRED graphics window system)
# Создадим исполняемый файл по имени player_movement из исходных файлов
add_executable(skilltree src/skilltree.cpp)
# Укажем, что нужно использовать стандарт C++20
target_compile_features(skilltree PRIVATE cxx_std_20)
# Подключим библиотеку SFML к нашему проекту
target_link_libraries(skilltree PRIVATE sfml-graphics sfml-system sfml-window)
file(COPY src/icons DESTINATION .)

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@ -0,0 +1,35 @@
#pragma once
#include <SFML/Graphics.hpp>
class sfLine
{
public:
sfLine(const sf::Vector2f& point1, const sf::Vector2f& point2, sf::Color color, float thickness):
color(color), thickness(thickness)
{
sf::Vector2f direction = point2 - point1;
sf::Vector2f unitDirection = direction/std::sqrt(direction.x*direction.x+direction.y*direction.y);
sf::Vector2f unitPerpendicular(-unitDirection.y,unitDirection.x);
sf::Vector2f offset = (thickness/2.f)*unitPerpendicular;
vertices[0].position = point1 + offset;
vertices[1].position = point2 + offset;
vertices[2].position = point2 - offset;
vertices[3].position = point1 - offset;
for (int i=0; i<4; ++i)
vertices[i].color = color;
}
void draw(sf::RenderTarget &target) const
{
target.draw(vertices, 4, sf::Quads);
}
private:
sf::Vertex vertices[4];
float thickness;
sf::Color color;
};

@ -0,0 +1,405 @@
#include <SFML/Graphics.hpp>
#include <cmath>
#include <vector>
#include <string>
#include <memory>
#include "sfline.hpp"
#include <iostream>
using std::cout, std::endl;
/*
Icons from Ken111
https://www.flaticon.com/ru/packs/game-skill?k=1650700359068
*/
class Node
{
public:
Node(sf::Vector2f& position)
: mPosition{position}
{
}
enum class State
{
Blocked,
Unblocked,
Activated
};
void addChild(const std::shared_ptr<Node>& child)
{
mChildren.push_back(child);
}
sf::Vector2f getPosition()
{
return mPosition;
}
void unblock()
{
mState = State::Unblocked;
}
void block()
{
mState = State::Blocked;
for (const auto& child : mChildren)
child->block();
}
virtual bool collisionTest(sf::Vector2f mouseCoords) = 0;
void onMousePressed(sf::Vector2f mouseCoords)
{
if (mState == State::Blocked)
return;
if (collisionTest(mouseCoords))
{
if (mState == State::Unblocked)
{
mState = State::Activated;
for (const auto& child : mChildren)
child->unblock();
}
else if (mState == State::Activated)
{
mState = State::Unblocked;
for (const auto& child : mChildren)
child->block();
}
}
for (const auto& child : mChildren)
{
child->onMousePressed(mouseCoords);
}
}
virtual void draw(sf::RenderWindow& window) const = 0;
protected:
sf::Vector2f mPosition {0, 0};
State mState = State::Blocked;
std::vector<std::shared_ptr<Node>> mChildren {};
inline static sf::Color sBlockedColor {40, 40, 40};
inline static sf::Color sUnlockedColor {80, 80, 40};
inline static sf::Color sActivatedColor {160, 160, 40};
};
class HitNode : public Node
{
public:
HitNode(sf::Vector2f position)
: Node{position}
{
}
virtual sf::String getIconPath() = 0;
void loadTexture()
{
sf::String texturePath = getIconPath();
if (!mTexture.loadFromFile(texturePath))
{
cout << "Error! Can't load file " << texturePath.toAnsiString() << endl;
std::exit(1);
}
mSprite.setTexture(mTexture);
mSprite.setOrigin({mRadius, mRadius});
mSprite.setPosition(mPosition);
}
sf::Color getCurrentColor() const
{
if (mState == State::Unblocked)
return sUnlockedColor;
else if (mState == State::Activated)
return sActivatedColor;
return sBlockedColor;
}
void draw(sf::RenderWindow& window) const
{
for (const auto& el : mChildren)
{
sfLine connectionLine {mPosition, el->getPosition(), getCurrentColor(), 2};
connectionLine.draw(window);
el->draw(window);
}
static sf::CircleShape shape(mRadius);
shape.setOrigin({mRadius, mRadius});
shape.setFillColor(getCurrentColor());
shape.setPosition(mPosition);
window.draw(shape);
window.draw(mSprite);
}
bool collisionTest(sf::Vector2f mouseCoords) override
{
sf::Vector2f d = mPosition - mouseCoords;
return d.x * d.x + d.y * d.y < mRadius * mRadius;
}
private:
sf::Texture mTexture;
sf::Sprite mSprite;
float mRadius = 24;
bool mIsActivated = false;
};
class BombSkillNode : public HitNode
{
public:
BombSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_bomb.png"};
}
};
class SpikesSkillNode : public HitNode
{
public:
SpikesSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_spikes.png"};
}
};
class LightningSkillNode : public HitNode
{
public:
LightningSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_lightning.png"};
}
};
class EyeSkillNode : public HitNode
{
public:
EyeSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_eye.png"};
}
};
class ClawsSkillNode : public HitNode
{
public:
ClawsSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_claws.png"};
}
};
class ShieldSkillNode : public HitNode
{
public:
ShieldSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_shield.png"};
}
};
class SwordSkillNode : public HitNode
{
public:
SwordSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_sword.png"};
}
};
class ShurikenSkillNode : public HitNode
{
public:
ShurikenSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_shuriken.png"};
}
};
class WindSkillNode : public HitNode
{
public:
WindSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_shuriken.png"};
}
};
class MeteoriteSkillNode : public HitNode
{
public:
MeteoriteSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_meteorite.png"};
}
};
class HandSkillNode : public HitNode
{
public:
HandSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_hand.png"};
}
};
class EarthquakeSkillNode : public HitNode
{
public:
EarthquakeSkillNode(sf::Vector2f position) : HitNode{position}
{
loadTexture();
}
sf::String getIconPath() override
{
return sf::String{"icons/icon_earthquake.png"};
}
};
std::shared_ptr<Node> createSkillTree()
{
std::shared_ptr<Node> root {new LightningSkillNode({400, 500})};
std::shared_ptr<Node> a {new ShurikenSkillNode({200, 400})};
std::shared_ptr<Node> b {new BombSkillNode({400, 400})};
std::shared_ptr<Node> c {new EyeSkillNode({600, 400})};
root->addChild(a);
root->addChild(b);
root->addChild(c);
a->addChild(std::shared_ptr<Node>{new ShieldSkillNode({100, 200})});
a->addChild(std::shared_ptr<Node>{new SwordSkillNode({200, 200})});
a->addChild(std::shared_ptr<Node>{new EarthquakeSkillNode({300, 200})});
b->addChild(std::shared_ptr<Node>{new HandSkillNode({400, 200})});
b->addChild(std::shared_ptr<Node>{new MeteoriteSkillNode({500, 200})});
std::shared_ptr<Node> e {new BombSkillNode({600, 200})};
b->addChild(e);
e->addChild(std::shared_ptr<Node>{new WindSkillNode({500, 100})});
e->addChild(std::shared_ptr<Node>{new SwordSkillNode({600, 100})});
c->addChild(std::shared_ptr<Node>{new EyeSkillNode({700, 200})});
return root;
}
int main()
{
sf::ContextSettings settings;
settings.antialiasingLevel = 8;
sf::RenderWindow window(sf::VideoMode(1000, 800), "Skill Tree", sf::Style::Close, settings);
window.setFramerateLimit(60);
std::shared_ptr<Node> root = createSkillTree();
root->unblock();
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::MouseButtonPressed)
{
sf::Vector2f mouseCoords = window.mapPixelToCoords({event.mouseButton.x, event.mouseButton.y});
root->onMousePressed(mouseCoords);
}
}
window.clear(sf::Color::Black);
root->draw(window);
window.display();
}
return 0;
}

@ -0,0 +1,75 @@
/*
Задача:
В данном примере написана функция шаблонная getMaxId, которая находит максимум из чисел в векторе.
При этом вычисления проходят однопоточно.
Вам нужно написать шаблонную функцию
size_t getMaxIdPar(int n, RandIt start, RandIt finish)
которая будет делать то же самое, но только использовать для этого n потоков.
Проверить, что эта функция будет работать и для других контейнеров и типов хранящихся в них данных.
Например, для:
std::deque<double> d {1.2, 5.1, 8.2, 1.0, 0.2, 5.0, 7.8};
*/
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <random>
#include <algorithm>
#include <cstdint>
using std::cout, std::endl, std::size_t;
using namespace std::chrono_literals;
template <typename RandIt>
size_t getMaxId(RandIt start, RandIt finish)
{
RandIt maxIt = start;
for (auto it = start; it != finish; ++it)
{
if (*it > *maxIt)
maxIt = it;
}
return maxIt - start;
}
int main()
{
cout << "Generating numbers!" << endl;
std::vector<uint64_t> numbers(5e8);
numbers[0] = 123456789;
for (size_t i = 1; i < numbers.size(); ++i)
{
numbers[i] = numbers[i - 1] * i + 1;
}
cout << "Numbers generated!" << endl;
auto start = std::chrono::high_resolution_clock::now();
size_t id = getMaxId(numbers.begin(), numbers.end());
cout << "Maximum = " << numbers[id] << endl;
auto end = std::chrono::high_resolution_clock::now();
cout << "Time to calclulate max = " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< " milliseconds." << endl;
}

@ -0,0 +1,9 @@
/*
Задача:
Напишите шаблонную функцию parallelTransform, аналог функции std::transform
из библиотеки algorithm.
Количество потоков в этот раз не передавайте через аргументы функции, а узнайте
внутри самой функции с помощью std::thread::hardware_concurrency().
*/