ランダムドットパターンの運動と奥行き知覚(PyGame)
平面上のランダムなドットパターンは、適切な運動を与えると奥行きのある立体に見える。例えば、図1に示されているランダムドットパターンは、リスト1のプログラムで与えられる運動により、円筒に貼りつけられたドットが運動しているように見える。
図1
リスト1のスクリプトファイルは、圧縮ファイルullman_files.zipとしているが、ダウンロード展開すれば自由に利用できる。図1の画面において、キーGを押せば、ドットパターンは運動するが、キーSを押すと停止する。停止したドットパターンは、平面上のランダムドットパターンに見えるが、キーGを押して、ドットパターンが運動を始めると、円筒に貼りつけられたドットパーンの運動に見える。
リスト1のスクリプトでは、モジュールPyGameを利用しているが、PyGameのインストールはこのウェブサイトで説明しているように簡単である。
ランダムドットパターンは、次のコードで設定している。
n = 200
x_polar = np.random.rand(n)
* np.pi * 2
# 横軸角度座標
y = np.random.rand(n)
* 260
# 縦軸座標
縦軸の座標値は、一様乱数で与えているが、横軸は角度座標で与え、次のコードで横軸座標に変換している。
x = np.cos(x_polar) * 100
# 角度座標ー>X軸座標
ランダムドット(x[i], y[j])は、次のコードで、中央黒画面内にプロットしている。
for i
in range(n):
pg.draw.circle(screen, (0,255,255), (400 + x[i], 70 + y[i]), 4)
画面の更新後、角度座標値の更新を次のコードで行っている。すなわち、値をx_stepだけ増やした後、2πで割った余りを求めることにより、更新値が0から2πの範囲に収まるようにしている。
x_polar
= (x_polar + x_step) % (np.pi * 2)
# 角度座標の更新
角度座標の更新後、次のコードでキー押しのチェックを行い、対応する処理を行っている。キー押しのチェック後、10msのウェイトを置いて処理速度の調整を行っている。
for e in pg.event.get():
if e.type == pg.KEYDOWN:
if e.key == pg.K_q: # 「キーJ」が押されたか?
ck0 = False
# While文の終了
elif e.key == pg.K_s:
x_step = 0
# 角度座標の更新量を0にする
elif e.key == pg.K_g:
x_step = 0.015 # 角度座標の更新量を0.015にする
pg.time.wait(10)
import numpy
as np
import pygame
as pg
from pygame
import font
pg.init()
screen = pg.display.set_mode(size=(800,
500))
# 画面の大きさ
pg.display.set_caption('Ullman')
screen.fill((255, 255, 255))
# 白背景
pg.draw.rect(screen, (0,0,0), (200, 50, 400,
300)) # 黒画面
#
#
表示文字列の作成と表示
#
msg = 'G: Go, S: Stop, Q: Quit'
my_font = pg.font.SysFont(None,
48)
img_msg = my_font.render(msg, True, (0, 0, 200), (255, 255, 255))
rect_msg = img_msg.get_rect()
screen.blit(img_msg,
(400 - rect_msg.width//2, 500 - rect_msg.height*2))
pg.display.flip()
# 描画の表示
n = 200
x_polar = np.random.rand(n)
* np.pi * 2
# 横軸角度座標
y = np.random.rand(n)
* 260
# 縦軸座標
x_step = 0.015
# 角度座標値のステップ値
ck0 = True
while ck0:
pg.draw.rect(screen,
(0,0,0), (200, 50, 400, 300))
# 中央黒画面
screen.blit(img_msg, (400 - rect_msg.width//2,
# 文字列表示
500 - rect_msg.height*2))
#
#
ドットの描画
#
x = np.cos(x_polar) * 100
# 角度座標ー>X軸座標
for i
in range(n):
pg.draw.circle(screen, (0,255,255), (400 + x[i], 70 + y[i]), 4)
pg.display.flip()
# 描画画像の表示
x_polar
= (x_polar + x_step) % (np.pi * 2)
# 角度座標の更新
#
# キーイベントのチェック
#
for e in pg.event.get():
if e.type == pg.KEYDOWN:
if e.key == pg.K_q: # 「キーJ」が押されたか?
ck0 = False
# While文の終了
elif e.key == pg.K_s:
x_step = 0
# 角度座標の更新量を0にする
elif e.key == pg.K_g:
x_step = 0.015 # 角度座標の更新量を0.015にする
pg.time.wait(10)
pg.quit()