1. OverView
どもども、今回はマウスイベントの取得を書いてみたいと思います。
やるタスクは二つ
- どう情報を表示しようか?
- イベントはどうやろうか?
…うん、Cursesで表示は今回はやめとくか…
2. 本文
2.1 まずは本体
さて、Your first Exray applicationを参考に、プログラムの構造を決めましょう。
うん、コピペなんだけどね。まずはプログラムの構造が決まってないと、書けないんだよ、おっさんだから。
ソースコードにコメントしていきますが、3つのプライベート関数(main_loop()、update()、draw())と、
実際にこのモジュールに入るためのパブリック関数(run())を作成する様です。
main_loopから、update(), draw()を呼び出す構造ですね。
drawは、画面描画をそこに入れるのが慣例の様ですが、updateはゲーム自体のupdateですかね?
defp main_loop() do
# Stay out of update and draw unless our window is ready to update and draw.
unless window_is_ready?(), do: main_loop()
# If at any point we press Raylib's default "Quit Application" key, (ESCAPE), stop looping and exit.
unless window_should_close?() do
update()
draw()
main_loop()
end
end
Stage 2; adding Raylib stuff
では、こいつをベースに、やっていきます。
defmodule SuperCoolGame do
# Exray.Core.Windowのimport
import Exray.Core.Window
# window_should_close?()イベントをポーリングするため、Exray.Core.Drawingもインポートします。
# end_draw()がないと、入力がまったくポーリングされないそうです。
import Exray.Core.Drawing
# FPSをセットするために、Exray.Core.Timingをimportします。 This is VERY important.だそうな。
import Exray.Core.Timing
# マウスを使うために、importします。
import Exray.Core.Input.Mouse
# テキストを描画する為に、importします。
import Exray.Text.Drawing
# Runを定義します。
# これは、publicな関数で、外部から呼び出される本体です。
def run(width \\ 200, height \\ 200, title \\ "Hello World!") do
# ウィンドウを初期化します。
init_window(width, height, title)
# init_windowを下すぐ後に、FPSを設定します。"SUPER important! Call"だそうで、やらんとsegvしまくります。
set_target_fps(60)
# main_loopの呼び出し
main_loop()
# WindowsがCloseしなかった場合、ここで再度 window_should_close?()でチェックし、close_window()します。
if window_should_close?() do
close_window()
end
:ok # :ok, because we're :ok :)
end
# mail loopです。
defp main_loop() do
# ウィンドウが更新および描画の準備が出来るまで、ここで再帰呼び出しして、これより下のupdateおよびdrawを実行しません。
unless window_is_ready?(), do: main_loop()
# Raylib's default "Quit Application" key, (ESCAPE)が押されるまで、実行を続けます。
unless window_should_close?() do
update()
draw()
main_loop()
end
end
# ゲームをupdateします。
defp update() do
# Nothing yet!
end
defp draw() do
# 描画する前に、Exray.Utils.Colors.black関数の結果で背景をクリアします
clear_background(Exray.Utils.Colors.black())
begin_drawing()
# Nothing yet!
end_drawing()
end
end
2.2 どう情報を表示しようか?
Exray.Text.Drawingを調べると、draw_text/5がありましてこいつを使いましょう。
https://hexdocs.pm/exray/Exray.Text.Drawing.html#draw_text/5
こいつの説明は簡単なので省くとして、以下の様にdraw/0をdraw/1へと書き直しております。
マップ。display_itemsで受け取った以下の様なmapを、受け取って、表示されましょう。
%{display_string: 画面のx, x: マウスのx座標, y: マウスのx座標}
コードはこちら、
begin_drawing()とend_drawing()の間でdraw_text/5を実行していることに注意してください。
defp draw(display_items) do
# Before drawing, we'll clear the background with the Exray.Utils.Colors.black function result- Which is %Exray.Structs.Color{r: 0, g: 0, b: 0, a: 255}.
clear_background(Colors.white)
begin_drawing()
draw_text( ~s/#{display_items.display_string} X: #{display_items.x} Y:#{display_items.y}/ , 20, 20, 12, Colors.red)
# Basic.draw_circle(100, 100, 50.0, Colors.red)
end_drawing()
end
2.3 マウスの情報はどう取ろう?
import Exray.Core.Input.Mouseを使うんです。
どーせ、ボタンとか押すのはあるはずだがら、今回はシンプルにx, yだけ採取しましょう
関数名 | 機能 |
---|---|
get_mouse_x() | マウスのX軸の座標を取得する |
get_mouse_y() | マウスのy軸の座標を取得する |
さて、update()に書き込んでみましょう。
defp update() do
%{display_string: "test", x: get_mouse_x(), y: get_mouse_y()}
end
合わせて、mail_loopもちょっと弄ります。
unless window_should_close?() do
display_items = update()
draw(display_items)
:timer.sleep(100)
main_loop()
end
2.4 、まとめ
本日のソースは、こうなりました。
みなさん、動いたでしょうか?
次回は、もう少し派手に張ろうぜ、派手に。
defmodule Mouseexample do
# We import Exray.Core.Window, like we did in IEX.
import Exray.Core.Window
# But, we also import Exray.Core.Drawing, to have access to begin_draw() and end_draw() calls.
# This is to poll for window_should_close?() events, as without end_draw() no inputs will be polled at all.
import Exray.Core.Drawing
# We also need to import Exray.Core.Timing in order to set our FPS. This is VERY important.
import Exray.Core.Timing
import Exray.Core.Input.Mouse
import Exray.Text.Drawing
alias Exray.Utils.Colors
alias Exray.Shapes.Basic
def run do
width = 200
height = 200
title = "Hello World!"
init_window(width, height, title)
set_target_fps(60) # <-- SUPER important! Call this just after you init_window, or segfaults are gonna happen a lot.
main_loop()
end
defp main_loop do
# Stay out of update and draw unless our window is ready to update and draw.
unless window_is_ready?(), do: main_loop()
# If at any point we press Raylib's default "Quit Application" key, (ESCAPE), stop looping and exit.
unless window_should_close?() do
display_items = update()
draw(display_items)
:timer.sleep(100)
main_loop()
end
end
defp update() do
%{display_string: "test", x: get_mouse_x(), y: get_mouse_y()}
end
defp draw(display_items) do
# 描画する前に、Exray.Utils.Colors.black関数の結果で背景をクリアします
clear_background(Colors.white)
begin_drawing()
draw_text( ~s/#{display_items.display_string} X: #{display_items.x} Y:#{display_items.y}/ , 20, 20, 12, Colors.red)
end_drawing()
end
end
Mouseexample.run()