Skip to content

Instantly share code, notes, and snippets.

@mirichi
Created September 20, 2015 07:28
Show Gist options
  • Save mirichi/c7cb3f02ce451910ddbc to your computer and use it in GitHub Desktop.
Save mirichi/c7cb3f02ce451910ddbc to your computer and use it in GitHub Desktop.
sdl2rでDXRuby互換ぽいライブラリを作る(6)
require 'sdl2r'
require_relative 'fpstimer'
SDL.init(SDL::INIT_EVERYTHING)
module DXRuby
C_WHITE = [255, 255, 255]
C_RED = [255, 0, 0]
module Window
@width = 640
@height = 480
@window = SDL.create_window("dxsdl2r Sample Application",
SDL::WINDOWPOS_UNDEFINED,
SDL::WINDOWPOS_UNDEFINED,
@width,
@height,
SDL::WINDOW_HIDDEN)
@renderer = SDL.create_renderer(@window, -1, 0)
def self.width;@width;end
def self.height;@height;end
def self._window;@window;end
def self._renderer;@renderer;end
def self.width=(v);@width=v;end
def self.height=(v);@height=v;end
# 描画予約配列
@reservation = []
def self.draw_box_fill(x1, y1, x2, y2, color, z=0)
tmp = DXRuby._convert_color_dxruby_to_sdl(color)
prc = ->{
SDL.set_render_draw_color(@renderer, tmp[0], tmp[1], tmp[2], tmp[3])
SDL.render_fill_rect(@renderer, SDL::Rect.new(x1, y1, x2 - x1 + 1, y2 - y1 + 1))
}
@reservation << [z, prc]
end
def self.draw(x, y, image, z=0)
prc = ->{
image._create_texture unless image._texture
SDL.render_copy(@renderer, image._texture, nil, SDL::Rect.new(x, y, image.width, image.height))
}
@reservation << [z, prc]
end
def self.loop
timer = FPSTimer.instance
timer.reset
SDL.set_window_size(@window, @width, @height)
SDL.show_window(@window)
Kernel.loop do
timer.wait_frame do
return if Input.update
SDL.set_render_draw_color(@renderer, 0, 0, 0, 255)
SDL.render_clear(@renderer)
yield
@reservation.sort_by!{|v|v[0]}.each{|v|v[1].call}
@reservation.clear
SDL.render_present(@renderer)
end
end
end
def self.fps=(v)
FPSTimer.instance.fps = v
end
def self.real_fps
FPSTimer.instance.real_fps
end
def self.caption
SDL.get_window_title(@window)
end
def self.caption=(str)
SDL.set_window_title(@window, str)
str
end
end
module Input
# マウスの情報
@mouse_button = @mouse_x = @mouse_y = 0
@old_mouse_button = @old_mouse_x = @old_mouse_y = 0
# キーボードの情報
@keys = []
@old_keys = []
# 内部情報の公開
def self._mouse_button;@mouse_button;end
def self._old_mouse_button;@old_mouse_button;end
def self._keys;@keys;end
def self._old_keys;@old_keys;end
# マウスボタン判定用クラス
class MouseButton
def initialize(b) # 1が左、2が真ん中、3が右
@button = b
end
def down?
(SDL::BUTTON(@button) & Input._mouse_button) != 0
end
def push?
(SDL::BUTTON(@button) & Input._mouse_button) != 0 and
(SDL::BUTTON(@button) & Input._old_mouse_button) == 0
end
def release?
(SDL::BUTTON(@button) & Input._mouse_button) == 0 and
(SDL::BUTTON(@button) & Input._old_mouse_button) != 0
end
end
# キーボード判定用クラス
class Keyboard
def initialize(k)
@key = k
end
def down?
Input._keys[@key]
end
def push?
Input._keys[@key] and !Input._old_keys[@key]
end
def release?
!Input._keys[@key] and Input._old_keys[@key]
end
end
# 各種判定メソッド
# 一応DXRuby互換で複数用意しているが中身はどれも同じ
def self.push?(button);button.push?;end
def self.down?(button);button.down?;end
def self.release?(button);button.release?;end
def self.mouse_push?(button);button.push?;end
def self.mouse_down?(button);button.down?;end
def self.mouse_release?(button);button.release?;end
def self.key_push?(button);button.push?;end
def self.key_down?(button);button.down?;end
def self.key_release?(button);button.release?;end
def self.mouse_x
@mouse_x
end
def self.mouse_y
@mouse_y
end
def self.x
x = 0
x -= 1 if K_LEFT.down?
x += 1 if K_RIGHT.down?
x
end
def self.y
y = 0
y -= 1 if K_UP.down?
y += 1 if K_DOWN.down?
y
end
def self.update
# 押されているキー一覧を取得する
@old_keys = @keys
@keys = SDL.get_keyboard_state
# マウスの状態を取得する
@old_mouse_button, @old_mouse_x, @old_mouse_y = @mouse_button, @mouse_x, @mouse_y
@mouse_button, @mouse_x, @mouse_y = SDL.get_mouse_state
# SDL2のイベント処理
while event = SDL.poll_event do
case event.type
when SDL::QUIT
return true
end
end
false
end
end
# ボタン定数
M_LBUTTON = Input::MouseButton.new(1)
M_MBUTTON = Input::MouseButton.new(2)
M_RBUTTON = Input::MouseButton.new(3)
K_LEFT = Input::Keyboard.new(SDL::SCANCODE_LEFT)
K_RIGHT = Input::Keyboard.new(SDL::SCANCODE_RIGHT)
K_UP = Input::Keyboard.new(SDL::SCANCODE_UP)
K_DOWN = Input::Keyboard.new(SDL::SCANCODE_DOWN)
K_SPACE = Input::Keyboard.new(SDL::SCANCODE_SPACE)
K_ESCAPE = Input::Keyboard.new(SDL::SCANCODE_ESCAPE)
K_Z = Input::Keyboard.new(SDL::SCANCODE_Z)
K_X = Input::Keyboard.new(SDL::SCANCODE_X)
K_C = Input::Keyboard.new(SDL::SCANCODE_C)
class Image
attr_accessor :_surface, :_texture, :_pixels
def self.load(filename)
image = Image.new(0, 0)
image._surface = SDL::IMG.load(filename)
image._pixels = image._surface.pixels
image
end
def self.load_tiles(filename, cx, cy)
surface = SDL::IMG.load(filename)
w, h = surface.w, surface.h
ary = []
cy.times do |y|
cx.times do |x|
tmp = Image.new(0, 0)
# IntelCPUはリトルエンディアンだがビッグエンディアンにも一応対応しておく
# 画像フォーマットは32bit固定
if SDL::BYTEORDER == SDL::BIG_ENDIAN
tmp._surface = SDL.create_rgb_surface(0, w / cx, h / cy, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff)
else
tmp._surface = SDL.create_rgb_surface(0, w / cx, h / cy, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
end
SDL.blit_surface(surface, SDL::Rect.new(w / cx * x, h / cy * y, w / cx, h / cy), tmp._surface, nil)
tmp._pixels = tmp._surface.pixels
ary << tmp
end
end
ary
end
def initialize(w, h, color=[0, 0, 0, 0])
# wとhの両方が0の場合はSurfaceを生成しない
return if w == 0 and h == 0
# IntelCPUはリトルエンディアンだがビッグエンディアンにも一応対応しておく
# 画像フォーマットは32bit固定
if SDL::BYTEORDER == SDL::BIG_ENDIAN
@_surface = SDL.create_rgb_surface(0, w, h, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff)
else
@_surface = SDL.create_rgb_surface(0, w, h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
end
# 指定色で塗りつぶす
SDL.fill_rect(@_surface, nil, DXRuby._convert_color_dxruby_to_sdl(color))
# Pixelsオブジェクト取得
@_pixels = @_surface.pixels
end
def width
@_surface.w
end
def height
@_surface.h
end
# テクスチャを破棄する
# 次に描画で使われる際に再生成される
def _modify
if @_texture
SDL.destroy_texture(@_texture)
@_texture = nil
end
nil
end
# テクスチャ生成
def _create_texture
# テクスチャ生成
@_texture = SDL.create_texture_from_surface(Window._renderer, @_surface)
end
# ピクセルに色を置く
def []=(x, y, color)
tmp = @_pixels[x, y] = DXRuby._convert_color_dxruby_to_sdl(color)
self._modify
tmp
end
# ピクセルの色を取得する
def [](x, y)
tmp = @_pixels[x, y]
self._modify
tmp
end
end
# DXRuby色配列からSDL::Color色配列へ変換
def self._convert_color_dxruby_to_sdl(color)
if color.size == 3
color + [255]
else
color[1..3] << color[0]
end
end
end
include DXRuby
END{
SDL.quit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment