Add resource manager. Add tic tac toe board abstraction
This commit is contained in:
parent
9a16c6ca69
commit
56e4599ea1
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -16,19 +16,25 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_SQUARE_HPP
|
||||
#define OUR_DICK_SQUARE_HPP
|
||||
#ifndef OUR_DICK_BOARD_HPP
|
||||
#define OUR_DICK_BOARD_HPP
|
||||
|
||||
#include "graphics/mesh.hpp"
|
||||
#include "graphics/model.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/shader_program.hpp"
|
||||
#include "renderable.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
|
||||
#include "engine/object.hpp"
|
||||
#include "renderable.hpp"
|
||||
#include "engine/resource_manager.hpp"
|
||||
#include "math/vec.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <memory> //unique_ptr
|
||||
|
||||
gfx::unified_mesh square_mesh(const gfx::material& blank, const gfx::material& o, const gfx::material& x);
|
||||
|
||||
class square : public renderable_iface , public egn::object_base
|
||||
class tile : public renderable_iface, public egn::object_base
|
||||
{
|
||||
public:
|
||||
enum class value{
|
||||
@ -43,7 +49,7 @@ private:
|
||||
math::vec4<float> m_color_filter = {};
|
||||
|
||||
public:
|
||||
square(gfx::model* model);
|
||||
tile(gfx::model* model);
|
||||
|
||||
void set_value(value v);
|
||||
value get_value()const;
|
||||
@ -52,6 +58,32 @@ public:
|
||||
|
||||
void render(gfx::shader_program&)override;
|
||||
|
||||
|
||||
};
|
||||
class board : public renderable_iface, public egn::object_base
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<tile[]> m_tiles;
|
||||
public:
|
||||
board(egn::resource_manager& r);
|
||||
~board(void) = default;
|
||||
|
||||
tile::value check_winner(void)const;
|
||||
|
||||
bool is_full(void)const;
|
||||
|
||||
void render(gfx::shader_program& shader);
|
||||
|
||||
int click_collision_cheat(const math::vec3<GLfloat>&)const;
|
||||
|
||||
void set_tile(int index, tile::value value);
|
||||
tile::value get_tile(int index)const;
|
||||
|
||||
private:
|
||||
tile::value check_rows_(void)const;
|
||||
tile::value check_columns_(void)const;
|
||||
tile::value check_diagonals_(void)const;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -22,6 +22,7 @@
|
||||
#include "observable.hpp"
|
||||
#include "game_state.hpp"
|
||||
#include "graphics/window.hpp"
|
||||
#include "resource_manager.hpp"
|
||||
#include "input.hpp"
|
||||
|
||||
#include <queue>
|
||||
@ -33,6 +34,7 @@ namespace egn{
|
||||
protected:
|
||||
gfx::window m_window;
|
||||
game_state_manager m_states_manager;
|
||||
resource_manager m_res_manager;
|
||||
std::queue<input_event> m_event_queue;
|
||||
double m_last_time;
|
||||
|
||||
@ -48,6 +50,12 @@ namespace egn{
|
||||
|
||||
void on_notify(const game_state_event& e)override;
|
||||
|
||||
resource_manager& resource_man(void);
|
||||
const resource_manager& resource_man(void)const;
|
||||
|
||||
void push_state(std::unique_ptr<game_state_iface>&&);
|
||||
void pop_state(void);
|
||||
|
||||
private:
|
||||
void setup_window_();
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -28,6 +28,8 @@
|
||||
|
||||
namespace egn{
|
||||
|
||||
class game;
|
||||
|
||||
struct game_state_event {
|
||||
enum class state_type{
|
||||
SHOULD_CLOSE,
|
||||
@ -59,10 +61,10 @@ namespace egn{
|
||||
class game_state_iface
|
||||
{
|
||||
protected:
|
||||
game_state_manager* m_owner = nullptr;
|
||||
game* m_owner = nullptr;
|
||||
|
||||
protected:
|
||||
game_state_iface(game_state_manager* owner);
|
||||
game_state_iface(game* owner);
|
||||
game_state_iface(const game_state_iface& g) = default;
|
||||
game_state_iface(game_state_iface&& g) = default;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -16,10 +16,12 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_GRAPHICS_IMAGE_HPP
|
||||
#define OUR_DICK_GRAPHICS_IMAGE_HPP
|
||||
#ifndef OUR_DICK_ENGINE_IMAGE_HPP
|
||||
#define OUR_DICK_ENGINE_IMAGE_HPP
|
||||
|
||||
namespace gfx{
|
||||
#include <string>
|
||||
|
||||
namespace egn{
|
||||
|
||||
//class handling image loading from files
|
||||
class image
|
||||
@ -52,6 +54,27 @@ namespace gfx{
|
||||
unsigned char* data();
|
||||
};
|
||||
|
||||
class deferred_image
|
||||
{
|
||||
private:
|
||||
std::string m_filename;
|
||||
bool m_flip = false;
|
||||
int m_req_chan = 0;
|
||||
public:
|
||||
deferred_image(const char* file, bool flip = false, int req_chan = 0);
|
||||
deferred_image(const std::string& file, bool flip = false, int req_chan = 0);
|
||||
deferred_image(const deferred_image&) = default;
|
||||
deferred_image(deferred_image&&) = default;
|
||||
|
||||
~deferred_image(void) = default;
|
||||
|
||||
deferred_image& operator=(const deferred_image&) = default;
|
||||
deferred_image& operator=(deferred_image&&) = default;
|
||||
|
||||
operator image(void)const;
|
||||
image get_image(void)const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
78
include/engine/resource_manager.hpp
Normal file
78
include/engine/resource_manager.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_ENGINE_RESOURCE_MANAGER_HPP
|
||||
#define OUR_DICK_ENGINE_RESOURCE_MANAGER_HPP
|
||||
|
||||
#include "engine/image.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/model.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <utility> //pair, forward
|
||||
|
||||
namespace egn{
|
||||
|
||||
class resource_manager
|
||||
{
|
||||
private:
|
||||
std::map<const char*,gfx::material> m_textures;
|
||||
std::map<const char*,gfx::model> m_models;
|
||||
|
||||
public:
|
||||
resource_manager(void) = default;
|
||||
resource_manager(const resource_manager&) = default;
|
||||
resource_manager(resource_manager&&) = default;
|
||||
|
||||
~resource_manager(void) = default;
|
||||
|
||||
resource_manager& operator=(const resource_manager&) = default;
|
||||
resource_manager& operator=(resource_manager&&) = default;
|
||||
|
||||
bool has_material(const char* key)const;
|
||||
|
||||
template<class... Args>
|
||||
std::pair<gfx::material*,bool> emplace_material(const char* key, Args&&... args);
|
||||
gfx::material* get_material(const char* file);
|
||||
|
||||
bool has_model(const char* key)const;
|
||||
|
||||
template<class... Args>
|
||||
std::pair<gfx::model*,bool> emplace_model(const char* key, Args&&... args);
|
||||
gfx::model* get_model(const char* file);
|
||||
};
|
||||
|
||||
|
||||
template<class... Args>
|
||||
std::pair<gfx::material*,bool> resource_manager::emplace_material(const char* key, Args&&... args){
|
||||
if(auto it = m_textures.find(key);it != m_textures.end())
|
||||
return {&(*it).second, false};
|
||||
auto ret = m_textures.emplace(key, std::forward<Args>(args)...);
|
||||
return {&(*(ret.first)).second, true};
|
||||
}
|
||||
template<class... Args>
|
||||
std::pair<gfx::model*,bool> resource_manager::emplace_model(const char* key, Args&&... args){
|
||||
if(auto it = m_models.find(key);it != m_models.end())
|
||||
return {&(*it).second, false};
|
||||
auto ret = m_models.emplace(key, std::forward<Args>(args)...);
|
||||
return {&(*(ret.first)).second, true};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -19,7 +19,7 @@
|
||||
#ifndef OUR_DICK_GRAPHICS_TEXTURE_HPP
|
||||
#define OUR_DICK_GRAPHICS_TEXTURE_HPP
|
||||
|
||||
#include "image.hpp"
|
||||
#include "engine/image.hpp"
|
||||
#include "gl_include.hpp"
|
||||
#include "math/vec.hpp"
|
||||
|
||||
@ -88,7 +88,8 @@ namespace gfx{
|
||||
texture(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type);
|
||||
texture(GLenum format, GLsizei w, GLsizei h, GLenum type);
|
||||
//create the texture with image data from 'i'
|
||||
texture(const image& i);
|
||||
texture(const egn::image& i);
|
||||
texture(const egn::deferred_image& i);
|
||||
texture(const texture&) = delete;
|
||||
texture(texture&&);
|
||||
~texture();
|
||||
@ -99,7 +100,9 @@ namespace gfx{
|
||||
GLuint raw()const;
|
||||
|
||||
//overwrite the current image data with 'i'
|
||||
bool set_image(const image& i);
|
||||
bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type);
|
||||
bool set_image(const egn::image& i);
|
||||
bool set_image(const egn::deferred_image& i);
|
||||
|
||||
//change wrap mode for both x and y
|
||||
void set_wrap_mode(wrap w);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -30,7 +30,7 @@ private:
|
||||
egn::game_state_iface* m_under_state;
|
||||
|
||||
public:
|
||||
pause_state(egn::game_state_manager& owner, egn::game_state_iface* under);
|
||||
pause_state(egn::game& owner, egn::game_state_iface* under);
|
||||
|
||||
void enter();
|
||||
void leave();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -26,7 +26,6 @@
|
||||
#include "sprite_renderer.hpp"
|
||||
#include "screen_renderer.hpp"
|
||||
#include "engine/camera.hpp"
|
||||
#include "square.hpp"
|
||||
|
||||
class play_state : public egn::game_state_iface
|
||||
{
|
||||
@ -39,17 +38,12 @@ private:
|
||||
double m_last_time;
|
||||
|
||||
public:
|
||||
play_state(egn::game_state_manager& owner, int width, int height);
|
||||
play_state(egn::game& owner, int width, int height);
|
||||
void enter()override;
|
||||
void leave()override;
|
||||
void handle_input(const egn::input_event& events)override;
|
||||
void update(double time)override;
|
||||
void render()override;
|
||||
|
||||
private:
|
||||
square::value check_win_condition_();
|
||||
bool is_board_full_();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -19,7 +19,6 @@
|
||||
#ifndef OUR_DICK_SCENE_HPP
|
||||
#define OUR_DICK_SCENE_HPP
|
||||
|
||||
#include "square.hpp"
|
||||
#include "graphics/texture.hpp" //TODO: use material interface instead of direct texture
|
||||
#include "engine/camera.hpp"
|
||||
#include "renderable.hpp"
|
||||
@ -31,9 +30,7 @@
|
||||
struct scene {
|
||||
std::vector<renderable_iface*> renderables;
|
||||
std::vector<std::unique_ptr<egn::object_base>> objects;
|
||||
std::vector<gfx::material> textures;
|
||||
std::vector<std::unique_ptr<egn::camera_iface>> cameras;
|
||||
std::vector<std::unique_ptr<gfx::model>> models;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_UTIL_MINMAX_HPP
|
||||
#define OUR_DICK_UTIL_MINMAX_HPP
|
||||
|
||||
//prevents inclusion of <algorithm> which triples compile times
|
||||
|
||||
namespace util{
|
||||
|
||||
template<typename T>
|
||||
struct greater {
|
||||
constexpr bool operator()(const T& left, const T& right)const{
|
||||
return left > right;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct less {
|
||||
constexpr bool operator()(const T& left, const T& right)const{
|
||||
return left < right;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static constexpr const T& max(const T& left, const T& right, Args&&... args){
|
||||
if constexpr(sizeof...(args) > 0){
|
||||
return left > right ? max(left, std::forward<Args>(args)...) : max(right, std::forward<Args>(args)...);
|
||||
}
|
||||
return left > right ? left : right;
|
||||
}
|
||||
template<typename T, typename... Args>
|
||||
static constexpr const T& min(const T& left, const T& right, Args&&... args){
|
||||
if constexpr(sizeof...(args) > 0){
|
||||
return left < right ? min(left, std::forward<Args>(args)...) : min(right, std::forward<Args>(args)...);
|
||||
}
|
||||
return left < right ? left : right;
|
||||
}
|
||||
template<typename T, typename Compare>
|
||||
static constexpr T maxc(const T& left, const T& right, Compare cmp){
|
||||
return cmp(left, right) ? left : right;
|
||||
}
|
||||
template<typename T, typename Compare>
|
||||
static constexpr T minc(const T& left, const T& right, Compare cmp){
|
||||
return cmp(left, right) ? left : right;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,131 +0,0 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_UTIL_RING_BUFFER_HPP
|
||||
#define OUR_DICK_UTIL_RING_BUFFER_HPP
|
||||
|
||||
#include <vector> //vector (duh)
|
||||
#include <cstdlib> //size_t
|
||||
#include <atomic> //atomic (duh)
|
||||
|
||||
|
||||
#ifdef __cpp_lib_hardware_interference_size
|
||||
#include <new> //hardware_destructive_interference_size
|
||||
#endif
|
||||
|
||||
#ifndef __cpp_aligned_new
|
||||
//TODO: custom aligned allocator
|
||||
#error "Require aligned new allocation"
|
||||
#endif
|
||||
|
||||
namespace util{
|
||||
|
||||
//multiproducer, multiconsumer thread safe ring buffer with some attempts to optimize against thread thrashing
|
||||
template<typename T>
|
||||
class mpmc_ring_buffer
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using reference = value_type&;
|
||||
using rvalue_reference = value_type&&;
|
||||
using const_reference = const value_type&;
|
||||
|
||||
private:
|
||||
#if defined(__cpp_lib_hardware_interference_size)
|
||||
// libc++ bug
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=41423
|
||||
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 11000
|
||||
static constexpr size_t cacheline_size = std::hardware_destructive_interference_size;
|
||||
#else
|
||||
static constexpr size_t cacheline_size = 64;
|
||||
#endif
|
||||
#else
|
||||
//Best guess
|
||||
static constexpr size_t cacheline_size = 64;
|
||||
#endif
|
||||
|
||||
class slot
|
||||
{
|
||||
public:
|
||||
static constexpr size_type active_bit = 1;
|
||||
private:
|
||||
//ensure no false sharing with previous slot in queue
|
||||
alignas(cacheline_size) std::atomic<size_type> m_turn = {0};
|
||||
alignas(alignof(value_type)) unsigned char m_data[sizeof(value_type)] = {};
|
||||
//ensure no false sharing with following data
|
||||
char cachline_padding[cacheline_size - (sizeof(m_data) + sizeof(m_turn))];
|
||||
public:
|
||||
slot() = default;
|
||||
slot(const slot& s);
|
||||
slot(slot&& s);
|
||||
~slot();
|
||||
template<typename... Args>
|
||||
void construct(Args&&... args);
|
||||
void destruct();
|
||||
|
||||
const_reference get()const&;
|
||||
reference get()&;
|
||||
rvalue_reference get()&&;
|
||||
std::atomic<size_type>& turn();
|
||||
const std::atomic<size_type>& turn()const;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<slot> m_slots;
|
||||
//keep head and tail on separate cache lines to prevent thread thrashing
|
||||
alignas(cacheline_size) std::atomic<size_type> m_head;
|
||||
alignas(cacheline_size) std::atomic<size_type> m_tail;
|
||||
|
||||
public:
|
||||
explicit mpmc_ring_buffer(size_type capacity);
|
||||
//copy/move NOT thread safe! requires external locking mechanism!
|
||||
mpmc_ring_buffer(const mpmc_ring_buffer& m);
|
||||
constexpr mpmc_ring_buffer(mpmc_ring_buffer&& m);
|
||||
~mpmc_ring_buffer() = default;
|
||||
mpmc_ring_buffer& operator=(const mpmc_ring_buffer& m);
|
||||
constexpr mpmc_ring_buffer& operator=(mpmc_ring_buffer&& m);
|
||||
|
||||
//NOT thread safe! requires external locking mechanism!
|
||||
void resize(size_type newcap);
|
||||
//NOT thread safe! requires external locking mechanism!
|
||||
void clear();
|
||||
|
||||
template<typename... Args>
|
||||
void emplace(Args&&... args);
|
||||
template<typename... Args>
|
||||
bool try_emplace(Args&&... args);
|
||||
|
||||
void push(const_reference t);
|
||||
void push(rvalue_reference t);
|
||||
bool try_push(const_reference t);
|
||||
bool try_push(rvalue_reference t);
|
||||
|
||||
void pop(reference t);
|
||||
bool try_pop(reference t);
|
||||
private:
|
||||
constexpr size_type rotation_cnt(size_type t);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "ring_buffer.tpp"
|
||||
|
||||
#endif
|
||||
@ -1,217 +0,0 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_UTIL_RING_BUFFER_TPP
|
||||
#define OUR_DICK_UTIL_RING_BUFFER_TPP
|
||||
|
||||
#include <utility> //forward, move
|
||||
#include <atomic> //memory_order, atomic
|
||||
#include <cstring> //memcpy
|
||||
|
||||
namespace util{
|
||||
template<typename T>
|
||||
mpmc_ring_buffer<T>::slot::slot(const slot& s):
|
||||
m_turn(s.m_turn.load(std::memory_order_acquire))
|
||||
{
|
||||
memcpy(m_data, s.m_data, sizeof(s.m_data));
|
||||
}
|
||||
template<typename T>
|
||||
mpmc_ring_buffer<T>::slot::slot(slot&& s):
|
||||
m_turn(s.m_turn.load(std::memory_order_acquire))
|
||||
{
|
||||
memcpy(m_data, s.m_data, sizeof(s.m_data));
|
||||
}
|
||||
template<typename T>
|
||||
mpmc_ring_buffer<T>::slot::~slot(){
|
||||
if(m_turn & active_bit){
|
||||
destruct();
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
void mpmc_ring_buffer<T>::slot::construct(Args&&... args){
|
||||
new (&m_data) value_type(std::forward<Args>(args)...);
|
||||
}
|
||||
template<typename T>
|
||||
void mpmc_ring_buffer<T>::slot::destruct(){
|
||||
reinterpret_cast<pointer>(&m_data)->~value_type();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto mpmc_ring_buffer<T>::slot::get()const& -> const_reference{
|
||||
return reinterpret_cast<const_reference>(m_data);
|
||||
}
|
||||
template<typename T>
|
||||
auto mpmc_ring_buffer<T>::slot::get()& -> reference{
|
||||
return reinterpret_cast<reference>(m_data);
|
||||
}
|
||||
template<typename T>
|
||||
auto mpmc_ring_buffer<T>::slot::get()&& -> rvalue_reference{
|
||||
return std::move(reinterpret_cast<reference>(m_data));
|
||||
}
|
||||
template<typename T>
|
||||
auto mpmc_ring_buffer<T>::slot::turn() -> std::atomic<size_type>&{
|
||||
return m_turn;
|
||||
}
|
||||
template<typename T>
|
||||
auto mpmc_ring_buffer<T>::slot::turn()const -> const std::atomic<size_type>&{
|
||||
return m_turn;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
mpmc_ring_buffer<T>::mpmc_ring_buffer(size_type capacity):
|
||||
m_slots(capacity),
|
||||
m_head(0),
|
||||
m_tail(0){}
|
||||
|
||||
template<typename T>
|
||||
mpmc_ring_buffer<T>::mpmc_ring_buffer(const mpmc_ring_buffer& m):
|
||||
m_slots(m.m_slots),
|
||||
m_head(m.m_head.load()),
|
||||
m_tail(m.m_tail.load()){}
|
||||
template<typename T>
|
||||
constexpr mpmc_ring_buffer<T>::mpmc_ring_buffer(mpmc_ring_buffer&& m):
|
||||
m_slots(std::move(m.m_slots)),
|
||||
m_head(m.m_head.load()),
|
||||
m_tail(m.m_tail.load()){}
|
||||
template<typename T>
|
||||
mpmc_ring_buffer<T>& mpmc_ring_buffer<T>::operator=(const mpmc_ring_buffer& m){
|
||||
return (*this = mpmc_ring_buffer(m));
|
||||
}
|
||||
template<typename T>
|
||||
constexpr mpmc_ring_buffer<T>& mpmc_ring_buffer<T>::operator=(mpmc_ring_buffer&& m){
|
||||
std::swap(m_slots, m.m_slots);
|
||||
m_head = m.m_head.load();
|
||||
m_tail = m.m_tail.load();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void mpmc_ring_buffer<T>::resize(size_type newcap){
|
||||
mpmc_ring_buffer tmp(newcap);
|
||||
size_type max = (m_head - m_tail) < newcap ? (m_head - m_tail) : newcap;
|
||||
for(size_type i = m_tail, j = 0;j < max;++i, ++j){
|
||||
tmp.m_slots[j].get() = std::move(m_slots[i % m_slots.capacity()].get());
|
||||
tmp.m_slots[j].turn() |= 1; //in-use bit
|
||||
}
|
||||
tmp.m_head = max;
|
||||
tmp.m_tail = 0;
|
||||
*this = std::move(tmp);
|
||||
}
|
||||
template<typename T>
|
||||
void mpmc_ring_buffer<T>::clear(){
|
||||
size_type head = m_head.load(std::memory_order_acquire);
|
||||
for(size_type i = m_tail;i < head;++i){
|
||||
m_slots[i].destruct();
|
||||
m_slots[i].turn().store(0, std::memory_order_release);
|
||||
}
|
||||
m_head.store(0, std::memory_order_release);
|
||||
m_tail.store(0, std::memory_order_release);
|
||||
}
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
void mpmc_ring_buffer<T>::emplace(Args&&... args){
|
||||
const size_type head = m_head.fetch_add(1, std::memory_order_seq_cst);
|
||||
slot& s = m_slots[head % m_slots.capacity()];
|
||||
//lsb is in-use flag. wait for it to be 0
|
||||
while(rotation_cnt(head) << 1 != s.turn().load(std::memory_order_acquire));
|
||||
|
||||
s.construct(std::forward<Args>(args)...);
|
||||
//set in-use flag
|
||||
s.turn().store((rotation_cnt(head) << 1) + 1, std::memory_order_release);
|
||||
}
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
bool mpmc_ring_buffer<T>::try_emplace(Args&&... args){
|
||||
size_type head = m_head.load(std::memory_order_acquire);
|
||||
while(1){
|
||||
slot& s = m_slots[head % m_slots.capacity()];
|
||||
if((rotation_cnt(head) << 1) == s.turn().load(std::memory_order_acquire)){
|
||||
if(m_head.compare_exchange_strong(head, head+1, std::memory_order_seq_cst)){
|
||||
s.construct(std::forward<Args>(args)...);
|
||||
s.turn().store((rotation_cnt(head) << 1) + 1, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
const size_type prev_head = head;
|
||||
head = m_head.load(std::memory_order_acquire);
|
||||
if(head == prev_head)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void mpmc_ring_buffer<T>::push(const_reference t){
|
||||
emplace(t);
|
||||
}
|
||||
template<typename T>
|
||||
bool mpmc_ring_buffer<T>::try_push(const_reference t){
|
||||
return try_emplace(t);
|
||||
}
|
||||
template<typename T>
|
||||
void mpmc_ring_buffer<T>::push(rvalue_reference t){
|
||||
emplace(std::move(t));
|
||||
}
|
||||
template<typename T>
|
||||
bool mpmc_ring_buffer<T>::try_push(rvalue_reference t){
|
||||
return try_emplace(std::move(t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void mpmc_ring_buffer<T>::pop(reference t){
|
||||
const size_type tail = m_tail.fetch_add(1, std::memory_order_seq_cst);
|
||||
slot& s = m_slots[tail % m_slots.capacity()];
|
||||
|
||||
//lsb is in-use flag. wait for it to be 1
|
||||
while((rotation_cnt(tail) << 1) + 1 != s.turn().load(std::memory_order_acquire));
|
||||
|
||||
t = std::move(s).get();
|
||||
s.destruct();
|
||||
s.turn().store((rotation_cnt(tail) << 1) + 2, std::memory_order_release);
|
||||
}
|
||||
template<typename T>
|
||||
bool mpmc_ring_buffer<T>::try_pop(reference t){
|
||||
size_type tail = m_tail.load(std::memory_order_acquire);
|
||||
while(1){
|
||||
slot& s = m_slots[tail % m_slots.capacity()];
|
||||
if((rotation_cnt(tail) << 1) + 1 == s.turn().load(std::memory_order_acquire)){
|
||||
if(m_tail.compare_exchange_strong(tail, tail+1, std::memory_order_seq_cst)){
|
||||
t = std::move(s).get();
|
||||
s.destruct();
|
||||
s.turn().store((rotation_cnt(tail) << 1) + 2, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
//if the tail hasn't moved, then we're still waiting on producer.
|
||||
//if it has moved, another consumer took our data. try again.
|
||||
const size_type prev_tail = tail;
|
||||
tail = m_tail.load(std::memory_order_acquire);
|
||||
if(tail == prev_tail)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
constexpr auto mpmc_ring_buffer<T>::rotation_cnt(size_type t) -> size_type{
|
||||
return (t / m_slots.capacity());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,37 +0,0 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_SEQUENCE_HPP
|
||||
#define OUR_DICK_SEQUENCE_HPP
|
||||
|
||||
#include <utility> //integer_sequence
|
||||
|
||||
namespace util{
|
||||
//generate an integer sequence counting up from 0. eg 0,1,2,3...
|
||||
template<int I, int... Is>
|
||||
struct sequence_gen{
|
||||
using type = typename sequence_gen<I-1, Is..., sizeof...(Is)>::type;
|
||||
};
|
||||
template<int... Is>
|
||||
struct sequence_gen<0,Is...>{
|
||||
using type = std::integer_sequence<int,Is...>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
4
makefile
4
makefile
@ -26,7 +26,7 @@ DEPDIR::=$(OBJDIR)/dep
|
||||
LIBDIRS::=lib
|
||||
INCLUDE_DIRS::=include
|
||||
CFLAGS::=-std=c18 -Wall -pedantic -Wextra
|
||||
CXXFLAGS::=-std=c++17 -Wall -pedantic -Wextra -fno-rtti -fno-exceptions
|
||||
CXXFLAGS::=-std=c++20 -Wall -pedantic -Wextra -fno-rtti -fno-exceptions
|
||||
DEBUG_CFLAGS::=
|
||||
DEBUG_CXXFLAGS::=-DOUR_DICK_DEBUG=2
|
||||
EXT::=cpp
|
||||
@ -41,7 +41,7 @@ ifneq ($(WINDOWS),1)
|
||||
#*nix settings
|
||||
CC::=gcc
|
||||
CXX::=g++
|
||||
LDLIBS::=-lglfw -lglad -ldl -lm -lportaudio -lsndfile -lpthread
|
||||
LDLIBS::=-lglfw -lglad -ldl -lm -lportaudio -lsndfile -lpthread -lrexy
|
||||
ifeq ($(shell uname -s),Linux)
|
||||
LDLIBS+=-lasound
|
||||
endif
|
||||
|
||||
209
src/board.cpp
Normal file
209
src/board.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2021rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "board.hpp"
|
||||
#include "math/mat.hpp"
|
||||
|
||||
#include "graphics/gl_include.hpp" //GLfloat
|
||||
|
||||
|
||||
gfx::unified_mesh square_mesh(const gfx::material& blank, const gfx::material& o, const gfx::material& x){
|
||||
static constexpr gfx::vertex s_vertices[] = {
|
||||
{{-1.0f, 1.0f, 0.0f}, {}, {0.0f, 1.0f}},
|
||||
{{-1.0f, -1.0f, 0.0f}, {}, {0.0f, 0.0f}},
|
||||
{{ 1.0f, -1.0f, 0.0f}, {}, {1.0f, 0.0f}},
|
||||
{{ 1.0f, -1.0f, 0.0f}, {}, {1.0f, 0.0f}},
|
||||
{{ 1.0f, 1.0f, 0.0f}, {}, {1.0f, 1.0f}},
|
||||
{{-1.0f, 1.0f, 0.0f}, {}, {0.0f, 1.0f}}
|
||||
};
|
||||
const gfx::material* mats[] = {&blank, &o, &x};
|
||||
|
||||
return gfx::unified_mesh{{s_vertices, sizeof(s_vertices) / sizeof(s_vertices[0])}, {mats, sizeof(mats) / sizeof(mats[0])}};
|
||||
}
|
||||
|
||||
|
||||
tile::tile(gfx::model* model):
|
||||
m_model(model){}
|
||||
|
||||
void tile::set_value(value t){
|
||||
m_active_value = t;
|
||||
}
|
||||
auto tile::get_value()const -> value{
|
||||
return m_active_value;
|
||||
}
|
||||
void tile::set_color(const math::vec4<float>& color){
|
||||
m_color_filter = color;
|
||||
}
|
||||
|
||||
void tile::render(gfx::shader_program& shader){
|
||||
shader.set_uniform("model_color", m_color_filter);
|
||||
shader.set_uniform("texture1", *m_model->mesh(0).material().get_material((int)m_active_value));
|
||||
m_model->mesh(0).vertex().render(shader);
|
||||
}
|
||||
|
||||
board::board(egn::resource_manager& resman):
|
||||
m_tiles(nullptr)
|
||||
{
|
||||
gfx::material* blank, *o, *x;
|
||||
gfx::model* sq;
|
||||
blank = resman.emplace_material("assets/images/blank.jpg", egn::deferred_image("assets/images/blank.jpg", true)).first;
|
||||
o = resman.emplace_material("assets/images/o.jpg", egn::deferred_image("assets/images/o.jpg", true)).first;
|
||||
x = resman.emplace_material("assets/images/x.jpg", egn::deferred_image("assets/images/x.jpg", true)).first;
|
||||
x = resman.emplace_material("assets/images/x.jpg", egn::deferred_image("assets/images/x.jpg", true)).first;
|
||||
|
||||
if(!resman.has_model("square")){
|
||||
sq = resman.emplace_model("square", square_mesh(*blank, *o, *x)).first;
|
||||
}else{
|
||||
sq = resman.get_model("square");
|
||||
}
|
||||
|
||||
|
||||
|
||||
m_tiles.reset(new tile[9]{sq, sq, sq, sq, sq, sq, sq, sq, sq});
|
||||
|
||||
m_tiles[0].set_position({-2.125, 2.125, -1});
|
||||
m_tiles[1].set_position({-2.125, 0, -1});
|
||||
m_tiles[2].set_position({-2.125, -2.125, -1});
|
||||
m_tiles[3].set_position({ 0, 2.125, -1});
|
||||
m_tiles[4].set_position({ 0, 0, -1});
|
||||
m_tiles[5].set_position({ 0, -2.125, -1});
|
||||
m_tiles[6].set_position({ 2.125, 2.125, -1});
|
||||
m_tiles[7].set_position({ 2.125, 0, -1});
|
||||
m_tiles[8].set_position({ 2.125, -2.125, -1});
|
||||
|
||||
}
|
||||
|
||||
void board::render(gfx::shader_program& shader){
|
||||
for(int i = 0;i < 9;++i){
|
||||
shader.set_uniform("model_mat", model_matrix() * m_tiles[i].model_matrix());
|
||||
m_tiles[i].render(shader);
|
||||
}
|
||||
}
|
||||
|
||||
bool board::is_full(void)const{
|
||||
for(size_t i = 0;i < 9;++i){
|
||||
if(m_tiles[i].get_value() == tile::value::BLANK)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int board::click_collision_cheat(const math::vec3<GLfloat>& unproj_3)const{
|
||||
math::vec4<GLfloat> unproj_4 = {unproj_3[0], unproj_3[1], unproj_3[2], 1};
|
||||
math::vec4<GLfloat> mod_coord = model_matrix().inverse() * unproj_4;
|
||||
mod_coord /= mod_coord[3];
|
||||
math::vec3<GLfloat> projected1 = {mod_coord[0], mod_coord[1], mod_coord[2]};
|
||||
|
||||
for(size_t i = 0;i < 9;++i){
|
||||
tile& sq = m_tiles[i];
|
||||
const math::vec3<GLfloat>& sq_pos = sq.position();
|
||||
if((projected1.x() > (sq_pos.x() - 1.0f) && projected1.x() < (sq_pos.x() + 1.0f)) &&
|
||||
(projected1.y() > (sq_pos.y() - 1.0f) && projected1.y() < (sq_pos.y() + 1.0f)))
|
||||
{
|
||||
debug_print_succ("Clicked on square %lu\n", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void board::set_tile(int index, tile::value value){
|
||||
m_tiles[index].set_value(value);
|
||||
}
|
||||
tile::value board::get_tile(int index)const{
|
||||
return m_tiles[index].get_value();
|
||||
}
|
||||
|
||||
tile::value board::check_winner(void)const{
|
||||
if(auto val = check_rows_();val != tile::value::BLANK)
|
||||
return val;
|
||||
if(auto val = check_columns_();val != tile::value::BLANK)
|
||||
return val;
|
||||
if(auto val = check_diagonals_();val != tile::value::BLANK)
|
||||
return val;
|
||||
|
||||
return tile::value::BLANK;
|
||||
}
|
||||
tile::value board::check_columns_(void)const{
|
||||
for(int i = 0;i < 3;++i){
|
||||
bool valid = true;
|
||||
auto& start_sq = m_tiles[i*3];
|
||||
if(start_sq.get_value() == tile::value::BLANK)
|
||||
continue;
|
||||
|
||||
for(int l = 1;l < 3;++l){
|
||||
auto& cur_sq = m_tiles[i*3 + l];
|
||||
if(cur_sq.get_value() != start_sq.get_value()){
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(valid)
|
||||
return start_sq.get_value();
|
||||
}
|
||||
return tile::value::BLANK;
|
||||
}
|
||||
tile::value board::check_rows_(void)const{
|
||||
|
||||
for(int i = 0;i < 3;++i){
|
||||
bool valid = true;
|
||||
auto& start_sq = m_tiles[i];
|
||||
if(start_sq.get_value() == tile::value::BLANK)
|
||||
continue;
|
||||
|
||||
for(int l = 1;l < 3;++l){
|
||||
auto& cur_sq = m_tiles[i + l*3];
|
||||
if(cur_sq.get_value() != start_sq.get_value()){
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(valid)
|
||||
return start_sq.get_value();
|
||||
}
|
||||
return tile::value::BLANK;
|
||||
}
|
||||
tile::value board::check_diagonals_(void)const{
|
||||
for(int i = 0;i < 2;++i){
|
||||
//check diagonals
|
||||
int offset = 0;
|
||||
int stride = 4;
|
||||
for(int k = 0;k < 2;++k){
|
||||
bool valid = true;
|
||||
auto& start_sq = m_tiles[offset];
|
||||
if(start_sq.get_value() == tile::value::BLANK){
|
||||
goto blank_continue; //bottom of loop
|
||||
}
|
||||
for(int l = 0;l < 3;++l){
|
||||
auto& cur_sq = m_tiles[l*stride + offset];
|
||||
if(cur_sq.get_value() != start_sq.get_value()){
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(valid)
|
||||
return start_sq.get_value();
|
||||
|
||||
blank_continue:
|
||||
offset = 2;
|
||||
stride = 2;
|
||||
}
|
||||
}
|
||||
return tile::value::BLANK;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -91,6 +91,20 @@ namespace egn{
|
||||
|
||||
void game::on_notify(const game_state_event&){}
|
||||
|
||||
resource_manager& game::resource_man(void){
|
||||
return m_res_manager;
|
||||
}
|
||||
const resource_manager& game::resource_man(void)const{
|
||||
return m_res_manager;
|
||||
}
|
||||
void game::push_state(std::unique_ptr<game_state_iface>&& state){
|
||||
m_states_manager.push_state(std::move(state));
|
||||
}
|
||||
void game::pop_state(void){
|
||||
m_states_manager.pop_state();
|
||||
}
|
||||
|
||||
|
||||
void game::setup_window_(){
|
||||
glfwSetWindowUserPointer(m_window, this);
|
||||
glfwSetKeyCallback(m_window.raw(), handle_input_events); //TODO
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -69,7 +69,7 @@ namespace egn{
|
||||
}
|
||||
|
||||
|
||||
game_state_iface::game_state_iface(game_state_manager* owner):
|
||||
game_state_iface::game_state_iface(game* owner):
|
||||
m_owner(owner){}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -16,13 +16,13 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "graphics/image.hpp"
|
||||
#include "graphics/stb_include.hpp"
|
||||
#include "engine/image.hpp"
|
||||
#include "engine/stb_include.hpp"
|
||||
#include "config.hpp"
|
||||
#include <cstring> //memcpy
|
||||
#include <utility> //exchange
|
||||
|
||||
namespace gfx{
|
||||
namespace egn{
|
||||
|
||||
image::image(const char* file, bool flip, int req_chan){
|
||||
stbi_set_flip_vertically_on_load(flip);
|
||||
@ -79,4 +79,20 @@ namespace gfx{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
|
||||
deferred_image::deferred_image(const char* file, bool flip, int req_chan):
|
||||
m_filename(file),
|
||||
m_flip(flip),
|
||||
m_req_chan(req_chan){}
|
||||
deferred_image::deferred_image(const std::string& file, bool flip, int req_chan):
|
||||
m_filename(file),
|
||||
m_flip(flip),
|
||||
m_req_chan(req_chan){}
|
||||
|
||||
deferred_image::operator image(void)const{
|
||||
return get_image();
|
||||
}
|
||||
image deferred_image::get_image(void)const{
|
||||
return image(m_filename.c_str(), m_flip, m_req_chan);
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,6 @@
|
||||
|
||||
#include "engine/object.hpp"
|
||||
#include "config.hpp"
|
||||
#include "util/minmax.hpp"
|
||||
|
||||
namespace egn{
|
||||
|
||||
|
||||
47
src/engine/resource_manager.cpp
Normal file
47
src/engine/resource_manager.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "engine/resource_manager.hpp"
|
||||
|
||||
namespace egn{
|
||||
|
||||
bool resource_manager::has_material(const char* key)const{
|
||||
if(auto it = m_textures.find(key);it != m_textures.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::material* resource_manager::get_material(const char* file){
|
||||
if(auto it = m_textures.find(file);it != m_textures.end())
|
||||
return &(*it).second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool resource_manager::has_model(const char* key)const{
|
||||
if(auto it = m_models.find(key);it != m_models.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
gfx::model* resource_manager::get_model(const char* file){
|
||||
if(auto it = m_models.find(file);it != m_models.end())
|
||||
return &(*it).second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
|
||||
#include "graphics/stb_alloc.hpp"
|
||||
#include "engine/stb_alloc.hpp"
|
||||
|
||||
#define STBI_MALLOC(size) our_dick_stb_malloc(size)
|
||||
#define STBI_FREE(data) our_dick_stb_free(data)
|
||||
@ -16,7 +16,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "graphics/stb_alloc.hpp"
|
||||
#include "engine/stb_alloc.hpp"
|
||||
|
||||
#include <cstdlib> //size_t
|
||||
#include <new> //new, delete
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -23,7 +23,8 @@
|
||||
|
||||
namespace gfx{
|
||||
|
||||
static bool is_format_compatible(GLenum format, int channel_count){
|
||||
[[maybe_unused]]
|
||||
static constexpr bool is_format_compatible(GLenum format, int channel_count){
|
||||
switch(channel_count){
|
||||
case 1:
|
||||
return format == GL_RED;
|
||||
@ -36,6 +37,34 @@ namespace gfx{
|
||||
};
|
||||
return false;
|
||||
}
|
||||
[[maybe_unused]]
|
||||
static constexpr GLenum convert_channel_to_format(int channels){
|
||||
switch(channels){
|
||||
case 1:
|
||||
return GL_RED;
|
||||
case 2:
|
||||
return GL_RG;
|
||||
case 3:
|
||||
return GL_RGB;
|
||||
case 4:
|
||||
return GL_RGBA;
|
||||
};
|
||||
return GL_RED;
|
||||
}
|
||||
[[maybe_unused]]
|
||||
static constexpr GLenum convert_format_to_channel(int channels){
|
||||
switch(channels){
|
||||
case GL_RED:
|
||||
return 1;
|
||||
case GL_RG:
|
||||
return 2;
|
||||
case GL_RGB:
|
||||
return 3;
|
||||
case GL_RGBA:
|
||||
return 4;
|
||||
};
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -71,7 +100,12 @@ namespace gfx{
|
||||
}
|
||||
texture::texture(GLenum format, GLsizei w, GLsizei h, GLenum type):
|
||||
texture(nullptr, format, w, h, type){}
|
||||
texture::texture(const image& i):
|
||||
texture::texture(const egn::image& i):
|
||||
texture()
|
||||
{
|
||||
set_image(i);
|
||||
}
|
||||
texture::texture(const egn::deferred_image& i):
|
||||
texture()
|
||||
{
|
||||
set_image(i);
|
||||
@ -90,46 +124,48 @@ namespace gfx{
|
||||
return m_tex_id;
|
||||
}
|
||||
|
||||
bool texture::set_image(const image& i){
|
||||
if(!i){
|
||||
bool texture::set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type){
|
||||
if(!data){
|
||||
debug_print_error("Image is invalid\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_width != i.get_width() || m_height != i.get_height() || !is_format_compatible(m_format, i.get_channels())){
|
||||
if(m_width != w || m_height != h || m_format != format){
|
||||
if(m_format != 0){
|
||||
debug_print_warn("Regenerating texture\n");
|
||||
glDeleteTextures(1, &m_tex_id);
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_tex_id);
|
||||
}
|
||||
m_width = i.get_width();
|
||||
m_height = i.get_height();
|
||||
switch(i.get_channels()){
|
||||
case 1:
|
||||
m_format = GL_RED;
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
switch(format){
|
||||
case GL_RED:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_R8, m_width, m_height);
|
||||
break;
|
||||
case 2:
|
||||
m_format = GL_RG;
|
||||
case GL_RG:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RG8, m_width, m_height);
|
||||
break;
|
||||
case 3:
|
||||
m_format = GL_RGB;
|
||||
case GL_RGB:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGB8, m_width, m_height);
|
||||
break;
|
||||
case 4:
|
||||
m_format = GL_RGBA;
|
||||
case GL_RGBA:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGBA8, m_width, m_height);
|
||||
break;
|
||||
default:
|
||||
debug_print_error("Invalid format for texture\n");
|
||||
return false;
|
||||
};
|
||||
m_format = format;
|
||||
}
|
||||
glTextureSubImage2D(m_tex_id, 0, 0, 0, m_width, m_height, m_format, GL_UNSIGNED_BYTE, i.data());
|
||||
glTextureSubImage2D(m_tex_id, 0, 0, 0, m_width, m_height, m_format, type, data);
|
||||
glGenerateTextureMipmap(m_tex_id);
|
||||
return true;
|
||||
}
|
||||
bool texture::set_image(const egn::image& i){
|
||||
return set_image(i.data(), convert_channel_to_format(i.get_channels()), i.get_width(), i.get_height(), GL_UNSIGNED_BYTE);
|
||||
}
|
||||
bool texture::set_image(const egn::deferred_image& i){
|
||||
return set_image(i.get_image());
|
||||
}
|
||||
|
||||
void texture::set_wrap_mode(wrap w){
|
||||
glTextureParameteri(m_tex_id, GL_TEXTURE_WRAP_S, static_cast<GLint>(w));
|
||||
|
||||
@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "graphics/vbo.hpp"
|
||||
#include "util/minmax.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <rexy/utility.hpp>
|
||||
#include <utility> //exchange, swap, move
|
||||
|
||||
namespace gfx{
|
||||
@ -68,7 +68,7 @@ namespace gfx{
|
||||
|
||||
bool vbo::buffer(const void* data, size_t datasize){
|
||||
if(datasize + m_buffer_size > get_cap()){
|
||||
if(!resize(util::max(datasize + m_buffer_size, get_cap() * 2)))
|
||||
if(!resize(rexy::max(datasize + m_buffer_size, get_cap() * 2)))
|
||||
return false;
|
||||
}
|
||||
glNamedBufferSubData(m_buffer, get_size(), datasize, data);
|
||||
@ -107,7 +107,7 @@ namespace gfx{
|
||||
}
|
||||
|
||||
bool vbo::copy_buffer(vbo& dest, const vbo& src){
|
||||
size_t bytes = util::min(dest.get_cap(), src.get_size());
|
||||
size_t bytes = rexy::min(dest.get_cap(), src.get_size());
|
||||
scoped_vbo_map<void> data(src.m_buffer, maptype::READ);
|
||||
if(!data.valid())
|
||||
return false;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -139,12 +139,16 @@ static void enable_opengl_debug_context(){
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
static char* copy_title(const char* src, size_t titlelen){
|
||||
char* dest = new char[titlelen + 1];
|
||||
strncpy(dest, src, titlelen);
|
||||
dest[titlelen] = 0;
|
||||
return dest;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
window::window(int width, int height, const char* title, bool makecurrent):
|
||||
window(s_default_cver_maj, s_default_cver_min, width, height, title, makecurrent){}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -17,12 +17,13 @@
|
||||
*/
|
||||
|
||||
#include "pause_state.hpp"
|
||||
#include "engine/game.hpp"
|
||||
|
||||
#include "graphics/gl_include.hpp" //TODO
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
pause_state::pause_state(egn::game_state_manager& owner, egn::game_state_iface* under):
|
||||
pause_state::pause_state(egn::game& owner, egn::game_state_iface* under):
|
||||
game_state_iface(&owner),
|
||||
m_under_state(under){}
|
||||
|
||||
@ -35,7 +36,7 @@ void pause_state::handle_input(const egn::input_event& event){
|
||||
m_owner->pop_state();
|
||||
return;
|
||||
}else if(event.key == GLFW_KEY_ESCAPE && !event.mods && event.action == GLFW_PRESS){
|
||||
m_owner->notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
m_owner->on_notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
}
|
||||
}else if(event.ev_type == egn::input_event::type::RESIZE){
|
||||
m_under_state->handle_input(event);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -21,39 +21,22 @@
|
||||
#include <queue>
|
||||
#include "pause_state.hpp"
|
||||
#include "graphics/gl_include.hpp" //TODO: separate key definitions from GLFW
|
||||
#include "graphics/image.hpp" //TODO: move image to engine namespace
|
||||
#include "engine/image.hpp" //TODO: move image to engine namespace
|
||||
#include "math/math.hpp"
|
||||
#include "square.hpp"
|
||||
#include "config.hpp"
|
||||
#include "engine/game.hpp"
|
||||
#include "board.hpp"
|
||||
|
||||
play_state::play_state(egn::game_state_manager& owner, int width, int height):
|
||||
play_state::play_state(egn::game& owner, int width, int height):
|
||||
game_state_iface(&owner),
|
||||
m_sprite_renderer(width, height),
|
||||
m_screen_renderer(width, height, m_sprite_renderer.color_buffer()),
|
||||
m_current_player(rand() % 2)
|
||||
{
|
||||
debug_print("First player chosen is %c\n", m_current_player ? 'X' : 'O');
|
||||
m_scene.textures.emplace_back(gfx::image("assets/images/blank.jpg", true));
|
||||
m_scene.textures.emplace_back(gfx::image("assets/images/o.jpg", true));
|
||||
m_scene.textures.emplace_back(gfx::image("assets/images/x.jpg", true));
|
||||
|
||||
m_scene.models.emplace_back(new gfx::model{gfx::unified_mesh(square_mesh(m_scene.textures[0],
|
||||
m_scene.textures[1],
|
||||
m_scene.textures[2]))});
|
||||
gfx::model& sm = *m_scene.models[0];
|
||||
for(int i = 0;i < 9;++i){
|
||||
m_scene.objects.emplace_back(new square(&sm));
|
||||
m_scene.renderables.emplace_back(static_cast<square*>(m_scene.objects[i].get()));
|
||||
}
|
||||
m_scene.objects[0]->set_position({-2, 2, -1});
|
||||
m_scene.objects[1]->set_position({-2, 0, -1});
|
||||
m_scene.objects[2]->set_position({-2, -2, -1});
|
||||
m_scene.objects[3]->set_position({ 0, 2, -1});
|
||||
m_scene.objects[4]->set_position({ 0, 0, -1});
|
||||
m_scene.objects[5]->set_position({ 0, -2, -1});
|
||||
m_scene.objects[6]->set_position({ 2, 2, -1});
|
||||
m_scene.objects[7]->set_position({ 2, 0, -1});
|
||||
m_scene.objects[8]->set_position({ 2, -2, -1});
|
||||
m_scene.objects.emplace_back(new board(m_owner->resource_man()));
|
||||
m_scene.renderables.emplace_back(static_cast<board*>(m_scene.objects[0].get()));
|
||||
|
||||
m_scene.cameras.emplace_back(new egn::ortho_camera(10 * ((float)width / height), 10, 0.1, 50));
|
||||
m_main_camera = static_cast<egn::ortho_camera*>(m_scene.cameras[0].get());
|
||||
@ -71,7 +54,7 @@ void play_state::handle_input(const egn::input_event& ev){
|
||||
m_owner->push_state(std::unique_ptr<game_state_iface>(new pause_state(*m_owner, this)));
|
||||
return;
|
||||
}else if(ev.key == GLFW_KEY_ESCAPE && !ev.mods && ev.action == GLFW_PRESS){
|
||||
m_owner->notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
m_owner->on_notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
}
|
||||
}else if(ev.ev_type == egn::input_event::type::RESIZE){
|
||||
if(ev.x > ev.y){
|
||||
@ -96,87 +79,27 @@ void play_state::handle_input(const egn::input_event& ev){
|
||||
debug_print("projected click vector: (%f, %f, %f)\n",
|
||||
projected1.x(), projected1.y(), projected1.z());
|
||||
|
||||
for(size_t i = 0;i < m_scene.objects.size();++i){
|
||||
square& sq = static_cast<square&>(*m_scene.objects[i]);
|
||||
const math::vec3<GLfloat>& sq_pos = sq.position();
|
||||
if((projected1.x() > (sq_pos.x() - 1.0f) && projected1.x() < (sq_pos.x() + 1.0f)) &&
|
||||
(projected1.y() > (sq_pos.y() - 1.0f) && projected1.y() < (sq_pos.y() + 1.0f)))
|
||||
{
|
||||
debug_print_succ("Clicked on square %lu\n", i);
|
||||
if(sq.get_value() == square::value::BLANK){
|
||||
sq.set_value(((++m_current_player) %= 2) ? square::value::O : square::value::X);
|
||||
}
|
||||
break;
|
||||
}
|
||||
board& b = static_cast<board&>(*m_scene.objects[0]);
|
||||
int index = b.click_collision_cheat(projected1);
|
||||
|
||||
if(index >= 0 && b.get_tile(index) == tile::value::BLANK)
|
||||
b.set_tile(index, (++m_current_player %= 2) ? tile::value::O : tile::value::X);
|
||||
|
||||
tile::value winner = b.check_winner();
|
||||
if(winner != tile::value::BLANK){
|
||||
printf("Winner is %c\n", winner == tile::value::O ? 'O' : 'X');
|
||||
m_owner->on_notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
}else if(b.is_full()){
|
||||
printf("Game is a tie\n");
|
||||
m_owner->on_notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void play_state::update(double time_diff){
|
||||
square::value winner = check_win_condition_();
|
||||
if(winner != square::value::BLANK){
|
||||
printf("Winner is %c\n", winner == square::value::O ? 'O' : 'X');
|
||||
m_owner->notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
}else if(is_board_full_()){
|
||||
printf("Game is a tie\n");
|
||||
m_owner->notify({egn::game_state_event::state_type::SHOULD_CLOSE, 0, 0});
|
||||
}
|
||||
}
|
||||
void play_state::render(){
|
||||
m_sprite_renderer.set_vp_matrix(m_main_camera->get_projection_matrix() * m_main_camera->get_view_matrix());
|
||||
m_sprite_renderer.render(m_scene);
|
||||
m_screen_renderer.render(m_scene);
|
||||
}
|
||||
|
||||
square::value play_state::check_win_condition_(){
|
||||
square::value v = square::value::O;
|
||||
for(int i = 0;i < 2;++i){
|
||||
for(int j = 0;j < 3;++j){
|
||||
//check columns
|
||||
bool valid = true;
|
||||
for(int l = 0;l < 3;++l){
|
||||
if(static_cast<square&>(*m_scene.objects[j*3 + l]).get_value() != v){
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(valid)
|
||||
return v;
|
||||
//check rows
|
||||
valid = true;
|
||||
for(int l = 0;l < 3;++l){
|
||||
if(static_cast<square&>(*m_scene.objects[j + l*3]).get_value() != v){
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(valid)
|
||||
return v;
|
||||
}
|
||||
//check diagonals
|
||||
int offset = 0;
|
||||
int stride = 4;
|
||||
for(int k = 0;k < 2;++k){
|
||||
bool valid = true;
|
||||
for(int l = 0;l < 3;++l){
|
||||
if(static_cast<square&>(*m_scene.objects[l * stride + offset]).get_value() != v){
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(valid)
|
||||
return v;
|
||||
offset = 2;
|
||||
stride = 2;
|
||||
}
|
||||
v = square::value::X;
|
||||
}
|
||||
return square::value::BLANK;
|
||||
}
|
||||
bool play_state::is_board_full_(){
|
||||
for(size_t i = 0;i < m_scene.objects.size();++i){
|
||||
if(static_cast<square&>(*m_scene.objects[i]).get_value() == square::value::BLANK)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "square.hpp"
|
||||
#include "graphics/gl_include.hpp"
|
||||
|
||||
#include <utility> //swap
|
||||
|
||||
gfx::unified_mesh square_mesh(const gfx::material& blank, const gfx::material& o, const gfx::material& x){
|
||||
static constexpr gfx::vertex s_vertices[] = {
|
||||
{{-1.0f, 1.0f, 0.0f}, {}, {0.0f, 1.0f}},
|
||||
{{-1.0f, -1.0f, 0.0f}, {}, {0.0f, 0.0f}},
|
||||
{{ 1.0f, -1.0f, 0.0f}, {}, {1.0f, 0.0f}},
|
||||
{{ 1.0f, -1.0f, 0.0f}, {}, {1.0f, 0.0f}},
|
||||
{{ 1.0f, 1.0f, 0.0f}, {}, {1.0f, 1.0f}},
|
||||
{{-1.0f, 1.0f, 0.0f}, {}, {0.0f, 1.0f}}
|
||||
};
|
||||
const gfx::material* mats[] = {&blank, &o, &x};
|
||||
|
||||
return gfx::unified_mesh{{s_vertices, sizeof(s_vertices) / sizeof(s_vertices[0])}, {mats, sizeof(mats) / sizeof(mats[0])}};
|
||||
}
|
||||
|
||||
|
||||
square::square(gfx::model* model):
|
||||
m_model(model){}
|
||||
|
||||
void square::set_value(value t){
|
||||
m_active_value = t;
|
||||
}
|
||||
auto square::get_value()const -> value{
|
||||
return m_active_value;
|
||||
}
|
||||
void square::set_color(const math::vec4<float>& color){
|
||||
m_color_filter = color;
|
||||
}
|
||||
|
||||
void square::render(gfx::shader_program& shader){
|
||||
shader.set_uniform("model_mat", model_matrix());
|
||||
shader.set_uniform("model_color", m_color_filter);
|
||||
shader.set_uniform("texture1", *m_model->mesh(0).material().get_material((int)m_active_value));
|
||||
m_model->mesh(0).vertex().render(shader);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2021 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -26,7 +26,7 @@ tic_tac_toe::tic_tac_toe(int width, int height):
|
||||
{
|
||||
m_window.make_current();
|
||||
m_states_manager.add_observer(*this);
|
||||
m_states_manager.push_state(std::unique_ptr<egn::game_state_iface>(new play_state(m_states_manager, width, height)));
|
||||
m_states_manager.push_state(std::unique_ptr<egn::game_state_iface>(new play_state(*this, width, height)));
|
||||
}
|
||||
|
||||
bool tic_tac_toe::is_game_over()const{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user