Skip to content

Instantly share code, notes, and snippets.

@mieki256
Last active September 12, 2022 11:43
Show Gist options
  • Save mieki256/70dc5a2ec3e7ed0a36b6715b99670b2f to your computer and use it in GitHub Desktop.
Save mieki256/70dc5a2ec3e7ed0a36b6715b99670b2f to your computer and use it in GitHub Desktop.
pygletでフルスクリーン表示等をするサンプル・Windows7 x64 (+ GeForce 9800GTGE) + Python 2.6.6 32bit + pyglet 1.2 alpha 1 で動作確認。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- mode: python;Encoding: utf8n -*-
"""
Pygletサンプル
BG表示、スプライト表示、oggのループ再生を行う
- 座標は、左下が(0,0)になってることに注意
- ジョイスティックにも対応。pyglet 1.2 alpha 1 以上が必要。
- use pyglet 1.2 alpha 1
- use joystick
"""
import os
import sys
sys.path.insert(0, '.')
import PIL.Image
sys.modules['Image'] = PIL.Image
import math
import time
import pyglet
# pyglet.options['debug_gl'] = False
import pyglet.window
import pyglet.window.key
import pyglet.window.mouse
import pyglet.gl
import pyglet.resource
import pyglet.media
import pyglet.sprite
import pyglet.font
from pyglet.window import key
from pyglet.window import mouse
class Window(pyglet.window.Window):
"""ウインドウ用クラス"""
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.step = 0
self.set_vsync(False)
self.running = True
self.frame = 0 # フレームカウンタ
self.count = 0
self.fps_count = 0 # FPS算出用
self.lasttime = time.time()
self.updating = False # 更新処理中かどうかのフラグ
self.keys_held = [] # 入力されたキーの記録用
self.batch_enable = False # バッチを使って描画するか否か
self.scr_w = self.width
self.scr_h = self.height
self.resize_fg = False
self.bgm_file = ""
self.bgm_src = None
self.spr_batch = None
self.bg_batch = None
self.txt_batch = None
self.image = None
self.bgimg = []
self.bgspr = []
self.sprs = []
self.label = []
self.sprite = None
self.sprdraw = True
self.bgx = [0, 0]
self.bgy = [0, 0]
self.fntname = "Arial"
self.font_bold = False
# ジョイスティック用の初期化処理
self.joystick_enable = False
joysticks = pyglet.input.get_joysticks()
if joysticks:
self.joystick_enable = True
self.joystick = joysticks[0]
self.joystick.open()
fpsrate = 60
# FPS制限
# ※ pyglet 1.1以降、schedule_interval() を使うなら不要らしい
# pyglet.clock.set_fps_limit(fpsrate)
# 更新処理を一定時間間隔で呼ぶように設定
pyglet.clock.schedule_interval(self.update, 1.0 / float(fpsrate))
def on_key_press(self, symbol, modifiers):
"""キーを押した瞬間のイベント"""
if self.step == 0:
return
self.keys_held.append(symbol) # キーをリストに記録
if symbol == key.F2:
# フルスクリーン/ウインドウ表示切り替え
if not self.fullscreen:
# フルスクリーン表示に設定
self.set_fullscreen(fullscreen=True,
width=self.width,
height=self.height)
else:
# ウインドウ表示に設定
self.set_fullscreen(fullscreen=False)
if symbol == key.F3:
# スプライト表示切り替え
self.sprdraw = not self.sprdraw
if symbol == key.F4:
# FPS表示切り替え
self.fps_disp_enable = not self.fps_disp_enable
if symbol == key.F5:
# バッチ描画切り替え
self.batch_enable = not self.batch_enable
self.label[8].text = "F5: BATCH %s" % \
("ON" if self.batch_enable else "OFF")
if symbol == key.F6:
# Vsync切り替え
self.set_vsync(not self.vsync)
self.label[9].text = "F6: VSYNC %s" % \
("ON" if self.vsync else "OFF")
if symbol == key.Q or symbol == key.ESCAPE: # アプリ終了を指示
self.running = False
def on_key_release(self, symbol, modifiers):
"""キーを離した際のイベント"""
if symbol in self.keys_held:
self.keys_held.pop(self.keys_held.index(symbol)) # キーを除外
def on_mouse_press(self, x, y, button, modifiers):
"""マウスボタン押し下げイベント"""
if self.step > 0:
if button == mouse.LEFT:
self.sprite.x = x
self.sprite.y = y
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
"""マウスドラッグイベント"""
if self.step > 0:
if button == mouse.LEFT:
self.sprite.x = x
self.sprite.y = y
# def on_resize(self, width, height):
# """ウインドウリサイズイベント"""
# super(Window, self).on_resize(width, height)
# # print "on_resize(width=%d, height=%d)" % (width, height)
# self.scr_w = width
# self.scr_h = height
# self.resize_fg = True
def init_resource(self):
"""画像リソースその他を読み込み"""
# リソースの場所を設定
pyglet.resource.path = ['res']
pyglet.resource.reindex()
# フォント読み込み
if False:
pyglet.resource.add_font('VeraMoBd.ttf')
pyglet.font.load("Bitstream Vera Sans Mono", bold=True)
self.fntname = "Bitstream Vera Sans Mono"
self.font_bold = True
else:
self.fntname = "Arial"
self.font_bold = False
# バッチ描画用の初期化
self.bg_batch = pyglet.graphics.Batch() # BG表示用
self.spr_batch = pyglet.graphics.Batch() # スプライト表示用
self.txt_batch = pyglet.graphics.Batch() # テキスト表示用
# 画像読み込み
# スプライト表示用の画像を読み込む
self.image = pyglet.resource.image('ufo.png')
# 基準座標を画像の中心にする
self.image.anchor_x = self.image.width // 2
self.image.anchor_y = self.image.height // 2
# BG表示用の画像を読み込む
self.bgimg = []
self.bgimg.append(pyglet.resource.image('bg1.png'))
self.bgimg.append(pyglet.resource.image('bg2.png'))
# ogg読み込み
self.bgm_file = "bgm32.ogg"
if os.path.exists("./res/bgm32.wav"):
self.bgm_file = "bgm32.wav"
self.bgm_src = pyglet.resource.media(self.bgm_file, streaming=False)
def init_bg(self):
"""BG初期化.
512x512ドットのスプライトを4枚並べてBG1つ分、それを2枚作る
"""
self.bgx = [0.0, 0.0]
self.bgy = [0.0, 0.0]
self.bgspr = []
for i in range(2):
for o in [[0, 0], [512, 0], [0, 512], [512, 512]]:
bg = pyglet.sprite.Sprite(img=self.bgimg[i],
x=o[0], y=o[1],
batch=self.bg_batch
)
bg.scale = 1.0
self.bgspr.append(bg)
def init_sprite(self):
"""スプライト群を初期化"""
# 画面内を跳ね回る(?)スプライトを発生
ufo_num = 512
self.sprs = []
self.sprdraw = True
sx = self.width / 2
sy = self.height / 2
r = 3.0
for i in range(ufo_num):
ang = i * 360.0 / ufo_num
ufo = pyglet.sprite.Sprite(img=self.image, x=sx, y=sy,
batch=self.spr_batch
)
rad = math.radians(ang)
ufo.dx = r * math.cos(rad)
ufo.dy = r * math.sin(rad)
ufo.fpx = float(sx)
ufo.fpy = float(sy)
ufo.scale = 1.0
self.sprs.append(ufo)
# 入力機器の動作確認用スプライトを発生
self.sprite = pyglet.sprite.Sprite(img=self.image, x=sx, y=sy,
batch=self.spr_batch
)
self.sprite.scale = 1.0
# self.sprite.scale = 1.5
def init_text(self):
"""テキスト描画関係を初期化"""
# 表示するテキスト群
mesdt = ["FPS", # 0
"Joystick None", # 1
"BGM", # 2
"avbin Ver.", # 3
"", # 4
"F2: Full/Wdw", # 5
"F3: SPR", # 6
"F4: L-FPS", # 7
"F5: BATCH OFF", # 8
"F6: VSYNC OFF", # 9
"Mouse Click: ?",
"Cursor Key: ?",
"ESC,Q: EXIT"]
tx = 10
ty = 450
fsize = 10
self.label = []
for s in mesdt:
lbl = pyglet.text.Label(text=s, font_name=self.fntname,
font_size=fsize, bold=self.font_bold,
x=tx, y=ty,
batch=self.txt_batch
)
self.label.append(lbl)
ty -= (fsize + 6)
# FPS表示のための初期化
self.fps_disp_enable = True
self.fps_disp = pyglet.clock.ClockDisplay(format='%(fps).2f FPS',
color=(1, 1, 1, 0.75))
# ジョイスティックが繋がっているなら、そのことも表示
if self.joystick_enable:
self.label[1].text = "Joystick"
self.label[2].text = "play %s" % (self.bgm_file)
def init_sound(self):
"""ogg再生開始"""
if pyglet.media.have_avbin:
self.label[3].text = \
"avbin ver = %d" % (pyglet.media.avbin.get_version())
else:
self.label[3].text = "not have avbin"
# self.sndplayer = pyglet.media.Player()
self.sndplayer = pyglet.media.ManagedSoundPlayer()
self.sndplayer.queue(self.bgm_src) # キューに入れる
self.sndplayer.eos_action = self.sndplayer.EOS_LOOP # ループ再生を指定
self.sndplayer.play() # 再生開始
def update(self, dt):
"""座標更新処理"""
if self.updating:
# 前回の更新処理が終わって無ければ、何もせずに戻る
return
self.updating = True # 処理中フラグを設定
if self.step == 0:
# 初期化処理
self.init_resource()
self.init_bg()
self.init_sprite()
self.init_text()
self.init_sound()
self.step = 1
elif self.step == 1:
# BGスクロール
ofsx = math.cos(math.radians(self.frame))
self.bgx[0] = -64.0 + (64.0 * ofsx)
self.bgx[1] = -128.0 + (128.0 * ofsx)
self.bgy[0] = (self.bgy[0] + 2.0) % 512.0
self.bgy[1] = (self.bgy[1] + 6.0) % 512.0
bgid = 0
for i in range(2):
for o in [[0, 0], [512, 0], [0, 512], [512, 512]]:
bg = self.bgspr[bgid]
bg.set_position(int(self.bgx[i] + o[0]),
int(-self.bgy[i] + o[1]))
bgid += 1
# スプライト群の移動
x_min = 32.0
y_min = 32.0
x_max = float(self.width - 32.0)
y_max = float(self.height - 32.0)
for ufo in self.sprs:
ufo.fpx += ufo.dx
ufo.fpy += ufo.dy
if ufo.fpx < x_min or ufo.fpx > x_max:
ufo.dx *= -1.0
if ufo.fpy < y_min or ufo.fpy > y_max:
ufo.dy *= -1.0
ufo.set_position(ufo.fpx, ufo.fpy)
self.sprite.rotation += 4
# 押されたキーによってスプライトを移動
spd = 6.0
if key.LEFT in self.keys_held:
self.sprite.x -= spd
if key.RIGHT in self.keys_held:
self.sprite.x += spd
if key.UP in self.keys_held:
self.sprite.y += spd
if key.DOWN in self.keys_held:
self.sprite.y -= spd
# ジョイスティックの入力値でスプライトを移動
if self.joystick_enable:
# デジタルバッドの場合、x,y は -1,0,1 の値が得られる
jx = self.joystick.x
jy = self.joystick.y
self.sprite.x += (jx * spd)
self.sprite.y += (-jy * spd)
self.label[1].text = "Joystick (%.2f,%.2f)" % (jx, jy)
self.sprite.scale = 0.5
self.sprite.opacity = 255
self.sprite.color = (255, 255, 255)
# ボタン情報は True/False が入っている
if self.joystick.buttons[0]:
self.sprite.scale = 2.0
if self.joystick.buttons[1]:
self.sprite.opacity = 128
if self.joystick.buttons[2]:
self.sprite.color = (255, 255, 0)
if not self.running:
self.step = 2
elif self.step == 2:
# BGMフェードアウト開始
self.count = 1.0
self.step = 3
elif self.step == 3:
# BGMフェードアウト中
self.sndplayer.volume = self.count
self.count -= 0.05
if self.count <= 0.0:
self.sndplayer.pause()
self.step = 4
elif self.step == 4:
pyglet.app.exit() # アプリ終了
self.frame += 1 # フレームカウンタをインクリメント
self.updating = False # 処理中フラグをクリア
def calc_fps(self):
"""FPS算出"""
if time.time() - self.lasttime >= 1:
# 1秒以上時間が経っていたら、FPS表示値を更新
self.label[0].text = "FPS: %d" % (self.fps_count)
self.fps_count = 0
self.lasttime = time.time()
else:
self.fps_count += 1
def on_draw(self):
"""描画処理"""
if self.step <= 0:
return # 初期化がまだなら、何もせず戻る
# pyglet.clock.tick() # 時間待ち、らしい
self.clear() # 画面クリア
if self.batch_enable:
# バッチ描画する場合
self.bg_batch.draw() # BG描画
if self.sprdraw:
self.spr_batch.draw() # スプライト描画
self.calc_fps()
self.txt_batch.draw() # テキスト描画
else:
# バッチ描画をしない場合
for bg in self.bgspr:
bg.draw()
if self.sprdraw:
for spr in self.sprs:
spr.draw()
self.sprite.draw()
self.calc_fps()
for lbl in self.label:
lbl.draw()
if self.fps_disp_enable:
self.fps_disp.draw() # FPS表示(大)
# self.flip()
def main():
# ウインドウ生成
window = Window(width=640,
height=480,
caption='Pyglet Sample',
# resizable=True,
# vsync=True
)
pyglet.app.run() # イベントループ開始
if __name__ == '__main__':
main()
@rem make exe
@echo.
@set /p INP="remove build folder ? (y/n) "
@if "%INP%" == "y" goto REMOVEFOLDER
@goto MKEXEJOB
:REMOVEFOLDER
@echo ---------------------------------------- remove folder
rmdir /s /q build
rmdir /s /q dist
@echo.
:MKEXEJOB
@echo.
@echo ---------------------------------------- make exe
python setup.py py2exe
@echo.
@echo ---------------------------------------- file copy
@rem pause
@rem mkdir .\dist\pyglet
@rem xcopy C:\Python26\Lib\site-packages\pyglet .\dist\pyglet /e
@rem mkdir .\dist\ctypes
@rem xcopy C:\Python26\Lib\ctypes .\dist\ctypes /e
@rem copy C:\Python26\Lib .\dist
@echo.
@set /p INP="copy file to target folder ? (y/n) "
@if "%INP%" == "y" goto COPYFILES
@goto END
:COPYFILES
del /q D:\pub\exe_test\test_pyglet\
del /q D:\pub\exe_test\test_pyglet\res\
xcopy .\dist\* D:\pub\exe_test\test_pyglet /E /Y
:END
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe
import os
import glob
script_file = 'fullscrpyglet.py'
icon_file = 'res/app.ico'
# add res/*.*
res_files = []
for fn in os.listdir('res'):
fn = os.path.join('res', fn)
if os.path.isfile(fn):
res_files.append(fn)
py2exe_options = {"compressed" : 1,
"optimize" : 2,
"bundle_files" : 2,
# "includes": ["ctypes", "logging"],
# "packages": ['pyglet'],
# "excludes": ["pyglet"],
}
dll_files = [
# "avbin.pyo",
]
setup(
console=[{"script" : script_file , "icon_resources" : [(1, icon_file)]}],
options={"py2exe": py2exe_options},
# zipfile=None,
data_files=[('res', res_files),
('.', glob.glob('*.dll')),
('.', glob.glob('*.pyd')),
('.', dll_files)],
)
@mieki256
Copy link
Author

Screenshots.

screenshot01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment