smalruby/dxruby_sdl

View on GitHub
lib/dxruby_sdl/input.rb

Summary

Maintainability
D
2 days
Test Coverage
# -*- coding: utf-8 -*-

require 'set'

module DXRubySDL
  module Input
    module_function

    def set_repeat(wait, interval)
      SDL::Key.enable_key_repeat(wait, interval)
    end

    def x(pad_number = 0)
      res = 0
      if sdl_key_press?(SDL::Key::LEFT)
        res -= 1
      end
      if sdl_key_press?(SDL::Key::RIGHT)
        res += 1
      end
      return res
    end

    def y(pad_number = 0)
      res = 0
      if sdl_key_press?(SDL::Key::UP)
        res -= 1
      end
      if sdl_key_press?(SDL::Key::DOWN)
        res += 1
      end
      return res
    end

    def pad_down?(button_code, pad_number = 0)
      if button_code == P_BUTTON0 && sdl_key_press?(SDL::Key::Z) ||
          button_code == P_BUTTON1 && sdl_key_press?(SDL::Key::X) ||
          button_code == P_BUTTON2 && sdl_key_press?(SDL::Key::C) ||
          button_code == P_LEFT && sdl_key_press?(SDL::Key::LEFT) ||
          button_code == P_RIGHT && sdl_key_press?(SDL::Key::RIGHT) ||
          button_code == P_UP && sdl_key_press?(SDL::Key::UP) ||
          button_code == P_DOWN && sdl_key_press?(SDL::Key::DOWN) ||
          ((j = joystick(pad_number)) && j.button(button_code))
        return true
      end
      return false
    end

    def pad_push?(button_code, pad_number = 0)
      if button_code == P_BUTTON0 && sdl_key_push?(SDL::Key::Z) ||
          button_code == P_BUTTON1 && sdl_key_push?(SDL::Key::X) ||
          button_code == P_BUTTON2 && sdl_key_push?(SDL::Key::C) ||
          button_code == P_LEFT && sdl_key_push?(SDL::Key::LEFT) ||
          button_code == P_RIGHT && sdl_key_push?(SDL::Key::RIGHT) ||
          button_code == P_UP && sdl_key_push?(SDL::Key::UP) ||
          button_code == P_DOWN && sdl_key_push?(SDL::Key::DOWN) ||
          ((j = joystick(pad_number)) && j.button(button_code))
        return true
      end
      return false
    end

    def mouse_pos_x
      return SDL::Mouse.state[0]
    end

    def mouse_pos_y
      return SDL::Mouse.state[1]
    end

    def key_down?(key_code)
      return sdl_key_press?(to_sdl_key(key_code))
    end

    def key_push?(key_code)
      return sdl_key_push?(to_sdl_key(key_code))
    end

    def mouse_down?(button)
      case button
      when M_LBUTTON
        index = 2
      when M_MBUTTON
        index = 3
      when M_RBUTTON
        index = 4
      end
      return SDL::Mouse.state[index]
    end

    def mouse_push?(button)
      case button
      when M_LBUTTON
        index = 2
      when M_MBUTTON
        index = 3
      when M_RBUTTON
        index = 4
      end
      return SDL::Mouse.state[index] && !@last_mouse_state[index]
    end

    def keys
      return @keys
    end

    class << self
      alias_method :setRepeat, :set_repeat
      alias_method :padDown?, :pad_down?
      alias_method :padPush?, :pad_push?
      alias_method :mousePosX, :mouse_pos_x
      alias_method :mousePosY, :mouse_pos_y
      alias_method :keyDown?, :key_down?
      alias_method :keyPush?, :key_push?
      alias_method :mouseDown?, :mouse_down?
      alias_method :mousePush?, :mouse_push?
    end

    private

    @keys = Set.new
    @checked_keys = Set.new
    @down_keys = Set.new
    @last_mouse_state = [false, false, false]
    @joysticks = []

    class << self

      private

      SDL_KEY_TABLE = {}
      replace_table = {
        'BACK' => 'BACKSPACE',
        'ADD' => 'PLUS',
        'DIVIDE' => 'SLASH',
        'LCONTROL' => 'LCTRL',
        'RCONTROL' => 'RCTRL',
        'SCROLL' => 'SCROLLOCK',
        'GRAVE' => 'BACKQUOTE',
        'LBRACKET' => 'LEFTBRACKET',
        'RBRACKET' => 'RIGHTBRACKET',
        'LWIN' => 'LSUPER',
        'RWIN' => 'RSUPER',
        'YEN' => 'BACKSLASH',
      }
      ::DXRubySDL.constants.grep(/^K_/).each do |k|
        name = k.to_s.sub(/^K_/, '')
        name.gsub!('COMMA', 'PERIOD')
        if replace_table.key?(name)
          name = replace_table[name]
        end
        case name
        when /^\d$/
          name = "K#{name}"
        when /^NUMPAD(.+)$/
          md = Regexp.last_match
          if md[1].length > 1
            name = "KP_#{md[1]}"
          else
            name = "KP#{md[1]}"
          end
        end
        begin
          SDL_KEY_TABLE[DXRubySDL.const_get(k)] =
            SDL::Key.const_get(name.to_sym)
        rescue NameError
        end
      end
      private_constant :SDL_KEY_TABLE

      DXRUBY_KEY_TABLE = SDL_KEY_TABLE.invert
      private_constant :DXRUBY_KEY_TABLE

      def store_last_state
        @down_keys.merge(@checked_keys)
        @checked_keys.clear
        @last_mouse_state = SDL::Mouse.state
      end

      def sdl_key_press?(key)
        dkey = to_dxruby_key(key)
        if @keys.include?(dkey)
          @checked_keys.add(dkey)
          return true
        else
          return false
        end
      end

      def sdl_key_push?(key)
        dkey = to_dxruby_key(key)
        return sdl_key_press?(key) && !@down_keys.include?(dkey)
      end

      def joystick(pad_number)
        if pad_number >= SDL::Joystick.num
          return nil
        end
        if !@joysticks[pad_number]
          @joysticks[pad_number] = SDL::Joystick.open(pad_number)
        end
        return @joysticks[pad_number]
      end

      def to_sdl_key(key_code)
        return SDL_KEY_TABLE[key_code]
      end

      def to_dxruby_key(key_code)
        return DXRUBY_KEY_TABLE[key_code]
      end

      def handle_key_event(event)
        dkey = to_dxruby_key(event.sym)
        case event
        when SDL::Event::KeyDown
          @keys.add(dkey)
        when SDL::Event::KeyUp
          @keys.delete(dkey)
          @checked_keys.delete(dkey)
          @down_keys.delete(dkey)
        end
      end
    end
  end
end