1 of 50

レトロゲームエンジン「Pyxel」で�ゲームプログラミングをはじめよう!

Let’s start game programming with the retro game engine “Pyxel”

北尾 崇 @kitao

Takashi Kitao

ピ ク セ ル

2 of 50

こんにちは、PyCon JP 2020!

Hello, PyCon JP 2020!

2

3 of 50

自己紹介 Self-introduction

  • 北尾 崇(きたおたかし)Takashi Kitao�

  • 元ゲーム開発者 Ex-game developer�

  • 現在は電機メーカーにてAR/VR技術を研究開発中�AR/VR research and development at an electronics company�

  • レトロゲームエンジンPyxel(ピクセル)の開発者�Developer of the retro game engine Pyxel�

  • 2018年、GitHubデイリーランキングにて�全世界の開発者中1位を獲得(ただし3日間だけ…)�Ranked first in the GitHub daily ranking in 2018 (only three days)�

  • 工学社 月刊 I/O 2019年5月号〜2020年3月号にて�「PyxelではじめるPythonゲームプログラミング」連載�Serialized articles of Pyxel in the monthly magazine

3

4 of 50

本日得られること What you can get today

4

Pythonだけでこんなプログラムを簡単に作れるようになります�You can easily create such programs only with Python

155行 155 lines

14行 14 lines

5 of 50

本日の説明内容 Contents

  • Pyxelの概要と導入�Overview and installation of Pyxel
  • Pyxelを使ったお絵描きプログラムの作成�Create a doodle program with Pyxel
  • 付属ツールを使った素材の作成�Create assets using the included tool
  • 本格的なゲームプログラミングの方法�Full-scale game programming method
  • まとめ�Summary

5

6 of 50

Pyxelの概要と導入�Overview and installation of Pyxel

6

7 of 50

Pyxel(ピクセル)とは What is Pyxel?

  • Python向けレトロゲームエンジン (https://github.com/kitao/pyxel)A retro game engine for Python�
  • 昔ながらのドット絵タイプのゲームを作るためのPython用ライブラリ�A library for Python for making old-fashioned pixel-art-type games�
  • オープンソース。現在GitHubで7300スター�Open source. Currently 7300 stars on GitHub�
  • 2018年生まれの比較的新しい「Fantasy Console」�Relatively new “Fantasy Console” born in 2018

7

8 of 50

「Fantasy Console」について About “Fantasy Console”

  • PCやスマホなどの上で動作する架空のゲーム機�A fictitious game console that runs on a PC or smartphone�
  • PICO-8制作者のジョセフ・ホワイト氏が提唱�Proposed by Joseph White, creator of PICO-8
  • 8ビット、16ビットゲーム機時代の制約を再現�Reproduce constraints of the 8-bit and 16-bit game console eras�
  • 制約の例 Constraint examples
    • 16色のみ Only 16 colors
    • 十字キー+ボタン2つだけ Only cross key and two buttons
    • 画面サイズは256x256以下 Screen size is 256x256 or less
    • 等々 etc.

8

9 of 50

Fantasy Console俯瞰 Fantasy Console overview

9

有償 Paid

無料 Free

厳密な制約

Strict constraints

緩めの制約

Less constraints

Lua

Lua

Lua / MoonScript

Lua

Python

10 of 50

Pyxelの5つの特長 Five features of Pyxel

  1. Pythonでプログラムできる。他のライブラリも併用可能�Programmable in Python. Other libraries can be used together
  2. マルチプラットフォーム対応 (Windows, Mac, Linux)�Multi-platform support (Windows, Mac, and Linux)
  3. シンプルなAPIで覚えることが少ない�Less to learn with simple APIs
  4. 画像・音楽制作のためのツールが同梱されている�Tool for image and music production is included
  5. 無料で使える (MIT License)。商用利用も可能�Can be used for free (MIT License). Commercial use is also possible

10

11 of 50

Pyxelの基本仕様

  • 16色固定パレット�Fixed 16 color palette�
  • 最大画面サイズ256x256�Maximum screen size 256x256�
  • 256x256サイズ、3イメージバンク�256x256 sized 3 image banks�
  • 256x256サイズ、8タイルマップ�256x256 sized 8 tilemaps�
  • 4音同時再生、定義可能な64サウンド�4 channels with 64 definable sounds�
  • 任意のサウンドを組み合わせ可能な8ミュージック�8 musics which can combine arbitrary sounds�
  • キーボード、マウス、ゲームパッド入力�Keyboard, mouse, and gamepad inputs

11

12 of 50

16色で表現できること What can be expressed in 16 colors

12

Illustration by Toshio Noguchi

13 of 50

作品例① Production examples #1

13

Both games are created by helpcomputer0

14 of 50

作品例② Production examples #2

14

レトロゲーム風セキュリティ・インシデント可視化ツール「8vana(ハチバーナ)」 by Isao Takaesu

Retro game style security incident visualization tool "8vana" by Isao Takaesu

15 of 50

Pyxelの導入方法 Installation of Pyxel

15

Windows (32bit / 64bit)

Python3インストール&PATH追加後に After installing Python3 and adding to PATH

pip install pyxel

Linux (Ubuntu)

sudo apt install python3 python3-pip libsdl2-dev libsdl2-image-dev gifsicle

sudo -H pip3 install -U pyxel

Mac (Catalina)

brew install python3 gcc sdl2 sdl2_image gifsicle

pip3 install -U pyxel

Homebrewインストール後に After installing Homebrew

16 of 50

WindowsでのPATH追加方法 How to add to PATH on Windows

16

17 of 50

サンプルの実行方法 How to execute the examples

サンプルを専用コマンド install_pyxel_examples でコピー�Copy the examples with the dedicated command install_pyxel_examples����任意のファイルを選んで実行�Select and execute any file� Windows:���� Mac or Linux:

17

install_pyxel_examples

cd pyxel_examples

python 01_hello_pyxel.py

python3 01_hello_pyxel.py

18 of 50

サンプル一覧 List of examples

  • 01_hello_pyxel.pyシンプルなアプリケーション Simplest application
  • 02_jump_game.pyリソースを使ったジャンプゲーム Jump game with resources
  • 03_draw_api.py描画APIのデモ Demonstration of drawing API
  • 04_sound_api.pyサウンドAPIのデモ Demonstration of sound API
  • 05_color_palette.pyカラーパレット一覧 Color palette list
  • 06_click_game.pyマウスクリックゲーム Mouse click game
  • 07_snake.pyBGM付きスネークゲーム Snake game with BGM
  • 08_triangle_api.py三角形描画APIのデモ Demonstration of triangle drawing API

18

19 of 50

Pyxelを使ったお絵描きプログラムの作成�Create a doodle program with Pyxel

19

20 of 50

Pyxelを使ったお絵描きの方法 How to doodle with Pyxel

  1. PythonコードでPyxelモジュールをインポートする�Import Pyxel module from your Python code���
  2. init(画面幅, 画面高さ) 命令で画面を初期化する�Initialize the screen with the init(width, height) command���
  3. 好きな描画命令を呼ぶ�Call any drawing commands���
  4. show() 命令で画面を表示する�Show the screen with the show() command

20

import pyxel

pyxel.init(160, 120)

pyxel.rect(40, 40, 80, 40, 8)

pyxel.show()

21 of 50

実行結果 Execution result

21

22 of 50

実行結果 Execution result

22

rect(左座標, 上座標, 幅, 高さ, 色):指定した位置とサイズの矩形を描画する�rect(left, top, width, height, color) : Draw a rectangle at the specified position and size

pyxel.rect(40, 40, 80, 40, 8)

(0,0)

+x

+y

(40,40)

80

40

(159,119)

23 of 50

Pyxelの描画命令 Drawing commands of Pyxel

23

画面をクリアする�Clear screen

点を描画する�Draw a point

矩形を描画する�Draw a rectangle

円を描画する�Draw a circle

画像を描画する�Draw an image

文字を描画する�Draw text

直線を描画する�Draw a line

矩形の枠を描画する�Draw a rectangular frame

円の枠を描画する�Draw a circle frame

タイルマップを描画する�Draw a tilemap

色番号を置き換える�Replace color number

24 of 50

お絵描きの例 Doodle example

24

import pyxel

data = [40, 70, 50, 20, 100, 50, 40, 20]

pyxel.init(128, 128)

for i, d in enumerate(data):

pyxel.rect(i * 14 + 10, 120 - d, 10, d, 8 + i)

pyxel.line(0, 120, 127, 120, 7)

pyxel.show()

25 of 50

Pyxelによる絵の動かし方 How to animate doodles with Pyxel

  • PythonコードでPyxelモジュールをインポートする�Import Pyxel module from your Python code
  • アニメーション用の変数を設定する�Set variables for animation
  • init(画面幅, 画面高さ) 命令でウィンドウを初期化する�Initialize the window with the init(width, height) command
  • アニメーション用のループを作成する�Make the loop for animation
  • 変数を更新して描画命令を呼ぶ�Update variables and call any drawing commands
  • flip() 命令で画面を更新する�Update the screen with the flip() command

25

import pyxel

x = 0

pyxel.init(160, 120)

while True:

x += 2

if x >= pyxel.width + 20:

x = -20

pyxel.cls(0)

pyxel.circ(x, 60, 20, 11)

pyxel.flip()

26 of 50

実行結果 Execution result

26

circ(中心X座標, 中心Y座標, 半径, 色):指定した位置と半径の円を描画する�circ(x, y, radius, color) : Draw a circle at the specified position and radius

pyxel.circ(x, 60, 20, 11)

27 of 50

つぶやきPyxelへの挑戦 Challenge to Pyxel tweet

  • Pyxelのお絵描きプログラムをTwitterでツイートする試み�Attempt to tweet Pyxel doodle program on Twitter�
  • JavaScriptやLuaでやっている人たちがいてうらやましかった�I was envious of people doing similar things in JavaScript and Lua
  • とはいえPythonで280文字の制限は相当厳しい�However, the limit of 280 characters is quite severe in Python
  • Python上級者の人たちのがんばりに期待しています!�I’m looking forward to good work of advanced Pythonists!

27

28 of 50

つぶやきPyxelの例① Pyxel tweet example #1

28

from pyxel import *

from math import *

a=0

init(128,128)

while 1:

cls(1)

for x in range(0,128,4):

for y in range(0,128,4):

d=sqrt((x-64)**2+(y-64)**2)

b=sin(d*0.2+a)*4

c=(15-d*0.2)%16

circ(x+b,y+sin(b/4)*4,1,c)

a+=0.2

flip()

29 of 50

つぶやきPyxelの例② Pyxel tweet example #2

29

from pyxel import *

t=0

w=256

init(w,w)

i=image

b=i(0)

s=i(4,system=True)

while 1:

t += 1

b.copy(0,0,4,0,0,w,w)

s.copy(0,1,0,0,0,w,w)� for x in range(w):pset(x,0,7 if abs(t+((x-t)^(x+t))**3)%997<97 else 0)

flip()

Original version in p5.js is created by ntsutae

30 of 50

SNS投稿に便利な機能 Convenient functions for SNS posting

  • 実行中に ALT+1 (OPT+1):スクリーンショットを撮影�Press ALT+1 (OPT+1) during execution: Take a screenshot�
  • 実行中に ALT+3 (OPT+3):直近30秒をアニメーションGIFとして保存�Press ALT+3 (OPT+3) during execution: Save the last 30 seconds as an animated GIF�
  • 実行中に ALT+2 (OPT+2):アニメーションGIFの開始ポイントをリセット�Press ALT+2 (OPT+2) during execution: Reset starting point of animated GIF�
  • 各ファイルはデスクトップに保存されるEach file is saved on your desktop

30

31 of 50

付属ツールを使った素材の作成�Create assets using the included tool

31

32 of 50

Pyxel Editorについて About Pyxel Editor

  • Pyxelに付属する画像と音楽の制作ツール�Image and music production tool comes with Pyxel�
  • ターミナルから pyxeleditor コマンドで起動Start with the pyxeleditor command from terminal�
  • リソースの種類に対応した各モードが存在�There are 4 modes corresponding to the type of resource
    • イメージエディタ Image Editor
    • タイルマップエディタ Tilemap Editor
    • サウンドエディタ Sound Editor
    • ミュージックエディタ Music Editor
  • 作成したPyxelリソースファイル(.pyxres)は�load(ファイル名) 命令で読み込み可能�The created Pyxel resource file (.pyxres) can be loaded�with the load(filename) command

32

pyxeleditor

pyxeleditor your_resource_filename

または or

モード変更ボタン�Mode change buttons

ヘルプメッセージ�Help message

33 of 50

イメージバンクの仕組み Image Bank mechanism

33

Copy

blt(x, y, img, u, v, w, h, [colkey])

Image Bank with 256x256 pixels (0-2)

Screen with

256x256 pixels or less

w

h

Image Bank #img

(u,v)

(x,y)

34 of 50

イメージエディタ Image Editor

イメージバンクを編集するモード Mode for editing Image Banks

34

0-2の3イメージバンクが使用可能�3 Image Banks from 0 to 2 are available

PNG画像をドラッグ&ドロップすると選択中のイメージバンクにインポートできる

Drag and drop PNG images to import into the selected image bank

他の慣れたツールで画像を作成してインポートするのも一つのやり方�Creating and importing images with other familiar tools is another way

35 of 50

タイルマップの仕組み Tilemap mechanism

35

bltm(x, y, tm, u, v, w, h, [colkey])

Image Bank with 256x256 pixels (0-2)

Tilemap with 256x256 tiles (0-7)

Tilemap #tm

w

h

(u,v)

(x,y)

Screen with�256x256 pixels or less

00

01

02

...

03

32

33

34

...

35

64

65

66

...

67

Refer to tile image

Copy

00

01

02

...

03

32

33

34

...

35

64

65

66

...

67

36 of 50

タイルマップエディタ Tilemap Editor

タイルマップを編集するモード Mode for editing Tilemaps

36

0-7の8タイルマップが使用可能�8 Tilemaps from 0 to 7 are available

イメージバンクを選択する際にドラッグすると、複数のタイルを同時に選択できる

Multiple tiles can be selected simultaneously by dragging when selecting an image bank

そのタイルマップが何番のイメージバンクを�参照していたかも保存される�The number of the Image Bank that the Tilemap referred to is also saved

37 of 50

サウンドエディタ Sound Editor

サウンドを編集するモード Mode for editing Sounds

37

0-63の64サウンドが使用可能�64 Sounds from 0 to 63 are available

SPEED値が小さいほど速く再生される

The smaller the SPEED value, the faster the playback

再生速度によって効果音やメロディになる

Depending on the playback speed, it becomes a sound effect or melody

使用可能な音色(TON)やエフェクト(EFX)の種類は右上のヘルプメッセージに表示される

The types of tones (TON) and effects (EFX) that can be used are displayed in the help message in the upper right

38 of 50

ミュージックエディタ Music Editor

ミュージックを編集するモード Mode for editing Musics

38

0-7の8ミュージックが使用可能�8 Musics from 0 to 7 are available

最大4つのサウンドをミュージックとして同時に再生できる�Up to 4 sounds can be played as music simultaneously

ミュージックで使用するのは3音に留めて、�残りの1つは効果音の再生に使うのがおすすめ

It is recommended to use only three sounds for music, and use the other one for playing sound effects

39 of 50

本格的なゲームプログラミングの方法�Full-scale game programming method

39

40 of 50

ゲームの処理の流れ Game processing flow

40

入力情報の取得�Get input information

各要素の状態を更新�Update each element state

相互作用の処理�Process interactions

各要素を描画�Render each element

マウス、キーボード、ゲームパッド等�Mouse, keyboard, gamepad, etc.

プレイヤー、敵、弾、背景等�Player, enemies, bullets, background, etc.

衝突判定、ダメージ処理等�Collision detection, damage reaction, etc.

負荷が大きいとスキップする場合もある�It may be skipped if the load is large

41 of 50

Pyxelアプリケーションの雛形 Pyxel application template

41

import pyxel

class App:

def __init__(self):

pyxel.init(160, 120)

# 初期化処理 Initialization process

pyxel.run(self.update, self.draw)

def update(self):

# 更新処理 Update process

def draw(self):

# 描画処理 Render process

App()

init(画面幅, 画面高さ):指定した画面サイズでアプリを初期化する�init(width, height) : Initialize an application with the specified screen size

run(更新関数, 描画関数)アプリの実行を開始するrun(update, draw) : Start running the application

更新関数run命令から一定時間(1/30秒)ごとに呼ばれるupdate(self) : Called at regular intervals (1/30 sec) from the run command

描画関数run命令から描画が必要な時に呼ばれるdraw(self) : Called when drawing is required from the run command

42 of 50

初期化処理の例 Initialization process example

42

class App:

def __init__(self):

pyxel.init(120, 160, caption="Pyxel Shooter")�

# 略 Ommited

self.scene = SCENE_TITLE

self.score = 0

self.background = Background()

self.player = Player(pyxel.width / 2, pyxel.height - 20)

pyxel.run(self.update, self.draw)

アプリケーション名をcaptionオプションで設定

Set application name with caption option

クラスのメンバ変数として必要な変数を初期化

Initialize necessary variables as class member

背景クラス、プレイヤークラスのインスタンスを生成・保持�Create and remember the Background class and the Player class instances

43 of 50

更新処理の例 Update process example

43

class Player:

def update(self):

if pyxel.btn(pyxel.KEY_LEFT):

self.x -= PLAYER_SPEED

if pyxel.btn(pyxel.KEY_RIGHT):

self.x += PLAYER_SPEED

# 略 Omitted

if pyxel.btnp(pyxel.KEY_SPACE):

Bullet(

self.x + (PLAYER_WIDTH - BULLET_WIDTH) / 2,

self.y - BULLET_HEIGHT / 2

)

pyxel.play(0, 0)

btn(key)keyが押されていたらTrue、押されていなければFalseを返す�btn(key) : Return True if key is pressed, otherwise return False

play(ch, snd, loop=False):チャンネルch(0-3) でサウンドsnd(0-63) を再生する

play(ch, snd, loop=False) : Play the sound snd(0-63) on channel ch(0-3)

btnp(key, [hold], [period]):そのフレームにkeyが押されたらTrue、押されなければFalseを返す�btnp(key, [hold], [period]) : Return True if key is pressed at that frame, otherwise return False

44 of 50

描画処理の例 Draw process example

44

class Player:

def draw(self):

pyxel.blt(self.x, self.y, 0, 0, 0, self.w, self.h, 0

class Blast:

def draw(self):

pyxel.circ(self.x, self.y, self.radius, BLAST_COLOR_IN)

pyxel.circb(self.x, self.y, self.radius, BLAST_COLOR_OUT)

class Bullet:

def draw(self):

pyxel.rect(self.x, self.y, self.w, self.h, BULLET_COLOR

自機はイメージバンクの画像をコピー�Copy a player image from the Image Bank

爆発は2つの円として描画

Draw two circles as a blast effect

弾は矩形として描画�Draw a rectangle as a bullet

45 of 50

実行結果 Execution result

45

このサンプルの全ソースコードはこちらFull source code for this example is here

46 of 50

ジャンルごとのポイント紹介 Key points for each genre

  • シューティングゲーム Shoot’em up
    • 複数の敵や弾はクラスとして定義して、リストで管理するとよい�To manage multiple enemies and bullets, define it as a class and add it to the list�
  • プラットフォーマー(アクションゲーム) Platformer
    • 壁の押し戻し処理はこちらを参照のこと�Please refer to here for collision response�
    • タイルマップの値は tilemap(番号).get(x, y) で取得可能�The value of tilemap can be obtained by tilemap(no).get(x, y)�
  • パズルゲーム Puzzle game
    • ステージはタイルマップとして作成すると編集しやすい�Creating a level as a tile map makes it easier to edit�
    • タイルマップは tilemap(番号).copy(...) でコピー可能�Tilemap can be copied by tilemap(no).copy(...)�
  • ロールプレイングゲーム Role playing game
    • 自前でウィンドウやテキストの管理が必要。がんばって!� Need to manage windows and texts yourself. Good luck!

46

47 of 50

まとめSummary

47

48 of 50

Pyxelの今後 The future of Pyxel

  • コアライブラリの実装言語をC++からRustに移行する�Migrate core library implementation language from C++ to Rust
  • 単体アプリとしても動作可能にする�Make it work as a standalone application
  • Webブラウザ上で動くようにする�Make it work on a web browser
  • ソフトシンセサイザーを刷新する�Renovate the software synthesizer
  • 日本のPythonコミュニティでもう少し話題になる�Get a little more attention from the Python community in Japan

48

49 of 50

本日のまとめ Today’s summary

  • Pyxel(ピクセル)�
    • Python向けレトロゲームエンジン�Retro game engine for Python�
    • オープンソース・無料�Open source and free to use�
    • 映像・音楽の制作ツール付属�Image and music production tool included�
  • 参考リンク Reference links�

49

50 of 50

ご清聴ありがとうございました!

Thank you for listening!

50