pyglet でプレイヤーを移動:斜めも同じ速度で

さて、少し間が空いてしまいました。

キー入力で8方向に移動するとき、斜め移動だと速度が速くなって気になる問題を解決してみます。縦横に移動速度をそのまま加えると、sqrt(2) 倍の速度で移動してしまいますね。

  • 「斜め方向」に移動しているときだけ移動速度の計算を変えたい
  • 斜め方向=方向キーが2個同時に押されているとき
  • 各ボタンにビットを割り当てて、ビット数を数えたら良い

という発想で組んでみました。

しかし、bit_count が実装されたのはだいぶ最近で Python 3.10 なのですね…。速度をそこまで気にするプログラムでもないですけれど、bin(button).count(“1”) なんていうのはさすがにまどろっこしいです。どうせ bit を立てるときに if で判定するので、そこで数えてしまいますか。

import pyglet
from pyglet.window import key
from collections import defaultdict
import math

window = pyglet.window.Window()

label = pyglet.text.Label('<->',
                          font_name='Courier New',
                          font_size=12,
                          x=window.width//2, y=window.height//2,
                          anchor_x='center', anchor_y='center')

@window.event
def on_draw():
    window.clear()
    label.draw()

key_status = defaultdict(bool)

@window.event
def on_key_press(symbol, modifiers):
    key_status[symbol] = True

@window.event
def on_key_release(symbol, modifiers):
    key_status[symbol] = False

# 1 秒あたり 320 ピクセル移動する
MOVE_SPEED = 320

# 上下左右ボタンの定義
BUTTON_UP       = 0x01
BUTTON_RIGHT    = 0x02
BUTTON_LEFT     = 0x04
BUTTON_DOWN     = 0x08

def update(dt):
    dx = 0
    dy = 0
    d = dt * MOVE_SPEED
    bit_count = 0

    button = 0
    if key_status[key.W]: # up
        button |= BUTTON_UP
        bit_count += 1
        dy = d
    elif key_status[key.S]: # down
        button |= BUTTON_DOWN
        bit_count += 1
        dy = -d
    
    if key_status[key.A]: # left
        button |= BUTTON_LEFT
        bit_count += 1
        dx = -d
    elif key_status[key.D]: # right
        button |= BUTTON_RIGHT
        bit_count += 1
        dx = d

    # 同時にキーが複数押されているなら斜め移動なので、速度を下げる。

    # Python 3.10 なら bit_count が使える
    # bit_count = button.bit_count()
    if bit_count == 1:
        label.x += dx
        label.y += dy
    elif bit_count == 2:
        label.x += dx / math.sqrt(2)
        label.y += dy / math.sqrt(2)

pyglet.clock.schedule_interval(update, 1 / 120.0)

pyglet.app.run()
タイトルとURLをコピーしました