完整代码如下:// main.cpp
#include <SFML/Graphics.hpp>
#include "threads.h"
DistributeThread threads;
class Main
{
public:
double view_direction[2] = {0, 0};
double player_position[3] = {0, 0, 0};
sf::RenderWindow *window = nullptr;
sf::RenderWindow *window_log = nullptr;
sf::Event event;
void control()
{
while (this->window->pollEvent(event))
{
switch (event.type)
{
case sf::Event::KeyPressed:
if (event.key.control)
{
switch (event.key.code)
{
case sf::Keyboard::L:
if (this->window_log == nullptr)
{
this->window_log->setVisible(true);
}
break;
};
};
break;
case sf::Event::Closed:
this->window->close();
threads.stop();
break;
};
};
};
void init()
{
this->window = new sf::RenderWindow(sf::VideoMode(1000, 1000), "Minecraft for C");
this->window_log = new sf::RenderWindow(sf::VideoMode(1000, 1000), "Minecraft for C");
this->window_log->setVisible(false);
};
};
int main()
{
Main system;
threads.work("Control", std::bind(Main::init, &system));
threads.repeat_work("Control", 50, std::bind(Main::control, &system));
if (threads.start())
{
threads.join();
};
return 0;
};
// math.cpp
#include <cmath>
#include "math.h"
#include "constants.hpp"
double radian(const double theta){
return theta * (constants::pi / 180);
};
Matrix::Matrix(const Matrix &item) : Matrix(item.dimensions, item.values)
{};
Matrix::Matrix(Matrix &&item)
{
this->dimensions[0] = item.dimensions[0];
this->dimensions[1] = item.dimensions[1];
this->values = item.values;
item.values = nullptr;
};
Matrix::Matrix(const unsigned short dimensions[2])
{
this->dimensions[0] = dimensions[0];
this->dimensions[1] = dimensions[1];
this->values = new double[dimensions[0] * dimensions[1]]();
};
Matrix::Matrix(const unsigned short dimensions[2], const double *values) : Matrix(dimensions)
{
for (unsigned int ptr_offset = 0; ptr_offset < dimensions[0] * dimensions[1]; ptr_offset++)
{
*(this->values + ptr_offset) = *(values + ptr_offset);
};
};
Matrix::~Matrix()
{
if (this->values != nullptr)
{
delete[] this->values;
};
};
Matrix Matrix::operator+(const Matrix &other) const
{
if (this->dimensions[0] != other.dimensions[0] || this->dimensions[1] != other.dimensions[1])
{
throw errors::MatrixDimensionError();
};
Matrix result(*this);
for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
{
*(result.values + ptr_offset) += *(other.values + ptr_offset);
};
return result;
};
Matrix Matrix::operator+(const double other) const
{
Matrix result(*this);
for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
{
*(result.values + ptr_offset) += other;
};
return result;
};
Matrix Matrix::operator-() const
{
Matrix result(*this);
for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
{
*(result.values + ptr_offset) += -*(result.values + ptr_offset);
};
return result;
};
Matrix Matrix::operator-(const Matrix &other) const
{
Matrix reversed = -other;
return *this + reversed;
};
Matrix Matrix::operator-(const double other) const
{
return *this + -other;
};
Matrix Matrix::operator*(const Matrix &other) const
{
if (this->dimensions[1] != other.dimensions[0])
{
throw errors::MatrixDimensionError();
};
unsigned short result_dimensions[2] = {this->dimensions[0], other.dimensions[1]};
Matrix result(result_dimensions);
int result_ptr_offset, this_ptr_offset, other_ptr_offset;
for (short result_row = 0; result_row < result_dimensions[0]; result_row++)
{
for (short result_column = 0; result_column < result_dimensions[1]; result_column++)
{
result_ptr_offset = result_row * result_dimensions[1] + result_column;
for (short index = 0; index < this->dimensions[1]; index++)
{
this_ptr_offset = result_row * this->dimensions[1] + index;
other_ptr_offset = index * other.dimensions[1] + result_column;
*(result.values + result_ptr_offset) += *(this->values + this_ptr_offset) * *(other.values + other_ptr_offset);
};
};
};
return result;
};
Vector Matrix::operator*(const Vector &other) const
{
unsigned short vector_matrix_dimensions[2] = {other.dimensions, 1};
Matrix vector_matrix(vector_matrix_dimensions, other.values);
Matrix result_matrix = *this * vector_matrix;
Vector result = Vector(result_matrix.dimensions[0], result_matrix.values);
return result;
};
Matrix Matrix::operator*(const double other) const
{
Matrix result(*this);
for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
{
*(result.values + ptr_offset) *= other;
};
return result;
};
Matrix Matrix::operator/(const double other) const
{
return *this * (1.0 / other);
};
Matrix Matrix::transpose() const
{
Matrix result(this->dimensions);
unsigned short row, column;
for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
{
row = ptr_offset / this->dimensions[1];
column = ptr_offset % this->dimensions[1];
*(result.values + column + row * this->dimensions[1]) = *(this->values + ptr_offset);
};
return result;
};
Vector::Vector(const Vector &item) : Vector(item.dimensions, item.values)
{};
Vector::Vector(const unsigned short dimensions, const double values[])
{
this->dimensions = dimensions;
this->values = new double[dimensions]();
for (unsigned short index = 0; index < dimensions; index++)
{
this->values[index] = values[index];
};
};
Vector::Vector(Vector &&item)
{
this->dimensions = item.dimensions;
this->values = item.values;
item.values = nullptr;
};
Vector::~Vector()
{
if (this->values != nullptr)
{
delete[] this->values;
};
};
Vector Vector::operator+(const Vector &other) const
{
if (this->dimensions != other.dimensions)
{
throw errors::VectorDimensionError();
};
Vector result(*this);
for (unsigned short index = 0; index < this->dimensions; index++)
{
result.values[index] += other.values[index];
};
return result;
};
Vector Vector::operator+(const double other) const
{
Vector result(*this);
for (unsigned short index = 0; index < this->dimensions; index++)
{
result.values[index] += other;
};
return result;
};
Vector Vector::operator-() const
{
Vector result = *this;
for (unsigned short index = 0; index < this->dimensions; index++)
{
result.values[index] = -result.values[index];
};
return result;
};
Vector Vector::operator-(const Vector &other) const
{
Vector reversed = -other;
return *this + reversed;
};
Vector Vector::operator-(const double other) const
{
return *this + -other;
};
Vector Vector::operator*(const Vector &other) const
{
if (this->dimensions != 3 || other.dimensions != 3)
{
throw errors::VectorDimensionError();
};
Vector result(*this);
for (unsigned short index = 0; index < this->dimensions; index++)
{
result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
};
return result;
};
Vector Vector::operator*(const double other) const
{
Vector result(*this);
for (unsigned short index = 0; index < this->dimensions; index++)
{
result.values[index] *= other;
};
return result;
};
Vector Vector::operator/(const double other) const
{
return *this * (1.0 / other);
};
double Vector::dot(const Vector &other) const
{
if (this->dimensions != other.dimensions)
{
throw errors::VectorDimensionError();
};
double result = 0;
for (unsigned short index = 0; index < this->dimensions; index++)
{
result += this->values[index] * other.values[index];
};
return result;
};
double Vector::length() const
{
double result_squared = 0;
for (unsigned short index = 0; index < this->dimensions; index++)
{
result_squared += this->values[index] * this->values[index];
};
return sqrt(result_squared);
};
Vector Vector::length(const int scale) const
{
return *this / (this->length() * scale);
};
double Vector::angle(const Vector &other) const
{
return acos(this->dot(other) / (this->length() * other.length()));
};
// threads.cpp
#include <unistd.h>
#include <iostream>
#include "threads.h"
BasicThread::BasicThread(const char* name)
{
this->name.assign(name);
this->state = choices::state_free;
this->thread = new std::thread(&BasicThread::run, this);
};
choices::state BasicThread::get_state()
{
return this->state;
};
[[nodiscard]]
std::unique_lock<std::mutex> * BasicThread::pause()
{
this->state = choices::state_paused;
std::unique_lock<std::mutex> *lock = new std::unique_lock<std::mutex>(this->mutex);
return lock;
};
void BasicThread::resume(std::unique_lock<std::mutex> &lock)
{
lock.unlock();
this->alarm.notify_all();
};
void BasicThread::run()
{
this->lock = new std::unique_lock<std::mutex>(this->mutex);
this->lock->unlock();
std::function<void ()> function;
while (this->running)
{
this->state = choices::state_running;
if (this->queue.empty())
{
this->sleep();
}
else
{
function = queue.front();
if (function)
function();
this->queue.pop();
};
};
delete this->lock;
};
void BasicThread::sleep()
{
this->state = choices::state_free;
this->alarm.wait(*this->lock);
};
void BasicThread::stop()
{
this->running = false;
this->alarm.notify_all();
this->thread->join();
this->state = choices::state_stopped;
};
void BasicThread::work(std::function<void ()> function)
{
this->queue.push(function);
this->alarm.notify_all();
};
BasicThread * DistributeThread::create(const char* name)
{
std::string name_string = name;
if (this->threads.find(name_string) != this->threads.end())
{
throw errors::ThreadExistError();
};
BasicThread *new_thread = new BasicThread(name);
this->threads[name_string] = new_thread;
this->locks[name_string] = std::unique_lock<std::mutex>(new_thread->mutex);
this->locks[name_string].unlock();
return new_thread;
};
bool DistributeThread::start()
{
if (this->plans.empty())
{
return false;
};
this->thread = new std::thread(DistributeThread::run, this);
return true;
};
BasicThread * DistributeThread::get(const char *thread_name)
{
std::string thread_string = thread_name;
if (this->threads.find(thread_string) == this->threads.end())
{
return this->create(thread_name);
}
else
{
return this->threads[thread_string];
};
};
void DistributeThread::join()
{
this->thread->join();
};
void DistributeThread::repeat_work(const char* thread_name, unsigned int delay, std::function<void ()> function)
{
plan new_plan;
new_plan.delay = delay;
new_plan.function = function;
new_plan.thread = this->get(thread_name);
this->plans[last_id] = new_plan;
this->queue.push(queue_item(delay, last_id));
last_id++;
};
void DistributeThread::run()
{
queue_item function;
plan function_plan;
while (this->running)
{
function = this->queue.top();
if (function.first > this->game_time)
{
sleep((function.first - this->game_time) / 1000); // Change milliseconds into seconds
this->game_time = function.first;
continue;
};
this->queue.pop();
function_plan = this->plans[function.second];
function_plan.thread->work(function_plan.function);
this->queue.push(queue_item(function.first + function_plan.delay, function.second));
};
};
void DistributeThread::stop()
{
this->running = false;
for (auto iterator : this->threads)
{
iterator.second->stop();
};
this->thread->join();
};
void DistributeThread::work(const char* thread_name, std::function<void ()> function)
{
this->get(thread_name)->work(function);
};
// math.h
#pragma once
double radian(const double);
class Vector
{
public:
unsigned short dimensions = 0;
double *values = nullptr;
Vector(const Vector &);
Vector(Vector &&);
Vector(const unsigned short, const double []);
~Vector();
Vector operator+(const Vector &) const;
Vector operator+(const double) const;
Vector operator-() const;
Vector operator-(const Vector &) const;
Vector operator-(const double) const;
Vector operator*(const Vector &) const;
Vector operator*(const double) const;
Vector operator/(const double) const;
double dot(const Vector &) const;
double length() const;
Vector length(const int) const;
double angle(const Vector &) const;
};
class Matrix
{
public:
unsigned short dimensions[2] = {0, 0};
double *values = nullptr; // "*" creates a ptr pointing at an array with two dimensions.
Matrix(const Matrix &);
Matrix(Matrix &&);
Matrix(const unsigned short [2]);
Matrix(const unsigned short [2], const double *); // "*" is actually a ptr pointing at the first element of an array with two dimensions.
~Matrix();
Matrix operator+(const Matrix &) const;
Matrix operator+(const double) const;
Matrix operator-() const;
Matrix operator-(const Matrix &) const;
Matrix operator-(const double) const;
Matrix operator*(const Matrix &) const;
Vector operator*(const Vector &) const;
Matrix operator*(const double) const;
Matrix operator/(const double) const;
Matrix transpose() const;
};
// threads.h
#include <condition_variable>
#include <functional>
#include <thread>
#include <map>
#include <mutex>
#include <queue>
#include <unordered_map>
#include "constants.hpp"
class BasicThread
{
friend class DistributeThread;
public:
std::string name = "Basic";
BasicThread(const char*);
choices::state get_state();
std::unique_lock<std::mutex> * pause();
void resume(std::unique_lock<std::mutex> &);
void stop();
protected:
std::condition_variable alarm;
std::unique_lock<std::mutex> *lock;
std::mutex mutex;
std::queue<std::function<void ()>> queue;
bool running = true;
choices::state state = choices::state_free;
std::thread *thread = nullptr;
void run();
void sleep();
public:
void work(std::function<void ()> function);
};
class DistributeThread
{
typedef std::pair<unsigned long long, unsigned int> queue_item;
struct plan
{
unsigned int delay;
std::function<void ()> function = nullptr;
BasicThread* thread;
};
public:
unsigned long long game_time = 0;
std::string name = "Distributor";
BasicThread * create(const char*);
BasicThread * get(const char*);
void join();
void repeat_work(const char* thread_name, unsigned int delay, std::function<void ()> function);
bool start();
void stop();
void work(const char* thread_name, std::function<void ()> function);
protected:
unsigned int last_id = 0;
std::unordered_map<std::string, std::unique_lock<std::mutex>> locks;
std::map<unsigned int, plan> plans;
std::priority_queue<queue_item, std::vector<queue_item>, std::greater<queue_item>> queue;
bool running = true;
std::unordered_map<std::string, BasicThread*> threads;
std::thread *thread = nullptr;
void run();
};
|