Good progress. Line drawing coming along decent.

This commit is contained in:
That-One-Nerd 2024-08-02 23:10:42 -04:00
parent e0b31c0238
commit 9168e584ef
9 changed files with 176 additions and 4 deletions

View File

@ -29,6 +29,11 @@ namespace sharp
double magnitude() const;
operator float2() const;
const int2 operator+(const int2& other) const;
const int2 operator-(const int2& other) const;
const int2 operator*(const int factor) const;
const int2 operator/(const int factor) const;
};
struct float2
{
@ -40,6 +45,11 @@ namespace sharp
double magnitude() const;
operator int2() const;
const float2 operator+(const float2& other) const;
const float2 operator-(const float2& other) const;
const float2 operator*(const double factor) const;
const float2 operator/(const double factor) const;
};
struct int_rect

View File

@ -36,4 +36,7 @@ namespace sharp
void start();
void end();
bool is_started();
double get_delta_time();
double get_elapsed_time();
}

View File

@ -17,6 +17,7 @@ namespace sharp
void render_iter();
void render_loop();
void draw_global_pixel(const color& color, const int2& pos);
void draw_global_line(const color& color, const int2& start, const int2& end);
void draw_global_rectangle(const color& color, const int_rect& rect);
void fill_global_rectangle(const color& color, const int_rect& rect);

View File

@ -10,9 +10,14 @@ namespace sharp
WINDOW_ACTIVE = 0x01,
WINDOW_VISIBLE = 0x02,
WINDOW_HEADER_VALIDATED = 0x04,
WINDOW_CONTENT_VALIDATED = 0x08
WINDOW_CONTENT_VALIDATED = 0x08,
WINDOW_IS_IN_PAINT_MODE = 0x10
};
// Can't tell if these are good ideas.
// FIXME: Messing with the header here requires a full screen
// invalidation triggered by the user, because I can't
// detect when its variables are modified.
struct window_features
{
static const window_features defaults;
@ -49,6 +54,8 @@ namespace sharp
window_features win_features;
window_styles styles;
double elapsed_time;
void paint_header() const;
void paint_content_back() const;
@ -61,6 +68,12 @@ namespace sharp
virtual void paint() = 0;
virtual void tick() = 0;
void draw_pixel(const color& color, const int2& pos);
void draw_line(const color& color, const int2& start, const int2& end);
//void draw_rect(const color& color, const int_rect& rect);
//void fill_rect(const color& color, const int_rect& rect);
public:
const window_styles& style() const;
window_styles& style();
@ -68,6 +81,7 @@ namespace sharp
const window_features& features() const;
window_features& features();
double get_elapsed_time() const;
const int2 get_pos() const;
const int2 get_size() const;
const int_rect get_content_rect() const;
@ -83,6 +97,9 @@ namespace sharp
void set_window_rect(const int_rect& new_rect);
void set_title(const std::string& new_title);
const int2 to_screen(const int2& window_pos) const;
const int2 to_window(const int2& screen_pos) const;
void invalidate();
void show();

View File

@ -1,3 +1,4 @@
#include <numbers>
#include "main.h"
#include "sharpsoft/all.hpp"
#include "sharpsoft/basic_types.hpp"
@ -6,12 +7,36 @@
// This library is intended to be referenced by the prefix `sharp::`
// Including `using namespace sharp;` is not recommended.
using std::numbers::pi;
class test_window : public sharp::window_base
{
protected:
void paint() override
{
constexpr int points = 5;
int bigRadius = 100,
smallRadius = 60;
sharp::int2 center = get_size() / 2;
sharp::int2 arr[points * 2];
double time = get_elapsed_time();
double offset = pi / points;
for (int i = 0; i < points; i++)
{
arr[i * 2] = sharp::int2(bigRadius * cos(time + (offset * i * 2)), bigRadius * sin(time + (offset * i * 2))) + center;
arr[i * 2 + 1] = sharp::int2(smallRadius * cos(time + (offset * (i * 2 + 1))), smallRadius * sin(time + (offset * (i * 2 + 1)))) + center;
}
for (int i = 0; i < points * 2; i++)
{
sharp::int2& this_point = arr[i],
next_point = arr[(i + 1) % (points * 2)];
draw_line(0xABCDEF, this_point, next_point);
}
}
void tick() override
{

View File

@ -67,6 +67,22 @@ sharp::int2::operator float2() const
{
return float2(x, y);
}
const int2 sharp::int2::operator+(const int2& other) const
{
return int2(x + other.x, y + other.y);
}
const int2 sharp::int2::operator-(const int2& other) const
{
return int2(x - other.x, y - other.y);
}
const int2 sharp::int2::operator*(const int factor) const
{
return int2(x * factor, y * factor);
}
const int2 sharp::int2::operator/(const int factor) const
{
return int2(x / factor, y / factor);
}
sharp::float2::float2()
{
@ -86,6 +102,22 @@ sharp::float2::operator int2() const
{
return int2(x, y);
};
const float2 sharp::float2::operator+(const float2& other) const
{
return float2(x + other.x, y + other.y);
}
const float2 sharp::float2::operator-(const float2& other) const
{
return float2(x - other.x, y - other.y);
}
const float2 sharp::float2::operator*(const double factor) const
{
return float2(x * factor, y * factor);
}
const float2 sharp::float2::operator/(const double factor) const
{
return float2(x / factor, y / factor);
}
sharp::int_rect::int_rect()
{

View File

@ -22,6 +22,9 @@ color back_col;
int render_wait_ms;
thread* render_thread = nullptr;
double delta_time;
double elapsed_time;
vector<window_base*> windows;
void sharp::initialize()
@ -34,6 +37,8 @@ void sharp::initialize(const global_properties& props)
back_col = props.background_color;
render_wait_ms = 1000 / props.refresh_rate;
delta_time = 0;
elapsed_time = 0;
init = true;
}
@ -49,6 +54,8 @@ void sharp::uninitialize()
delete windows.at(i);
}
windows.clear();
delta_time = 0;
elapsed_time = 0;
init = false;
}
@ -103,15 +110,20 @@ void sharp::internal::render_iter()
if (!HAS_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED) ||
(!HAS_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED) && win->win_features.update_header))
{
ON_INTERNAL_FLAG(win, WINDOW_IS_IN_PAINT_MODE);
win->paint_header();
OFF_INTERNAL_FLAG(win, WINDOW_IS_IN_PAINT_MODE);
ON_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED);
}
if (!HAS_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED))
{
ON_INTERNAL_FLAG(win, WINDOW_IS_IN_PAINT_MODE);
win->paint_content_back();
win->paint();
OFF_INTERNAL_FLAG(win, WINDOW_IS_IN_PAINT_MODE);
ON_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED);
}
win->elapsed_time += delta_time;
}
}
void sharp::internal::render_loop()
@ -119,6 +131,9 @@ void sharp::internal::render_loop()
thread::delay(50); // Wait a sec for the screen to be ready.
while (true)
{
// TODO: This could be improved with a proper chrono timer, but it's alright.
delta_time = 1.0 / render_wait_ms;
elapsed_time += delta_time;
render_iter();
thread::delay(render_wait_ms);
}
@ -151,6 +166,8 @@ void sharp::start()
render_thread = new thread(internal::render_loop);
render_thread->start();
delta_time = 0;
elapsed_time = 0;
started = true;
}
@ -160,6 +177,8 @@ void sharp::end()
render_thread->stop();
delete render_thread;
delta_time = 0;
elapsed_time = 0;
started = false;
}
@ -168,3 +187,12 @@ bool sharp::is_started()
{
return started;
}
double sharp::get_delta_time()
{
return delta_time;
}
double sharp::get_elapsed_time()
{
return elapsed_time;
}

View File

@ -11,7 +11,12 @@
using namespace sharp;
#ifdef SH_PROS_ACTIVE
void internal::draw_global_line(const color &color, const int2 &start, const int2 &end)
void internal::draw_global_pixel(const color& color, const int2& pos)
{
pros::screen::set_pen(color.get_value());
pros::screen::draw_pixel(pos.x, pos.y);
}
void internal::draw_global_line(const color& color, const int2& start, const int2& end)
{
pros::screen::set_pen(color.get_value());
pros::screen::draw_line(start.x, start.y, end.x, end.y);
@ -56,3 +61,35 @@ void window_base::paint_content_back() const
{
internal::fill_global_rectangle(styles.background_color, get_content_rect());
}
void window_base::draw_pixel(const color& color, const int2& win_pos)
{
if (win_pos.x < 0 || win_pos.x >= width ||
win_pos.y < 0 || win_pos.y >= height) return; // Out of window bounds.
const int2 true_pos = to_screen(win_pos);
internal::draw_global_pixel(color, true_pos);
}
void window_base::draw_line(const color& color, const int2& pos_a, const int2& pos_b)
{
// FIXME: This causes artifacts occasionally along the top and bottom of the window.
// Why?
double slope = (double)(pos_b.y - pos_a.y) / (pos_b.x - pos_a.x),
inv_slope = (double)(pos_b.x - pos_a.x) / (pos_b.y - pos_a.y); // Prevent divide by zero errors.
int2 a = pos_a, b = pos_b;
if (a.x < 0) a = int2(0, -a.x * slope + a.y); // Left wall truncate for A.
else if (a.x >= width) a = int2(width - 1, ((width - 1) - a.x) * slope + a.y); // Right wall truncate for A.
if (a.y < 0) a = int2(-a.y * inv_slope + a.x, 0); // Bottom wall truncate for A.
else if (a.y >= height) a = int2(((height - 1) - a.y) * inv_slope + a.x, height - 1); // Top wall truncate for A.
if (b.x < 0) b = int2(0, -a.x * slope + a.y); // Left wall truncate for B.
else if (b.x >= width) b = int2(width - 1, ((width - 1) - a.x) * slope + a.y); // Right wall truncate for B.
if (b.y < 0) b = int2(-a.y * inv_slope + a.x, 0); // Bottom wall truncate for B.
else if (b.y >= height) b = int2(((height - 1) - a.y) * inv_slope + a.x, height - 1); // Top wall truncate for B.
const int2 true_pos_a = to_screen(a),
true_pos_b = to_screen(b);
internal::draw_global_line(color, true_pos_a, true_pos_b);
}

View File

@ -17,6 +17,8 @@ sharp::window_base::window_base(const string& title, const int2& pos, const int2
win_features = window_features::defaults;
styles = window_styles::defaults;
elapsed_time = 0;
}
sharp::window_base::~window_base()
{
@ -40,6 +42,10 @@ window_features& sharp::window_base::features()
{
return win_features;
}
double sharp::window_base::get_elapsed_time() const
{
return elapsed_time;
}
const int2 sharp::window_base::get_pos() const
{
return int2(posX, posY);
@ -137,3 +143,16 @@ void sharp::window_base::show()
OFF_INTERNAL_FLAG(this, WINDOW_HEADER_VALIDATED);
OFF_INTERNAL_FLAG(this, WINDOW_CONTENT_VALIDATED);
}
const int2 sharp::window_base::to_screen(const int2& window_pos) const
{
int header_height = get_header_height();
if (header_height > 0) return int2(window_pos.x + posX, window_pos.y + posY + header_height + 1);
else return int2(window_pos.x + posX, window_pos.y + posY);
}
const int2 sharp::window_base::to_window(const int2& screen_pos) const
{
int header_height = get_header_height();
if (header_height > 0) return int2(screen_pos.x - posX, screen_pos.y - posY - header_height - 1);
else return int2(screen_pos.x - posY, screen_pos.y - posY);
}