1
Fork 0

Added drawing and undoing

This commit is contained in:
Joshua Moerman 2013-06-01 18:11:59 +02:00
parent 39b71cc5c5
commit ee571c1b56
3 changed files with 117 additions and 33 deletions

View file

@ -92,7 +92,7 @@ void GameRenderer::draw(Client const & client){
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_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; auto modelViewProjectionMatrix = projectionMatrix;
std::swap(fbo1, fbo2); std::swap(fbo1, fbo2);
@ -118,13 +118,13 @@ void GameRenderer::draw(Client const & client){
gl::draw_arrays(GL_POINTS, 0, client.beat.notes.size()); 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); moggle::gl::blend_function(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
line_shader.s.use(); line_shader.s.use();
line_shader.s.uniform<matrix<float, 4>>("modelViewProjectionMatrix").set(modelViewProjectionMatrix); line_shader.s.uniform<matrix<float, 4>>("modelViewProjectionMatrix").set(modelViewProjectionMatrix);
lines.clear(); 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){ for(auto const & l : client.lines){
Color color = (l->line_kind == simulation::kFallThrough) Color color = (l->line_kind == simulation::kFallThrough)
? Color{1.0f, l->color_intensity, std::sin(l->color_intensity)} ? 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->starting_point, color});
lines.push_back({client.snare->end_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){ if(debug_draw){
for(auto const & l : client.sim.lines){ for(auto const & l : client.sim.lines){

View file

@ -38,7 +38,7 @@ namespace games {
} }
} else if (command == "peeps"){ } else if (command == "peeps"){
auto str = from_json<std::string>(object["data"]); auto str = from_json<std::string>(object["data"]);
current_client->update_peeps(str); current_client->set_text("Peeps: " + str);
} }
} catch(std::exception& e){ } catch(std::exception& e){
throw websockets::runtime_error(e.what()); throw websockets::runtime_error(e.what());
@ -115,6 +115,14 @@ namespace games {
lines_changed = true; lines_changed = true;
} }
void Client::remove_line(std::shared_ptr<Instrument> 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<Instrument> const & l){ return instr == l; }), w.end());
}
void Client::add_drum(){ void Client::add_drum(){
kick = std::make_shared<Instrument>(math::Vec2{x1 - 25.0f, window_height - 100.0f}, math::Vec2{x1 + 25.0f, window_height - 50.0f}, 1, -1); kick = std::make_shared<Instrument>(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])); kick->sound.reset(new motor::al::Source(sounds[2]));
@ -188,19 +196,19 @@ namespace games {
info.gid = -1; info.gid = -1;
info.uid = -1; info.uid = -1;
context = libwebsocket_create_context(&info); // context = libwebsocket_create_context(&info);
if(!context) throw std::runtime_error("context could not be created."); // if(!context) throw std::runtime_error("context could not be created.");
// std::string address = "127.0.0.1"; // std::string address = "127.0.0.1";
std::string address = "vadovas-studios.com"; std::string address = "vadovas-studios.com";
wsi = libwebsocket_client_connect(context, address.c_str(), 7681, false, "/", address.c_str(), "origin", "uberclient", -1); // 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."); // if(!wsi) throw std::runtime_error("socket could not be created.");
// motor // motor
world.physics.set_gravity({0.0, 0.0, 0.0}); world.physics.set_gravity({0.0, 0.0, 0.0});
hud->camera.set_orthographic(-100, 100, -100, 100, 1, -1); hud->camera.set_orthographic(-100, 100, -100, 100, 1, -1);
update_peeps(""); set_text("draw mode: guitar");
auto join_lbl = std::make_shared<motor::TextureLabel>("Join at: http://vadovas-studios.com/beats", motor::bundle.get_font_path() + "Arial Rounded Bold.ttf", 72); auto join_lbl = std::make_shared<motor::TextureLabel>("-/+: 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->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_position({-95.0, -95.0, 0.0});
join_lbl->set_scale(motor::scale(0.05)); join_lbl->set_scale(motor::scale(0.05));
@ -211,6 +219,26 @@ namespace games {
void Client::handle_input(float dt, Input input){ void Client::handle_input(float dt, Input input){
using motor::Position; 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]){ if(input.keys_went_down[SDLK_b]){
sim.balls.clear(); sim.balls.clear();
} }
@ -227,22 +255,55 @@ namespace games {
music_speed = 2.0; music_speed = 2.0;
} }
if(input.keys_went_down[SDLK_z]){ if(input.keys_went_down[SDLK_r]){
sim_speed = 0.5; sim_speed = 0.5;
} }
if(input.keys_went_down[SDLK_x]){ if(input.keys_went_down[SDLK_t]){
sim_speed = 1.0; sim_speed = 1.0;
} }
if(input.keys_went_down[SDLK_c]){ if(input.keys_went_down[SDLK_y]){
sim_speed = 2.0; sim_speed = 2.0;
} }
if(input.keys_went_down[SDLK_z] && !lines.empty()){
std::shared_ptr<Instrument> line = lines.back();
remove_line(line);
undo_stack.push(line);
}
if(input.keys_went_down[SDLK_x] && !undo_stack.empty()){
std::shared_ptr<Instrument> 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]){ if(input.keys_went_down[SDLK_p]){
pause = !pause; 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]){ if(input.keys_went_down[SDLK_l]){
bool restore_drum = false; bool restore_drum = false;
if(kick || snare){ if(kick || snare){
@ -295,10 +356,10 @@ namespace games {
Base::draw(); Base::draw();
} }
void Client::update_peeps(std::string peeps){ void Client::set_text(std::string peeps){
if(!peeps_lbl){ if(!peeps_lbl){
try { try {
peeps_lbl = std::make_shared<motor::TextureLabel>("Peeps:", motor::bundle.get_font_path() + "Arial Rounded Bold.ttf", 72); peeps_lbl = std::make_shared<motor::TextureLabel>("", 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->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_position({-95.0, -90.0, 0.0});
peeps_lbl->set_scale(motor::scale(0.05)); peeps_lbl->set_scale(motor::scale(0.05));
@ -308,14 +369,12 @@ namespace games {
CERR << e.what() << std::endl; CERR << e.what() << std::endl;
} }
} }
if(peeps == ""){ peeps_lbl->set_text(peeps);
peeps_lbl->set_text("No peeps online :(.");
} else {
peeps_lbl->set_text("Peeps: " + peeps);
}
} }
void Client::update(float const dt, Input input){ void Client::update(float dt, Input input){
dt *= global_speed;
// motor // motor
Base::update(dt, input); Base::update(dt, input);
handle_input(dt, input); handle_input(dt, input);
@ -361,18 +420,21 @@ namespace games {
const float push_interval = 0.05; const float push_interval = 0.05;
push_time += dt; push_time += dt;
int ret = libwebsocket_service(context, 10); if(context && wsi){
if(ret < 0) { int ret = libwebsocket_service(context, 10);
CERR << "ERROR: libwebsocket returns < 0\n"; if(ret < 0) {
} CERR << "ERROR: libwebsocket returns < 0\n";
if(push_time >= push_interval){ }
libwebsocket_callback_on_writable(context, wsi); if(push_time >= push_interval){
push_time -= push_interval; libwebsocket_callback_on_writable(context, wsi);
push_time -= push_interval;
}
} }
} }
Client::~Client(){ Client::~Client(){
libwebsocket_context_destroy(context); if(context)
libwebsocket_context_destroy(context);
current_client = nullptr; current_client = nullptr;
} }
} }

View file

@ -2,6 +2,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <stack>
#include <motor/sound/sound.hpp> #include <motor/sound/sound.hpp>
#include <motor/basic/texture_label.hpp> #include <motor/basic/texture_label.hpp>
@ -17,12 +18,17 @@
/* /*
Controls: Controls:
mouse: draw linez
1, .. 9, 0: change chord (will also be done automatically) 1, .. 9, 0: change chord (will also be done automatically)
q, w, e: music speed (= generation of balls) k: change line kind
z, x, c: simulation speed
a: toggle autopilot a: toggle autopilot
d: toggle drum d: toggle drum
p: pause p: pause
q, w, e: music speed (= generation of balls)
z, x, c: simulation speed
-, + (without shift): global speed
r: reload scales (aka chords) r: reload scales (aka chords)
s: reload shaders s: reload shaders
b: clear balls b: clear balls
@ -32,6 +38,7 @@
namespace games { namespace games {
struct Client : public Base { struct Client : public Base {
static constexpr char bundle_name[] = "client"; static constexpr char bundle_name[] = "client";
float global_speed = 1.0;
// websocket part // websocket part
libwebsocket_context * context{nullptr}; libwebsocket_context * context{nullptr};
@ -54,6 +61,7 @@ namespace games {
void add_line(cheap_line_type const & line); void add_line(cheap_line_type const & line);
void remove_line(int ID); void remove_line(int ID);
void remove_line(std::shared_ptr<Instrument> const & instr);
void add_drum(); void add_drum();
void remove_drum(); void remove_drum();
@ -62,6 +70,12 @@ namespace games {
float x2; float x2;
float x3; float x3;
// Input part
cheap_line_type current_line;
bool drawing = false;
simulation::LineKind current_kind = simulation::kFallThrough;
std::stack<std::shared_ptr<Instrument>> undo_stack;
// Sound part // Sound part
const std::vector<std::string> scale_files{ const std::vector<std::string> scale_files{
::bundle.get_sound_path() + "pentatonic.txt", // 0 a ::bundle.get_sound_path() + "pentatonic.txt", // 0 a
@ -94,13 +108,13 @@ namespace games {
}; };
float music_speed{1.0}; float music_speed{1.0};
bool auto_pilot{false}; bool auto_pilot{true};
// Graphics // Graphics
GameRenderer game_renderer; GameRenderer game_renderer;
std::shared_ptr<motor::TextureLabel> peeps_lbl; std::shared_ptr<motor::TextureLabel> peeps_lbl;
void update_peeps(std::string peeps); void set_text(std::string peeps);
// Base part // Base part
Client(int window_width, int window_height, std::shared_ptr<Base>& active_base); Client(int window_width, int window_height, std::shared_ptr<Base>& active_base);