diff --git a/build/Debug/unifont.ttf b/build/Debug/unifont.ttf new file mode 100644 index 0000000..ec875c5 Binary files /dev/null and b/build/Debug/unifont.ttf differ diff --git a/build/Release/unifont.ttf b/build/Release/unifont.ttf new file mode 100644 index 0000000..ec875c5 Binary files /dev/null and b/build/Release/unifont.ttf differ diff --git a/build/unifont.ttf b/build/unifont.ttf new file mode 100644 index 0000000..ec875c5 Binary files /dev/null and b/build/unifont.ttf differ diff --git a/src/Curses.cpp b/src/Curses.cpp new file mode 100644 index 0000000..9a3b1a8 --- /dev/null +++ b/src/Curses.cpp @@ -0,0 +1,187 @@ +#pragma once +#include "Curses.h" +#include +#include + +Curses::Curses(sf::Vector2i tile_size_, sf::Vector2i grid_dimensions_) : + window(sf::VideoMode(tile_size_.x * grid_dimensions_.x, tile_size_.y * grid_dimensions_.y), "SimpleFML Curses"), + grid_dimensions(grid_dimensions_), + tile_pixel_dimensions(tile_size_){ + + font.loadFromFile("unifont.ttf"); + + for (int y = 0; y < grid_dimensions_.y; y++) { + for (int x = 0 ; x < grid_dimensions_.x; x++) { + tiles.emplace_back(Tile(sf::Vector2i(x, y))); + + // L'\u0020' = space char + } + } + + + // Set screen values to increasing unicode chars + /*wchar_t char_ind = L'\u0041'; + for (int i = 0; i < tiles.size(); i++) { + tiles.at(i).push_clear(char_ind++, sf::Color::White, sf::Color::Black); + }*/ +} + +Curses::~Curses() { +} + +void Curses::Update(double delta_time_) { + + for (Tile &tile : tiles) { + tile.inc_index(); + } + + sf::Event event; + while (window.pollEvent(event)) { + if (event.type == sf::Event::Closed) + window.close(); + } +} + +void Curses::Render() { + window.clear(); + + sf::Texture font_texture = font.getTexture(tile_pixel_dimensions.x); + + // Draw text and backfills + sf::VertexArray backfill_v_arr(sf::Quads, grid_dimensions.x * grid_dimensions.y * 4); + sf::VertexArray font_v_arr(sf::Quads, grid_dimensions.x * grid_dimensions.y * 4); + + int tile_index = 0; + + for (int i = 0; i < backfill_v_arr.getVertexCount(); i += 4) { + + Tile* tile = &tiles.at(tile_index); + sf::Glyph glyph = font.getGlyph(tile->current_unicode_value(), tile_pixel_dimensions.x, false); + + // Backfill the tile with the specified backfill color + backfill_v_arr[i + 0].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x, tile->getPosition().y * tile_pixel_dimensions.y); + backfill_v_arr[i + 1].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x + tile_pixel_dimensions.x, tile->getPosition().y * tile_pixel_dimensions.y); + backfill_v_arr[i + 2].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x + tile_pixel_dimensions.x, tile->getPosition().y * tile_pixel_dimensions.y + tile_pixel_dimensions.y); + backfill_v_arr[i + 3].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x, tile->getPosition().y * tile_pixel_dimensions.y + tile_pixel_dimensions.y); + + backfill_v_arr[i + 0].color = tile->current_backfill_color(); + backfill_v_arr[i + 1].color = tile->current_backfill_color(); + backfill_v_arr[i + 2].color = tile->current_backfill_color(); + backfill_v_arr[i + 3].color = tile->current_backfill_color(); + + // Draw the font with the correct size, texture location, window location, and color + font_v_arr[i + 0].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x, tile->getPosition().y * tile_pixel_dimensions.y); + font_v_arr[i + 1].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x + glyph.textureRect.width, tile->getPosition().y * tile_pixel_dimensions.y); + font_v_arr[i + 2].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x + glyph.textureRect.width, tile->getPosition().y * tile_pixel_dimensions.y + glyph.textureRect.height); + font_v_arr[i + 3].position = sf::Vector2f(tile->getPosition().x * tile_pixel_dimensions.x, tile->getPosition().y * tile_pixel_dimensions.y + glyph.textureRect.height); + + // Make the letter appear in the center of the tile by applying an offset + sf::Vector2f position_offset = sf::Vector2f(tile_pixel_dimensions.x / 4, tile_pixel_dimensions.y / 4); + font_v_arr[i + 0].position += position_offset; + font_v_arr[i + 1].position += position_offset; + font_v_arr[i + 2].position += position_offset; + font_v_arr[i + 3].position += position_offset; + + font_v_arr[i + 0].texCoords = sf::Vector2f(glyph.textureRect.left, glyph.textureRect.top); + font_v_arr[i + 1].texCoords = sf::Vector2f(glyph.textureRect.width + glyph.textureRect.left, glyph.textureRect.top); + font_v_arr[i + 2].texCoords = sf::Vector2f(glyph.textureRect.width + glyph.textureRect.left, glyph.textureRect.top + glyph.textureRect.height); + font_v_arr[i + 3].texCoords = sf::Vector2f(glyph.textureRect.left, glyph.textureRect.top + glyph.textureRect.height); + + font_v_arr[i + 0].color = tile->current_font_color(); + font_v_arr[i + 1].color = tile->current_font_color(); + font_v_arr[i + 2].color = tile->current_font_color(); + font_v_arr[i + 3].color = tile->current_font_color(); + + tile_index++; + } + + window.draw(backfill_v_arr); + window.draw(font_v_arr, &font_texture); + + window.display(); +} + +void Curses::setTile(Tile tile_) { + tiles.at(multi_to_linear(tile_.getPosition())) = tile_; +} + +void Curses::setTiles(std::vector tiles_) { + for (Tile tile: tiles_) { + tiles.at(multi_to_linear(tile.getPosition())) = tile; + } +} + +void Curses::Clear() { + for (Tile &tile : tiles) { + tile.clear(); + } +} + +Curses::Tile* Curses::getTile(sf::Vector2i position_) { + return &tiles.at(multi_to_linear(position_)); +} + +std::vector Curses::getTiles(sf::Vector2i start_, sf::Vector2i end_) { + std::vector ret; + for (int i = multi_to_linear(start_); i < multi_to_linear(end_); i++) { + ret.push_back(&tiles.at(i)); + } + return ret; +} + +void Curses::setScroll(int ratio_, sf::Vector2i start_, std::list scroll_text_) { + // Scrolling and it's scroll ratio is faux implemented by + // essentially stacking values and repeating them to slow the scroll down + + + + for (int i = 0; i < scroll_text_.size(); i++) { + append_slots(start_, scroll_text_); + scroll_text_.push_back(scroll_text_.front()); + scroll_text_.pop_front(); + } + + +} + + + +void Curses::set_tile_ratio(int ratio_, sf::Vector2i tile_position_) { + getTile(tile_position_)->set_ratio(ratio_); +} + +void Curses::append_slots(sf::Vector2i start_, std::list values_) +{ + std::vector tiles = getTiles(start_, + sf::Vector2i((values_.size() + start_.x) % grid_dimensions.x, + (values_.size() + start_.x) / grid_dimensions.x + start_.y)); + + if (tiles.size() != values_.size()) { + std::cout << "Values did not match up to slots when appending\n"; + return; + } + + std::list::iterator beg_slot_it = values_.begin(); + std::list::iterator end_slot_it = values_.end(); + std::list::iterator slot_it; + + std::vector::iterator beg_tile_it = tiles.begin(); + std::vector::iterator end_tile_it = tiles.end(); + std::vector::iterator tile_it; + + for (slot_it = beg_slot_it, tile_it = beg_tile_it; + (slot_it != end_slot_it) && (tile_it != end_tile_it); + ++slot_it, ++tile_it) { + + Tile* t = *tile_it; + t->push_back(*slot_it); + + } +} + +sf::Vector2i Curses::linear_to_multi(int position_) const { + return sf::Vector2i(position_ % grid_dimensions.x, position_ / grid_dimensions.x); +} +int Curses::multi_to_linear(sf::Vector2i position_) const { + return position_.y * grid_dimensions.x + position_.x; +} diff --git a/src/Curses.h b/src/Curses.h new file mode 100644 index 0000000..91443a9 --- /dev/null +++ b/src/Curses.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include + +class Curses { +public: + + struct Slot { + Slot(wchar_t unicode_value_, + sf::Color font_color_, + sf::Color backfill_color_) : + unicode_value(unicode_value_), + font_color(font_color_), + backfill_color(backfill_color_) + {}; + + wchar_t unicode_value; + sf::Color font_color; + sf::Color backfill_color; + }; + + struct Tile { + public: + Tile(sf::Vector2i position_) : + blank_standby(L'\u0020', sf::Color::Transparent, sf::Color::Black), + position(position_) + { }; + + private: + Slot blank_standby; + + int index = 0; // What index in the vector are we. Backbone for blinking and scrolling + int ratio_counter = 0; // Secondary counter to hold index positions for (ratio) length of time + int ratio_value = 0; + + std::vector slot_stack; // The icon that aligns with the index + + sf::Vector2i position; // Position of the text, and backfill + + public: + void set_ratio(int ratio_) { + ratio_value = ratio_; + } + + sf::Vector2i getPosition() const { + return position; + } + + void push_back(Slot s) { + slot_stack.push_back(s); + } + + void clear_and_set(Slot s) { + slot_stack.clear(); + slot_stack.push_back(s); + } + + void clear() { + slot_stack.clear(); + } + + sf::Color current_font_color() { + if (slot_stack.size() > 0) + return slot_stack.at(index).font_color; + else + return blank_standby.font_color; + } + + sf::Color current_backfill_color() { + if (slot_stack.size() > 0) + return slot_stack.at(index).backfill_color; + else + return blank_standby.backfill_color; + } + + wchar_t current_unicode_value() { + if (slot_stack.size() > 0) + return slot_stack.at(index).unicode_value; + else + return blank_standby.unicode_value; + } + + void inc_index() { + if (index >= slot_stack.size() - 1) { + index = 0; + } + else if (ratio_counter == ratio_value) { + ratio_counter = 0; + index++; + } + else + ratio_counter++; + } + }; + + Curses(sf::Vector2i tile_size_, sf::Vector2i grid_dimensions); + ~Curses(); + + + void Update(double delta_time_); + void Render(); + + + void setTile(Tile tile_); + void setTiles(std::vector tiles_); // Can be seperate, non-adjacent tiles + + void Clear(); + + Tile* getTile(sf::Vector2i position_); + std::vector getTiles(sf::Vector2i start_, sf::Vector2i end_); + + void ResizeTiles(sf::Vector2i size_); + void ResizeTileGrid(sf::Vector2i grid_dimensions_); + + void setBlink(int ratio_, sf::Vector2i position_); + void setScroll(int ratio_, sf::Vector2i start_, sf::Vector2i end_); + void setScroll(int ratio_, sf::Vector2i start_, std::list tiles_); + + +private: + + sf::Vector2i grid_dimensions; + sf::Vector2i tile_pixel_dimensions; + + sf::RenderWindow window; + + std::vector tiles; + + sf::Font font; + + int multi_to_linear(sf::Vector2i position_) const; + sf::Vector2i linear_to_multi(int position_) const; + + void set_tile_ratio(int ratio_, sf::Vector2i tile_position_); + void append_slots(sf::Vector2i start_, std::list values_); + +}; + diff --git a/src/Ray.cpp b/src/Ray.cpp index bddc135..b822789 100644 --- a/src/Ray.cpp +++ b/src/Ray.cpp @@ -86,23 +86,23 @@ sf::Color Ray::Cast() { // If the ray went out of bounds if (voxel.z >= dimensions.z) { - return sf::Color(0, 0, 255, 50); + return sf::Color(172, 245, 251, 200); } if (voxel.x >= dimensions.x) { - return sf::Color(0, 0, 255, 100); + return sf::Color(172, 245, 251, 200); } if (voxel.y >= dimensions.x) { - return sf::Color(0, 0, 255, 150); + return sf::Color(172, 245, 251, 200); } if (voxel.x < 0) { - return sf::Color(0, 255, 0, 150); + return sf::Color(172, 245, 251, 200); } if (voxel.y < 0) { - return sf::Color(0, 255, 0, 100); + return sf::Color(172, 245, 251, 200); } if (voxel.z < 0) { - return sf::Color(0, 255, 0, 50); + return sf::Color(172, 245, 251, 200); } // If we hit a voxel diff --git a/src/main.cpp b/src/main.cpp index 2ee2da9..139d4b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,9 +5,10 @@ #include "util.hpp" #include "RayCaster.h" #include +#include "Curses.h" -const int WINDOW_X = 200; -const int WINDOW_Y = 200; +const int WINDOW_X = 150; +const int WINDOW_Y = 150; float elap_time(){ @@ -51,7 +52,10 @@ void test_ray_reflection(){ int main() { // Initialize the render window + Curses curse(sf::Vector2i(5, 5), sf::Vector2i(WINDOW_X, WINDOW_Y)); sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "SFML"); + + // The step size in milliseconds between calls to Update() // Lets set it to 16.6 milliseonds (60FPS) @@ -77,13 +81,16 @@ int main() { sf::Vector2i view_res(WINDOW_X, WINDOW_Y); sf::Vector3f cam_dir(1.0f, 0.0f, 1.57f); sf::Vector3f cam_pos(50, 50, 50); - + sf::Vector3f cam_vec(0, 0, 0); Map* map = new Map(map_dim); RayCaster ray_caster(map, map_dim, view_res); // =============================================================================== + // Mouse capture + sf::Vector2i deltas; + sf::Vector2i fixed(window.getSize()); while (window.isOpen()) { @@ -115,34 +122,81 @@ int main() { std::cout << "X:" << cam_dir.x << " Y:" << cam_dir.y << " Z:" << cam_dir.z << std::endl; } - // CAMERA POSITION - if (event.key.code == sf::Keyboard::Q) { - cam_pos.z -= 1; - std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; - } - if (event.key.code == sf::Keyboard::E) { - cam_pos.z += 1; - std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; - } - if (event.key.code == sf::Keyboard::W) { - cam_pos.y += 1; - std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; - } - if (event.key.code == sf::Keyboard::S) { - cam_pos.y -= 1; - std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; - } - if (event.key.code == sf::Keyboard::A) { - cam_pos.x += 1; - std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; - } - if (event.key.code == sf::Keyboard::D) { - cam_pos.x -= 1; - std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; - } + //// CAMERA POSITION + //if (event.key.code == sf::Keyboard::Q) { + // cam_pos.z -= 1; + // std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; + //} + //if (event.key.code == sf::Keyboard::E) { + // cam_pos.z += 1; + // std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; + //} + //if (event.key.code == sf::Keyboard::W) { + // cam_pos.y += 1; + // std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; + //} + //if (event.key.code == sf::Keyboard::S) { + // cam_pos.y -= 1; + // std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; + //} + //if (event.key.code == sf::Keyboard::A) { + // cam_pos.x += 1; + // std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; + //} + //if (event.key.code == sf::Keyboard::D) { + // cam_pos.x -= 1; + // std::cout << "X:" << cam_pos.x << " Y:" << cam_pos.y << " Z:" << cam_pos.z << std::endl; + //} } } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { + cam_vec.z = 1; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::E)) { + cam_vec.z = -1; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) { + cam_vec.y = 1; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { + cam_vec.y = -1; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) { + cam_vec.x = 1; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { + cam_vec.x = -1; + } + + deltas = fixed - sf::Mouse::getPosition(); + if (deltas != sf::Vector2i(0, 0)) + sf::Mouse::setPosition(fixed); + + cam_dir.y -= deltas.y / 300.0f; + cam_dir.z -= deltas.x / 300.0f; + + cam_pos.x += cam_vec.x / 10.0; + cam_pos.y += cam_vec.y / 10.0; + cam_pos.z += cam_vec.z / 10.0; + + if (cam_vec.x > 0.0f) + cam_vec.x -= 0.1; + else if (cam_vec.x < 0.0f) + cam_vec.x += 0.1; + + if (cam_vec.y > 0.0f) + cam_vec.y -= 0.1; + else if (cam_vec.y < 0.0f) + cam_vec.y += 0.1; + + if (cam_vec.z > 0.0f) + cam_vec.z -= 0.1; + else if (cam_vec.z < 0.0f) + cam_vec.z += 0.1; + + std::cout << cam_vec.x << " : " << cam_vec.y << " : " << cam_vec.z << std::endl; + // Get the elapsed time from the start of the application elapsed_time = elap_time(); @@ -168,18 +222,30 @@ int main() { // Take away a step from the accumulator accumulator_time -= step_size; - + curse.Update(delta_time); // And update the application for the amount of time alotted for one step // Update(step_size); } - map->moveLight(sf::Vector2f(0.3, 0)); + + + // map->moveLight(sf::Vector2f(0.3, 0)); window.clear(sf::Color::Black); // Cast the rays and get the image sf::Color* pixel_colors = ray_caster.CastRays(cam_dir, cam_pos); + for (int i = 0; i < WINDOW_X * WINDOW_Y; i++) { + + Curses::Tile t(sf::Vector2i(i % WINDOW_X, i / WINDOW_X)); + Curses::Slot s(L'\u0045', pixel_colors[i], sf::Color::Black); + t.push_back(s); + curse.setTile(t); + + } + + // Cast it to an array of Uint8's auto out = (sf::Uint8*)pixel_colors; @@ -187,6 +253,9 @@ int main() { window_sprite.setTexture(window_texture); window.draw(window_sprite); + + curse.Render(); + // Give the frame counter the frame time and draw the average frame time fps.frame(delta_time); fps.draw(&window); diff --git a/src/unifont.ttf b/src/unifont.ttf new file mode 100644 index 0000000..ec875c5 Binary files /dev/null and b/src/unifont.ttf differ