From ee571c1b56232ba5b0595197f64af8c36c6d96c6 Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Sat, 1 Jun 2013 18:11:59 +0200 Subject: [PATCH] Added drawing and undoing --- src/client/GameRenderer.cpp | 14 ++++- src/client/client.cpp | 114 ++++++++++++++++++++++++++++-------- src/client/client.hpp | 22 +++++-- 3 files changed, 117 insertions(+), 33 deletions(-) diff --git a/src/client/GameRenderer.cpp b/src/client/GameRenderer.cpp index 1b577fe..a23e2a9 100644 --- a/src/client/GameRenderer.cpp +++ b/src/client/GameRenderer.cpp @@ -92,7 +92,7 @@ void GameRenderer::draw(Client const & client){ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); - auto projectionMatrix = projection_matrices::orthographic(client.sim.bounds.xmin, client.sim.bounds.xmax, client.sim.bounds.ymax, client.sim.bounds.ymin, -100.0f, 100.0f); + auto projectionMatrix = projection_matrices::orthographic(0, client.window_width, client.window_height, 0, -100.0f, 100.0f); auto modelViewProjectionMatrix = projectionMatrix; std::swap(fbo1, fbo2); @@ -118,13 +118,13 @@ void GameRenderer::draw(Client const & client){ gl::draw_arrays(GL_POINTS, 0, client.beat.notes.size()); } - if(!client.lines.empty() || client.kick || client.snare){ + if(!client.lines.empty() || client.kick || client.snare || client.drawing){ moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); line_shader.s.use(); line_shader.s.uniform>("modelViewProjectionMatrix").set(modelViewProjectionMatrix); lines.clear(); - lines.reserve(client.lines.size() * 2 + 2 * 2); + lines.reserve(client.lines.size() * 2 + 2 * 2 + 2); for(auto const & l : client.lines){ Color color = (l->line_kind == simulation::kFallThrough) ? Color{1.0f, l->color_intensity, std::sin(l->color_intensity)} @@ -143,6 +143,14 @@ void GameRenderer::draw(Client const & client){ lines.push_back({client.snare->starting_point, color}); lines.push_back({client.snare->end_point, color}); } + if(client.drawing){ + const float color_intensity = 0.0f; + Color color = (client.current_kind == simulation::kFallThrough) + ? Color{1.0f, color_intensity, std::sin(color_intensity)} + : Color{std::sin(color_intensity), 0.5f + 0.5f*color_intensity, 1.0f}; + lines.push_back({to_FloatVec2(client.current_line.starting_point), color}); + lines.push_back({to_FloatVec2(client.current_line.end_point), color}); + } if(debug_draw){ for(auto const & l : client.sim.lines){ diff --git a/src/client/client.cpp b/src/client/client.cpp index 4b2210e..536a15b 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -38,7 +38,7 @@ namespace games { } } else if (command == "peeps"){ auto str = from_json(object["data"]); - current_client->update_peeps(str); + current_client->set_text("Peeps: " + str); } } catch(std::exception& e){ throw websockets::runtime_error(e.what()); @@ -115,6 +115,14 @@ namespace games { lines_changed = true; } + void Client::remove_line(std::shared_ptr const & instr){ + auto& v = sim.lines; + v.erase(std::remove_if(v.begin(), v.end(), [instr](line_type const &l2){ return instr.get() == l2.information; }), v.end()); + + auto& w = lines; + w.erase(std::remove_if(w.begin(), w.end(), [instr](std::shared_ptr const & l){ return instr == l; }), w.end()); + } + void Client::add_drum(){ kick = std::make_shared(math::Vec2{x1 - 25.0f, window_height - 100.0f}, math::Vec2{x1 + 25.0f, window_height - 50.0f}, 1, -1); kick->sound.reset(new motor::al::Source(sounds[2])); @@ -188,19 +196,19 @@ namespace games { info.gid = -1; info.uid = -1; - context = libwebsocket_create_context(&info); - if(!context) throw std::runtime_error("context could not be created."); + // context = libwebsocket_create_context(&info); + // if(!context) throw std::runtime_error("context could not be created."); // std::string address = "127.0.0.1"; std::string address = "vadovas-studios.com"; - wsi = libwebsocket_client_connect(context, address.c_str(), 7681, false, "/", address.c_str(), "origin", "uberclient", -1); - if(!wsi) throw std::runtime_error("socket could not be created."); + // wsi = libwebsocket_client_connect(context, address.c_str(), 7681, false, "/", address.c_str(), "origin", "uberclient", -1); + // if(!wsi) throw std::runtime_error("socket could not be created."); // motor world.physics.set_gravity({0.0, 0.0, 0.0}); hud->camera.set_orthographic(-100, 100, -100, 100, 1, -1); - update_peeps(""); - auto join_lbl = std::make_shared("Join at: http://vadovas-studios.com/beats", motor::bundle.get_font_path() + "Arial Rounded Bold.ttf", 72); + set_text("draw mode: guitar"); + auto join_lbl = std::make_shared("-/+: speed, l: clear lines, b: clear balls, d: toggle drums, k: change drawmode", motor::bundle.get_font_path() + "Arial Rounded Bold.ttf", 72); join_lbl->get_mesh()->material->diffuse_color = {1.0f, 1.0f, 1.0f, 1.0f}; join_lbl->set_position({-95.0, -95.0, 0.0}); join_lbl->set_scale(motor::scale(0.05)); @@ -211,6 +219,26 @@ namespace games { void Client::handle_input(float dt, Input input){ using motor::Position; + if(input.mouse.went_down[Input::Mouse::left]){ + drawing = true; + current_line.starting_point = {input.mouse.position[0], input.mouse.position[1]}; + current_line.end_point = {input.mouse.position[0], input.mouse.position[1]}; + } + + if(input.mouse.is_pressed[Input::Mouse::left]){ + current_line.end_point = {input.mouse.position[0], input.mouse.position[1]}; + current_line.line_kind = current_kind; + } + + if(input.mouse.went_up[Input::Mouse::left]){ + current_line.end_point = {input.mouse.position[0], input.mouse.position[1]}; + add_line(current_line); + while(!undo_stack.empty()){ + undo_stack.pop(); + } + drawing = false; + } + if(input.keys_went_down[SDLK_b]){ sim.balls.clear(); } @@ -227,22 +255,55 @@ namespace games { music_speed = 2.0; } - if(input.keys_went_down[SDLK_z]){ + if(input.keys_went_down[SDLK_r]){ sim_speed = 0.5; } - if(input.keys_went_down[SDLK_x]){ + if(input.keys_went_down[SDLK_t]){ sim_speed = 1.0; } - if(input.keys_went_down[SDLK_c]){ + if(input.keys_went_down[SDLK_y]){ sim_speed = 2.0; } + if(input.keys_went_down[SDLK_z] && !lines.empty()){ + std::shared_ptr line = lines.back(); + remove_line(line); + undo_stack.push(line); + } + + if(input.keys_went_down[SDLK_x] && !undo_stack.empty()){ + std::shared_ptr line = undo_stack.top(); + undo_stack.pop(); + lines.push_back(line); + + for(auto & l : line->calculate_lines()){ + sim.lines.push_back(l); + } + } + + const float step = 1.5; + if(input.keys_went_down[SDLK_MINUS]){ + global_speed /= step; + } + + if(input.keys_went_down[SDLK_EQUALS]){ + global_speed *= step; + } + if(input.keys_went_down[SDLK_p]){ pause = !pause; } + if(input.keys_went_down[SDLK_k]){ + switch(current_kind){ + case simulation::kFallThrough: current_kind = simulation::kOneWay; set_text("draw mode: bouncy"); break; + case simulation::kOneWay: current_kind = simulation::kFallThrough; set_text("draw mode: guitar"); break; + } + + } + if(input.keys_went_down[SDLK_l]){ bool restore_drum = false; if(kick || snare){ @@ -295,10 +356,10 @@ namespace games { Base::draw(); } - void Client::update_peeps(std::string peeps){ + void Client::set_text(std::string peeps){ if(!peeps_lbl){ try { - peeps_lbl = std::make_shared("Peeps:", motor::bundle.get_font_path() + "Arial Rounded Bold.ttf", 72); + peeps_lbl = std::make_shared("", motor::bundle.get_font_path() + "Arial Rounded Bold.ttf", 72); peeps_lbl->get_mesh()->material->diffuse_color = {1.0f, 1.0f, 1.0f, 1.0f}; peeps_lbl->set_position({-95.0, -90.0, 0.0}); peeps_lbl->set_scale(motor::scale(0.05)); @@ -308,14 +369,12 @@ namespace games { CERR << e.what() << std::endl; } } - if(peeps == ""){ - peeps_lbl->set_text("No peeps online :(."); - } else { - peeps_lbl->set_text("Peeps: " + peeps); - } + peeps_lbl->set_text(peeps); } - void Client::update(float const dt, Input input){ + void Client::update(float dt, Input input){ + dt *= global_speed; + // motor Base::update(dt, input); handle_input(dt, input); @@ -361,18 +420,21 @@ namespace games { const float push_interval = 0.05; push_time += dt; - int ret = libwebsocket_service(context, 10); - if(ret < 0) { - CERR << "ERROR: libwebsocket returns < 0\n"; - } - if(push_time >= push_interval){ - libwebsocket_callback_on_writable(context, wsi); - push_time -= push_interval; + if(context && wsi){ + int ret = libwebsocket_service(context, 10); + if(ret < 0) { + CERR << "ERROR: libwebsocket returns < 0\n"; + } + if(push_time >= push_interval){ + libwebsocket_callback_on_writable(context, wsi); + push_time -= push_interval; + } } } Client::~Client(){ - libwebsocket_context_destroy(context); + if(context) + libwebsocket_context_destroy(context); current_client = nullptr; } } diff --git a/src/client/client.hpp b/src/client/client.hpp index 0f261af..1669949 100644 --- a/src/client/client.hpp +++ b/src/client/client.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -17,12 +18,17 @@ /* Controls: + mouse: draw linez 1, .. 9, 0: change chord (will also be done automatically) - q, w, e: music speed (= generation of balls) - z, x, c: simulation speed + k: change line kind a: toggle autopilot d: toggle drum p: pause + + q, w, e: music speed (= generation of balls) + z, x, c: simulation speed + -, + (without shift): global speed + r: reload scales (aka chords) s: reload shaders b: clear balls @@ -32,6 +38,7 @@ namespace games { struct Client : public Base { static constexpr char bundle_name[] = "client"; + float global_speed = 1.0; // websocket part libwebsocket_context * context{nullptr}; @@ -54,6 +61,7 @@ namespace games { void add_line(cheap_line_type const & line); void remove_line(int ID); + void remove_line(std::shared_ptr const & instr); void add_drum(); void remove_drum(); @@ -62,6 +70,12 @@ namespace games { float x2; float x3; + // Input part + cheap_line_type current_line; + bool drawing = false; + simulation::LineKind current_kind = simulation::kFallThrough; + std::stack> undo_stack; + // Sound part const std::vector scale_files{ ::bundle.get_sound_path() + "pentatonic.txt", // 0 a @@ -94,13 +108,13 @@ namespace games { }; float music_speed{1.0}; - bool auto_pilot{false}; + bool auto_pilot{true}; // Graphics GameRenderer game_renderer; std::shared_ptr peeps_lbl; - void update_peeps(std::string peeps); + void set_text(std::string peeps); // Base part Client(int window_width, int window_height, std::shared_ptr& active_base);