From b13074ebe542aa25c5b3b08afed4b60e1d23e1c6 Mon Sep 17 00:00:00 2001 From: Tom Black Date: Sat, 2 Dec 2017 21:58:07 -0800 Subject: Use controller mappings --- ext/ruby2d/ruby2d.c | 111 +++++++++++++++++++++++----- lib/ruby2d/window.rb | 18 ++--- test/controller.rb | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 302 insertions(+), 31 deletions(-) diff --git a/ext/ruby2d/ruby2d.c b/ext/ruby2d/ruby2d.c index 6cbe219..1b1bb5e 100644 --- a/ext/ruby2d/ruby2d.c +++ b/ext/ruby2d/ruby2d.c @@ -68,7 +68,7 @@ #define r_args_none (MRB_ARGS_NONE()) #define r_args_req(n) MRB_ARGS_REQ(n) // Helpers - #define r_char_to_sym(str) mrb_check_intern_cstr(mrb, str) + #define r_char_to_sym(str) mrb_symbol_value(mrb_intern_cstr(mrb, str)) #else // Ruby #define R_VAL VALUE @@ -144,6 +144,14 @@ static void free_window() { } +/* + * Normalize controller axis values to 0.0...1.0 + */ +double normalize_controller_axis(int val) { + return val > 0 ? val / 32767.0 : val / 32768.0; +} + + /* * File#exists? for MRuby */ @@ -696,7 +704,7 @@ void on_mouse(S2D_Event e) { // type, direction, delta_x, delta_y type = r_char_to_sym("scroll"); direction = e.direction == S2D_MOUSE_SCROLL_NORMAL ? - r_str_new("normal") : r_str_new("inverted"); + r_char_to_sym("normal") : r_char_to_sym("inverted"); break; case S2D_MOUSE_MOVE: // type, x, y, delta_x, delta_y @@ -707,26 +715,23 @@ void on_mouse(S2D_Event e) { if (e.type == S2D_MOUSE_DOWN || e.type == S2D_MOUSE_UP) { switch (e.button) { case S2D_MOUSE_LEFT: - button = r_str_new("left"); + button = r_char_to_sym("left"); break; case S2D_MOUSE_MIDDLE: - button = r_str_new("middle"); + button = r_char_to_sym("middle"); break; case S2D_MOUSE_RIGHT: - button = r_str_new("right"); + button = r_char_to_sym("right"); break; case S2D_MOUSE_X1: - button = r_str_new("x1"); + button = r_char_to_sym("x1"); break; case S2D_MOUSE_X2: - button = r_str_new("x2"); + button = r_char_to_sym("x2"); break; } } - // Bug in MRuby: If `button` or `direction` are symbols (created with - // r_char_to_sym), they will always both be `nil`. Use `r_str_new` for now. - r_funcall( ruby2d_window, "mouse_callback", 7, type, button, direction, INT2NUM(e.x), INT2NUM(e.y), INT2NUM(e.delta_x), INT2NUM(e.delta_y) @@ -739,23 +744,93 @@ void on_mouse(S2D_Event e) { */ static void on_controller(S2D_Event e) { - R_VAL type = R_NIL; + R_VAL type = R_NIL; R_VAL axis = R_NIL; R_VAL button = R_NIL; switch (e.type) { case S2D_AXIS: type = r_char_to_sym("axis"); + switch (e.axis) { + case S2D_AXIS_LEFTX: + axis = r_char_to_sym("left_x"); + break; + case S2D_AXIS_LEFTY: + axis = r_char_to_sym("left_y"); + break; + case S2D_AXIS_RIGHTX: + axis = r_char_to_sym("right_x"); + break; + case S2D_AXIS_RIGHTY: + axis = r_char_to_sym("right_y"); + break; + case S2D_AXIS_TRIGGERLEFT: + axis = r_char_to_sym("trigger_left"); + break; + case S2D_AXIS_TRIGGERRIGHT: + axis = r_char_to_sym("trigger_right"); + break; + case S2D_AXIS_INVALID: + axis = r_char_to_sym("invalid"); + break; + } break; - case S2D_BUTTON_DOWN: - type = r_char_to_sym("button_down"); - break; - case S2D_BUTTON_UP: - type = r_char_to_sym("button_up"); + case S2D_BUTTON_DOWN: case S2D_BUTTON_UP: + type = e.type == S2D_BUTTON_DOWN ? r_char_to_sym("button_down") : r_char_to_sym("button_up"); + switch (e.button) { + case S2D_BUTTON_A: + button = r_char_to_sym("a"); + break; + case S2D_BUTTON_B: + button = r_char_to_sym("b"); + break; + case S2D_BUTTON_X: + button = r_char_to_sym("x"); + break; + case S2D_BUTTON_Y: + button = r_char_to_sym("y"); + break; + case S2D_BUTTON_BACK: + button = r_char_to_sym("back"); + break; + case S2D_BUTTON_GUIDE: + button = r_char_to_sym("guide"); + break; + case S2D_BUTTON_START: + button = r_char_to_sym("start"); + break; + case S2D_BUTTON_LEFTSTICK: + button = r_char_to_sym("left_stick"); + break; + case S2D_BUTTON_RIGHTSTICK: + button = r_char_to_sym("right_stick"); + break; + case S2D_BUTTON_LEFTSHOULDER: + button = r_char_to_sym("left_shoulder"); + break; + case S2D_BUTTON_RIGHTSHOULDER: + button = r_char_to_sym("right_shoulder"); + break; + case S2D_BUTTON_DPAD_UP: + button = r_char_to_sym("up"); + break; + case S2D_BUTTON_DPAD_DOWN: + button = r_char_to_sym("down"); + break; + case S2D_BUTTON_DPAD_LEFT: + button = r_char_to_sym("left"); + break; + case S2D_BUTTON_DPAD_RIGHT: + button = r_char_to_sym("right"); + break; + case S2D_BUTTON_INVALID: + button = r_char_to_sym("invalid"); + break; + } break; } r_funcall( - ruby2d_window, "controller_callback", 5, INT2NUM(e.which), type, - INT2NUM(e.axis), INT2NUM(e.value), INT2NUM(e.button) + ruby2d_window, "controller_callback", 5, INT2NUM(e.which), + type, axis, DBL2NUM(normalize_controller_axis(e.value)), button ); } diff --git a/lib/ruby2d/window.rb b/lib/ruby2d/window.rb index 0a5a995..686c6b0 100644 --- a/lib/ruby2d/window.rb +++ b/lib/ruby2d/window.rb @@ -6,10 +6,12 @@ module Ruby2D attr_reader :objects attr_accessor :mouse_x, :mouse_y, :frames, :fps - MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y) - KeyEvent = Struct.new(:type, :key) - ControllerEvent = Struct.new(:which, :type, :axis, :value, :button) EventDescriptor = Struct.new(:type, :id) + MouseEvent = Struct.new(:type, :button, :direction, :x, :y, :delta_x, :delta_y) + KeyEvent = Struct.new(:type, :key) + ControllerEvent = Struct.new(:which, :type, :axis, :value, :button) + ControllerAxisEvent = Struct.new(:which, :axis, :value) + ControllerButtonEvent = Struct.new(:which, :button) def initialize(args = {}) @title = args[:title] || "Ruby 2D" @@ -173,10 +175,6 @@ module Ruby2D end def mouse_callback(type, button, direction, x, y, delta_x, delta_y) - # Convert to symbols (see MRuby bug in native extension) - button = button.to_sym unless button == nil - direction = direction.to_sym unless direction == nil - # All mouse events @events[:mouse].each do |id, e| e.call(MouseEvent.new(type, button, direction, x, y, delta_x, delta_y)) @@ -216,17 +214,17 @@ module Ruby2D # When controller axis motion, like analog sticks when :axis @events[:controller_axis].each do |id, e| - e.call(ControllerEvent.new(which, type, axis, value, nil)) + e.call(ControllerAxisEvent.new(which, axis, value)) end # When controller button is pressed when :button_down @events[:controller_button_down].each do |id, e| - e.call(ControllerEvent.new(which, type, nil, nil, button)) + e.call(ControllerButtonEvent.new(which, button)) end # When controller button is released when :button_up @events[:controller_button_up].each do |id, e| - e.call(ControllerEvent.new(which, type, nil, nil, button)) + e.call(ControllerButtonEvent.new(which, button)) end end end diff --git a/test/controller.rb b/test/controller.rb index b4de79a..5035ebb 100644 --- a/test/controller.rb +++ b/test/controller.rb @@ -1,6 +1,180 @@ require 'ruby2d' -set title: "Ruby 2D — Controller", width: 300, height: 200 +set title: "Ruby 2D — Controller", width: 600, height: 425 +set diagnostics: true + +# Controller outline image +controller = Image.new(path: 'media/controller.png') + +scale = 80 + +axis_left_x = Quad.new( + x1: 156, y1: 130, + x2: 156, y2: 130, + x3: 156, y3: 159, + x4: 156, y4: 159, + color: [0, 1, 0, 1] +) + +axis_left_y = Quad.new( + x1: 142, y1: 145, + x2: 171, y2: 145, + x3: 171, y3: 145, + x4: 142, y4: 145, + color: [0, 1, 0, 1] +) + +axis_right_x = Quad.new( + x1: 374, y1: 215, + x2: 374, y2: 215, + x3: 374, y3: 244, + x4: 374, y4: 244, + color: [0, 1, 0, 1] +) + +axis_right_y = Quad.new( + x1: 359, y1: 229, + x2: 388, y2: 229, + x3: 388, y3: 229, + x4: 359, y4: 229, + color: [0, 1, 0, 1] +) + +axis_trigger_left = Quad.new( + x1: 8, y1: 71, + x2: 42, y2: 71, + x3: 42, y3: 71, + x4: 8, y4: 71, + color: [0, 1, 0, 1] +) + +axis_trigger_right = Quad.new( + x1: 8 + 550, y1: 71, + x2: 42 + 550, y2: 71, + x3: 42 + 550, y3: 71, + x4: 8 + 550, y4: 71, + color: [0, 1, 0, 1] +) + +@btn_a = Quad.new( + x1: 426, y1: 167, + x2: 426 + 33, y2: 167, + x3: 426 + 33, y3: 167 + 33, + x4: 426, y4: 167 + 33, + color: [0, 1, 0, 0] +) + +@btn_b = Quad.new( + x1: 464, y1: 129, + x2: 464 + 33, y2: 129, + x3: 464 + 33, y3: 129 + 33, + x4: 464, y4: 129 + 33, + color: [1, 0, 0, 0] +) + +@btn_x = Quad.new( + x1: 388, y1: 128, + x2: 388 + 33, y2: 128, + x3: 388 + 33, y3: 128 + 33, + x4: 388, y4: 128 + 33, + color: [0, 0.7, 1, 0] +) + +@btn_y = Quad.new( + x1: 426, y1: 91, + x2: 426 + 33, y2: 91, + x3: 426 + 33, y3: 91 + 33, + x4: 426, y4: 91 + 33, + color: [1, 1, 0, 0] +) + +@btn_back = Quad.new( + x1: 248, y1: 133, + x2: 248 + 23, y2: 133, + x3: 248 + 23, y3: 133 + 23, + x4: 248, y4: 133 + 23, + color: [1, 0.5, 0, 0] +) + +@btn_guide = Quad.new( + x1: 281, y1: 69, + x2: 281 + 38, y2: 69, + x3: 281 + 38, y3: 69 + 38, + x4: 281, y4: 69 + 38, + color: [0.5, 1, 0.5, 0] +) + +@btn_start = Quad.new( + x1: 331, y1: 133, + x2: 331 + 23, y2: 133, + x3: 331 + 23, y3: 133 + 23, + x4: 331, y4: 133 + 23, + color: [1, 0.5, 0, 0] +) + +@btn_left_stick = Quad.new( + x1: 8, y1: 4, + x2: 8 + 34, y2: 4, + x3: 8 + 38, y3: 4 + 67, + x4: 8 - 4, y4: 4 + 67, + color: [1, 0, 0, 0] +) + +@btn_right_stick = Quad.new( + x1: 558, y1: 4, + x2: 558 + 34, y2: 4, + x3: 558 + 38, y3: 4 + 67, + x4: 558 - 4, y4: 4 + 67, + color: [1, 0, 0, 0] +) + +@btn_left_shoulder = Quad.new( + x1: 111, y1: 84, + x2: 117, y2: 64, + x3: 198, y3: 39, + x4: 225, y4: 52, + color: [0.5, 0, 1, 0] +) + +@btn_right_shoulder = Quad.new( + x1: 494, y1: 85, + x2: 484, y2: 64, + x3: 401, y3: 39, + x4: 378, y4: 51, + color: [0.5, 0, 1, 0] +) + +@btn_up = Quad.new( + x1: 216, y1: 194, + x2: 216 + 23, y2: 194, + x3: 216 + 23, y3: 194 + 28, + x4: 216, y4: 194 + 28, + color: [1, 0, 0.5, 0] +) + +@btn_down = Quad.new( + x1: 216, y1: 243, + x2: 216 + 23, y2: 243, + x3: 216 + 23, y3: 243 + 27, + x4: 216, y4: 243 + 27, + color: [1, 0, 0.5, 0] +) + +@btn_left = Quad.new( + x1: 189, y1: 221, + x2: 189 + 28, y2: 221, + x3: 189 + 28, y3: 221 + 22, + x4: 189, y4: 221 + 22, + color: [1, 0, 0.5, 0] +) + +@btn_right = Quad.new( + x1: 238, y1: 221, + x2: 238 + 28, y2: 221, + x3: 238 + 28, y3: 221 + 22, + x4: 238, y4: 221 + 22, + color: [1, 0, 0.5, 0] +) on :controller do |event| puts event @@ -8,14 +182,38 @@ end on :controller_axis do |event| puts "Axis: #{event.axis}, Value: #{event.value}" + case event.axis + when :left_x + axis_left_x.x2 = 156 + event.value * scale + axis_left_x.x3 = 156 + event.value * scale + when :left_y + axis_left_y.y1 = 145 + event.value * scale + axis_left_y.y2 = 145 + event.value * scale + when :right_x + axis_right_x.x2 = 374 + event.value * scale + axis_right_x.x3 = 374 + event.value * scale + when :right_y + axis_right_y.y1 = 229 + event.value * scale + axis_right_y.y2 = 229 + event.value * scale + when :trigger_left + axis_trigger_left.y1 = 71 - event.value * 67 + axis_trigger_left.y2 = 71 - event.value * 67 + when :trigger_right + axis_trigger_right.y1 = 71 - event.value * 67 + axis_trigger_right.y2 = 71 - event.value * 67 + end end on :controller_button_down do |event| - puts "Button down: #{event.button}" + instance_variable_get("@btn_#{event.button}").opacity = 1.0 end on :controller_button_up do |event| - puts "Button up: #{event.button}" + instance_variable_get("@btn_#{event.button}").opacity = 0 +end + +on :key_down do |event| + close if event.key == 'escape' end show -- cgit v1.2.3