移動も出来たら、次は弾でも撃ってみましょうか。
キーボードでプレイするなら [SPACE] キーで撃つのが普通っぽい(pyglet のサンプルもそうですし)ので、真似するとして。
絵を用意するのも手間ですし、とりあえずはまたテキストでやりましょう。大文字の I とか出しておけば弾っぽく見えます。たぶん。
動いていたらもうちょっと弾に見えるんですけれど…。静止画だとなんだか、なんだこれみたいな…。
ちょこちょこと追加してきて、だいぶソースが長くなってきてしまいました。もう100行。そろそろ先送りにしてきた git 管理を考える頃かもしれません。
- ‘<->’ の文字はプレイヤーだ! というのを強調するために変数名を player に変更
- on_key_press にスペースキー判定を追加
- スペースキーが押されたら fire() を呼び出して、テキストラベルをプレイヤーの位置に作成
- 新しく出現した弾は bullets[] に入れて管理して、あとで draw や update から呼び出せるように対応
- update では上方向に常に移動するように対応
- ついでに、弾が画面外に出たら消えるように対応
などなどやってみました。プログラムで書いたら短いけれど、言葉で書く方が長くなるくらいな感じです。
import pyglet
from pyglet.window import key
from collections import defaultdict
import math
window = pyglet.window.Window()
player = pyglet.text.Label('<->',
font_name='Courier New',
font_size=12,
x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
bullets = []
def fire():
bullet = pyglet.text.Label('I', font_name='Courier New', font_size=12,
x=window.width//2, y=window.height//2,
anchor_x='center', anchor_y='center')
bullet.x = player.x
bullet.y = player.y
bullets.append(bullet)
@window.event
def on_draw():
window.clear()
player.draw()
for bullet in bullets:
bullet.draw()
key_status = defaultdict(bool)
@window.event
def on_key_press(symbol, modifiers):
key_status[symbol] = True
if symbol == key.SPACE:
fire()
@window.event
def on_key_release(symbol, modifiers):
key_status[symbol] = False
# プレイヤー移動速度(1 秒あたりのピクセル数)
MOVE_SPEED = 320
# 弾の速度
BULLET_SPEED = 480
# 上下左右ボタンの定義
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:
player.x += dx
player.y += dy
elif bit_count == 2:
player.x += dx / math.sqrt(2)
player.y += dy / math.sqrt(2)
# bullet 位置を更新し、範囲外のオブジェクトは削除
dead_objects = []
for bullet in bullets:
bullet.y += dt * BULLET_SPEED
if bullet.y > window.height:
dead_objects.append(bullet)
for to_remove in dead_objects:
bullets.remove(to_remove)
pyglet.clock.schedule_interval(update, 1 / 120.0)
pyglet.app.run()