NimでSDL2 ② 画像を表示


はじめに

NimでSDL2 ① 準備とウィンドウ表示

前回ウィンドウを表示したので、今回は画像を読み込んで表示してみる。

概要

  1. sdl2/imageをimportする。
  2. SDL2初期化時にINIT_VIDEOフラグを立てて初期化する。
  3. image.initに資料する画像タイプを指定して初期化する(今回はpngを使用する)
  4. createRenderer関数でWindowからレンダリングコンテキストを作成する。
  5. レンダリングコンテキストで背景色を設定
  6. レンダリングコンテキストで画像を読み込んでテクスチャを作成する。
  7. レンダリングコンテキストでテクスチャの一部、または全体を指定箇所にレンダリングする。
  8. レンダリングコンテキストのレンダリング結果をがめんに反映する。

コード

import sdl2, sdl2/image, os
const
  WINDOW_W = 640
  WINDOW_H = 480

proc main() =
  if not sdl2.init(INIT_VIDEO): # 画像を扱うのでINIT_VIDEOフラグを立てて初期化
    raise Exception.newException("[ERROR] SDL2 init: " & $getError())
  defer: sdl2.quit()
  let window = createWindow(title = "SDL2 Image Sample",
                            x = SDL_WINDOWPOS_CENTERED,
                            y = SDL_WINDOWPOS_CENTERED,
                            w = 640,
                            h = 480,
                            flags = SDL_WINDOW_SHOWN)
  if window.isNil:
    raise Exception.newException("[ERROR] createWindow: " & $getError())
  defer: window.destroy
  # image初期化
  if image.init(IMG_INIT_PNG) != IMG_INIT_PNG:
    raise Exception.newException("[ERROR] image init: " & $getError())
  # imageクリーンアップ処理
  defer: image.quit()
  # windowからrenderer作成
  let renderer = window.createRenderer(
    index = -1,
    flags = Renderer_Accelerated or Renderer_PresentVsync)
  # renderer作成エラーチェック
  if renderer.isNil:
    raise Exception.newException("[ERROR] createRenderer: " & $getError())
  # rendererクリーンアップ
  defer: renderer.destroy
  # 背景色を設定
  renderer.setDrawColor(r=0, g=128, b=128)
  # rendererを使って画像を読み込んでテクスチャにする
  let neko = renderer.loadTexture("genbaneko.png")
  # 画像読み込みエラーチェック
  if neko.isNil:
    raise Exception.newException("[ERROR] loadTexture: " & $getError())
  # 画面初期化
  renderer.clear
  # 描画するサイズ
  let
    w: cint = 256 # 描画する画像の幅
    h: cint = 256 # 描画する画像の高さ
  # 描画先のRectを作成(画面の真ん中に描画)
  var dst = rect(cint(WINDOW_W/2 - w/2), cint(WINDOW_H/2 - h/2), w, h)
  # レンダリング(描画元はnilを指定しているので画像全体を描画)
  renderer.copyEx(neko, nil, dst.addr, 0.0, nil, SDL_FLIP_NONE)
  # レンダリング結果を画面に反映
  renderer.present
  var done = false
  while not done:
    var event = defaultEvent
    while pollEvent(event):
      case event.kind:
      of QuitEvent:
        done = true
      else:
        discard
    sleep(100)

main()

結果

次は?

キーボード入力とかしてみたいですね。

以上〜。