方法
以下のいずれかを使う。
- OS.create_process(OS.get_executable_path(), [])
- OS.create_instance([])
Godotでは、1つの実行プロセスを「Debug Instance」と呼びます。上記のコードは、どちらも新しいDebug Instanceを作成するコードです。
以下のいずれかを使う。
Godotでは、1つの実行プロセスを「Debug Instance」と呼びます。上記のコードは、どちらも新しいDebug Instanceを作成するコードです。
関数を次フレームに呼び出す方法として、call_deferredがよく挙げられますが、誤った方法です。海外のコミュニティでも、「call_deferredを使えば良いよ!」という声しか無かったので、その誤解を解く為にこの記事を書きました。
await get_tree().create_timer(0).timeout
を使う。このコードの意味は「シーンツリー上に0秒のタイマーを作成して、そのタイマーが切れるまで待つ」です。次フレームまで処理が中断されるので、このコードの後ろに実行したい関数をおけば良いです。
「0秒タイマー」によって丁度次フレームまで処理を中断させることができる理由は、タイマーの処理が各フレームの最初(自作スクリプトが実行される前)に行われるからです。
call_deferredは「後で関数を呼ぶ」関数です。しかし、call_deferredによって指定された関数は次フレームに行く前に呼ばれてしまいます。例えば、あるフレームでcall_deferredを使って関数を呼んだ場合、同じフレームの_processの前に関数が呼ばれてしまうことがあります。
海外コミュニティにcall_deferredについての正確な動作を解説したポストがあります。
ここからかいつまんで説明すると、以下のようになります。
call_deferredはスタックに関数を入れますが、そのスタックの関数が実行されるタイミングは1フレームで複数回あります。コードの終わりなどにもそのタイミングがあるので、指定した関数が現フレームで呼ばれてしまいます。
画面の色を検知するソフトを作成してみたかったので、Pythonで画面キャプチャを作ってみました。
FPS=60で動かしたものです。
キャプチャした画面を更にキャプチャしているので、ミルフィーユのようになっています。
録画しながらのせいか右端に残像が残っていますが、普段は発生しません。
import tkinter
import dxcam
from PIL import Image, ImageTk
SCREEN_WIDTH = 1920
SCREEN_HEIGHT = 1080
FPS = 60
root = tkinter.Tk()
root.geometry(f"{SCREEN_WIDTH}x{SCREEN_HEIGHT}")
root.title("画面キャプチャ")
canvas = tkinter.Canvas(root, width=SCREEN_WIDTH, height=SCREEN_HEIGHT, background="#FFF")
canvas.pack()
camera = dxcam.create()
camera.start(target_fps=FPS)
def update():
global tk_image
frame = camera.get_latest_frame()
image = Image.fromarray(frame)
tk_image = ImageTk.PhotoImage(image)
canvas.create_image(SCREEN_WIDTH/2,SCREEN_HEIGHT/2,image=tk_image)
root.after(int(1000/FPS), update)
update()
root.mainloop()
SCREEN_WIDTH、SCREEN_HEIGHT:スクリーンの幅と高さです。
FPS:一秒あたり何回描画するか。FPSを高くしてもcamera.get_latest_frame()でのスクショが追い付かないので、実際には指定した値よりも低くなります。
tkinter.Tk():ウィンドウを作成します。
root.geometry(f”{SCREEN_WIDTH}x{SCREEN_HEIGHT}”):ウィンドウサイズを設定。このコードを書かない場合、ウィンドウの大きさはスクリーンの大きさになるので、今回は無意味です。
root.title(“画面キャプチャ”):ウィンドウのタイトル(名前)を「画面キャプチャ」にします。
tkinter.Canvas(root, width=SCREEN_WIDTH, height=SCREEN_HEIGHT, background=”#FFF”):ウィンドウに画像を描画する為のキャンバスを作成します。背景色は白です。
canvas.pack():キャンバスを配置します。このコードが無い場合、キャンバスは表示されません。
global tk_image:tk_imageがガベージコレクタによって廃棄されないようにする為にグローバル変数にする。このコードが無いと、tk_imageが即座に捨てられてしまい、キャンバスには何も表示されなくなります。
canvas.create_image(x,y,image=tk_image):x,yには画像の中心座標を入れます。
root.after(int(1000/FPS), update):int(1000/FPS)ミリ秒あとに、update関数を呼びます。第一引数は整数にする必要があります。
image = Image.fromarray(frame):numpyのndarrayをPillowのImageオブジェクトに変換します。
dxcam.create():DXCameraインスタンスを作成します。
camera.start(target_fps=FPS):指定したFPSでスクショを撮る作業をスタートします。
camera.get_latest_frame():新しいスクショが撮られるまで待ち、スクショが撮られたら値を返します。返り値の型は、numpyのndarrayです。