[ English | 日本語 | Other Languages ]

Pyxel is a retro game engine for Python.

Thanks to its simple specifications inspired by retro gaming consoles, such as only 16 colors can be displayed and only 4 sounds can be played back at the same time, you can feel free to enjoy making pixel art style games.

The specifications of the gaming console, APIs, and palettes of Pyxel are referring to awesome PICO-8 and TIC-80.

Pyxel is open source and free to use. Let’s start making a retro game with Pyxel!


  • Run on Windows, Mac, and Linux
  • Code writing with Python3
  • Fixed 16 color palette
  • 256x256 sized 3 image banks
  • 4 channels with 64 definable sound banks
  • Keyboard, mouse, and joystick(WIP) inputs
  • Image and sound editor (WIP)

Color Palette

How to Install


After installing Python3, the following pip command installs Pyxel:

pip install pyxel


After installing Python3 and glfw (version 3.2.1 or higher), install Pyxel with pip command.

If Homebrew package manager is ready, the following command installs all the necessary packages:

brew install python3 glfw
pip3 install pyxel


Install the required packages in a way appropriate for each distribution. glfw must be version 3.2.1 or higher.


Install python-pixel by using your favorite AUR helper:

yay -S python-pyxel


apt-get install python3 python3-pip libglfw3 libportaudio2 libasound-dev
pip3 install pyxel


dnf install glfw portaudio
pip3 install pyxel

Install examples

After installing Pyxel, the examples of Pyxel will be copied to the current directory with the following command:


How to Use

Create Pyxel Application

After importing the Pyxel module in your python code, specify the window size with init function first, then starts the Pyxel application with run function.

import pyxel

pyxel.init(160, 120)

def update():
    if pyxel.btnp(pyxel.KEY_Q):

def draw():
    pyxel.rect(10, 10, 20, 20, 11), draw)

The arguments of run function are update function to update each frame and draw function to draw screen when necessary.

In an actual application, it is recommended to wrap pyxel code in a class as below:

import pyxel

class App:
    def __init__(self):
        pyxel.init(160, 120)
        self.x = 0, self.draw)

    def update(self):
        self.x = (self.x + 1) % pyxel.width

    def draw(self):
        pyxel.rect(self.x, 0, self.x + 7, 7, 9)


Special Controls

The following special controls can be performed while a Pyxel application is running:

  • Alt(Option)+1
    Save the screenshot to the desktop
  • Alt(Option)+2
    Reset the recording start time of the screen capture video
  • Alt(Option)+3
    Save the screen capture video (gif) to the desktop (up to 30 seconds)
  • Alt(Option)+0
    Toggle the performance monitor (fps, update time, and draw time)
  • Alt(Option)+Enter
    Toggle full screen

Create Images

There are the following methods to create images for Pyxel:

  • Create an image from a list of strings with Image.set function
  • Load a png file in Pyxel palette with Image.load function
  • Create images with Pyxel Editor (WIP)

Please refer to the API reference for usage of Image.set and Image.load.

Because Pyxel uses the same palette as PICO-8, when creating png images for Pyxel, it is recommended to use Aseprite in PICO-8 palette mode.

API Reference


  • width, height
    The width and height of the screen

  • frame_count
    The number of the elapsed frames

  • init(width, height, [caption], [scale], [palette], [fps], [border_width], [border_color])
    Initialize the Pyxel application with screen size (width, height). The maximum width and height of the screen is 255
    It is also possible to specify the window title with caption, the display magnification with scale, the palette color with palette, the frame rate with fps, and the margin width and color outside the screen with border_width and border_color. palette is specified as a list of 16 elements of 24 bit color, border_color as 24 bit color

  • run(update, draw)
    Start the Pyxel application and call update function for frame update and draw function for drawing

  • quit()
    End the Pyxel application at the end of the current frame


  • mouse_x, mouse_y
    The current position of the mouse cursor

  • btn(key)
    Return True if key is pressed, otherwise return False (key definition list)

  • btnp(key, [hold], [period])
    Return True if key is pressed at that frame, otherwise return False. When hold and period are specified, True will be returned at the period frame interval when the key is held down for more than hold frames

  • btnr(key)
    Return True if key is released at that frame, otherwise return False


  • image(img, [system])
    Operate the image bank img(0-2) (see the Image class). If system is True, the image bank 3 for system can be accessed
    e.g. pyxel.image(0).load(0, 0, 'title.png')

  • clip(x1, y1, x2, y2)
    Set the drawing area of the screen to (x1, y1)-(x2, y2). Reset the drawing area with clip()

  • pal(col1, col2)
    Replace color col1 with col2 at drawing. pal() to reset to the initial palette

  • cls(col)
    Clear screen with color col

  • pix(x, y, col)
    Draw a pixel of color col at (x, y)

  • line(x1, y1, x2, y2, col)
    Draw a line of color col from (x1, y1) to (x2, y2)

  • rect(x1, y1, x2, y2, col)
    Draw a rectangle of color col from (x1, y1) to (x2, y2)

  • rectb(x1, y1, x2, y2, col)
    Draw the outline of a rectangle of color col from (x1, y1) to (x2, y2)

  • circ(x, y, r, col)
    Draw a circle of radius r and color col at (x, y)

  • circb(x, y, r, col)
    Draw the outline of a circle of radius r and color col at (x, y)

  • blt(x, y, img, sx, sy, w, h, [colkey])
    Copy the region of size (w, h) from (sx, sy) of the image bank img(0-2) to (x, y). If negative value is set for w and/or h, it will reverse horizontally and/or vertically. If colkey is specified, treated as transparent color

  • text(x, y, s, col)
    Draw a string s of color col at (x, y)


  • sound(snd)
    Operate the sound bank snd(0-63) (see the Sound class)
    e.g. pyxel.sound(0).speed = 60

  • play(ch, snd, loop=False)
    Play the sound bank snd(0-63) on channel ch(0-3). Play in order when snd is a list

  • stop(ch)
    Stop playback of channel ch(0-3)

Image Class

  • width, height
    The width and height of the Image

  • data
    The data of the Image (NumPy array)

  • set(x, y, data)
    Set the image as a list of strings at (x, y)
    e.g. pyxel.image(0).set(10, 10, ['1234', '5678', '9abc', 'defg'])

  • load(x, y, filename, [dirname])
    Read the png image from the directory of the execution script or dirname at (x, y)

  • copy(x, y, img, sx, sy, width, height)
    Copy the region of size (width, height) from (sx, sy) of the image bank img(0-2) to (x, y)

Sound Class

  • note
    List of note(0-127) (33 = ‘A2’ = 440Hz)

  • tone
    List of tone(0:Triangle / 1:Square / 2:Pulse / 3:Noise)

  • volume
    List of volume(0-7)

  • effect
    List of effects(0:None / 1:Slide / 2:Vibrato / 3:FadeOut)

  • speed
    The length of one note(120 = 1 second per tone)

  • set(note, tone, volume, effect, speed)
    Set a note, tone, volume, and effect with a string. If the tone, volume, and effect length are shorter than the note, it is repeated from the beginning

  • set_note(note)
    Set the note with a string consists of ‘CDEFGAB’+’#-‘+’0123’ or ‘R’. Case-insensitive and whitespace is ignored
    e.g. pyxel.sound(0).set_note('G2B-2D3R RF3F3F3')

  • set_tone(tone)
    Set the tone with a string consists of ‘TSPN’. Case-insensitive and whitespace is ignored
    e.g. pyxel.sound(0).set_tone('TTSS PPPN')

  • set_volume(volume)
    Set the volume with a string consists of ‘01234567’. Case-insensitive and whitespace is ignored
    e.g. pyxel.sound(0).set_volume('7777 7531')

  • set_effect(effect)
    Set the effect with a string consists of ‘NSVF’. Case-insensitive and whitespace is ignored
    e.g. pyxel.sound(0).set_effect('NFNF NVVS')

Other Information


Pyxel is under MIT license. It can be reused within proprietary software provided that all copies of the licensed software include a copy of the MIT License terms and the copyright notice.


VD3.09b readme


3.09B BUG更正rn========================================================================================rn* EDIT/FIELD配合EDITOR为CANLENDAR, 当_DATE_TYPE不为1或2时出现格式错误的问题, 已更正.rn* A/P SERVER的_DATE_TYPE没有与Client同步, 已更正.rn* 当GRID的Field加总时,如果DETAIL没有任何资料时会残留上一笔的加总值, 已更正(此为3.08以後rn 才有的新问题)rn* NEWFORM(Form,'',.T.,'别的VDS')时, 如果在2-TIER时(VD20模式), 会去找A/P SERVER,已更正如rn 果没有Login到A/P Server时不会去找A/P Server, 以相容VD20的模式.rn* MDI FORM的子视窗所出现的位置与大小不准确, 已更正能依照DesignTime的位置来调整之.rn* DRILLDOWN元件如果当对方表单SQuery的SQL语法有使用ALIAS别名时会失效, 已更正.rn* 更正程序编辑器新增的INSERT/DELETE TAB功能, 有时会发生INSERT错列的情况.(3.09A的新功能)rn* 更正 LookUpList 字段宽度有时会恢复成等宽的情况, 这是因为在设计模式对Global Form的rn LookupList存档时, 如果其CDS.Active=Fasle,就会发生, 此问题终於被找到了.rn* 更正Report有GroupFooter时, 当最後一页刚好打印完时, 其TotalPage值会多出一页的情况.rn* 更正Report的GroupHeader.PaintnewPage=True时, 在页尾刚好更换群组时其GroupHeader会重覆rn 印表.rn* Report的Memo与SubPanel在打印不下跨页时,则Detail如有垂直线在次页会没有划出, 已更正.rn* 当报表超过1,000 页时, 按下报表的上下页时会发生错误, 已更正.rn* 在MEMO元件编辑时, 如果在非'INS'模式下, 'CTRL-C'会无效, 已更正.rn* CDS与SQL元件, 在执行资料内容含有双引号(")与冒号(:)同时存在时, 会发生ERROR, 已更正.rn* FLsignature的Style为ssSignature时, Client端的数字签字打印不出来, 已更正每次都下载Serverrn 端users的数字签字图像, 但为了安全起见, 不会在Client下载这些BMP或JPG的数字签字文件, 另rn 更正当User的signature为BMP档时, FLSignature印表会发生ERROR的现象.rn* WorkFlow中的'通知删除'信息已更正改为'通知已删除',但须更正Server端的Applang0.ini(简体为rn Applang2.ini)rn rn3.09B 新功能说明rn=======================================================================================rn* 在VD3的DEBUG模式下, 可以在Windows的左下角工作列中'右键'中找到'DEBUG'选项, 让你容易选rn 择DEBUG的WINDOWS.rn* 增加一个VD30TEST.EXE的连线测试工具, 用来侦测VD30.EXE到A/P SERVER到Database Server间的rn 连线情况, 协助开发者与USER了解是哪一个环节出现问题, 详情请看下文重要Q&A.rn* DrillDown元件增加PARAMETERS的属性, 可用於DrillDown FORM/REPORT时, 传递这个PARAMETERSrn 参数给FORM与REPORT中, 可以用FORM.GETPARA()来取得, 此时GETPARA()除了取得PARAMETERS参数rn 外, 也可以取得另一个'@KEY:KEYFIELD=VAL'参数(指DrillDown的KEYField字段名称与内容).rn* DrillDown元件增加GridFont属性,用来控制如果目的为DataSet时,其Grid的Font就以此为准.rn* 设计模式的程序编辑器中,以'删除'去DELETE一个程序时,将会询问是否删除与否, 以防止误删.rn* FORM表单中增加OnRevive()事件,当FORM缩小被恢复时可以被触发此事件, 但只有MAIN FORM有效,rn 可以利用此方式来恢复缩小VD3後ACTIVE原来的表单, 如ACT_FORM为一个PUBLIC变数, 则在rn Main.OnRevive()设定:rn EXTERN ACT_FORMrn ACT_FORM.Focused()rn RETURNrn 在每个FORM的OnActive()中:rn EXTERN ACT_FORMrn ACT_FORM=THISrn RETURNrn* 增加CDS.COPYXLS(XLSFile-C,TITLE-C,OPEN-L), 同GRID.TOEXCEL()功能, 差别的是Grid是以rn Field为次序, CDS则以原来字段次序与所有字段皆输出.rn* 增加CDS.APPENDSDF(TXTFile-C,Separator-C), 可以将CDS.COPYSDF()资料传入,Separator-C最rn 好使用','或';',但如果资料内容有用到','或';'会造成冲突, 请自行注意.rn* BUTTON/SPEEDBUTTON增加了interactive(互动反应)/interactColor(互动颜色)/interactFontrn (互动字型),当Mouse移到此Button或SpeedButton时, 会自动反应此颜色与字型 (注意rn SpeedButton因为没有颜色, 所以只能反应字型).rn* 增加对OBJECT动态设定事件的功能, 原本OBJECT只能动态设定属性, 不能动态设定事件, 目前已rn 经可以利用_SYS_VD20_API的方式来动态设定, 如下:rn 在MYFOFM.INIT()中设定:rn _sys_vd20_api.SetEventSource(MYFORM,'onclose','MAIN.CHECK3()')rn RETURNrn* 增加_SYS_VD20_API.SetCaptionGap(Mode-N)功能, 统一来控制RptField的CaptionGap是否一定要rn 打印出, Mode-N:1一般为ON代表会打印出, 如果为OFF则代表不打印出CaptionGap的字段.(CaptionGaprn 代表RptField中Caption与字段内容间是否要有间隔字段, 如':")rn* Report在设计模式贴入RptLine, 如果高度比宽度长, 会自动设定LineStyle为直线, 否则为横线.rn* 在Report的环境下, 贴入Variable,SUM,MEMO,DetailTitle等元件时, 目前会自动预设与Report的rn Font同步, 不必每次都须更正.rn* FLSignTure元件增加SeparateTime=True/False, 为True时, 会将时间放下一列中, False则放在rn 同一列上.rn* FLsignture元件增加Stretch=True/False,True时,可以缩放ssSignature的数字签字的大小 (会自rn 动扣掉Date/Time的空间).rn* Flsignture增加DateAlign(Left/Center/Right), 用来控制Date与Time的对齐方式. 论坛