Pyxel is a retro game development environment in 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 paletts of Pyxel are reffering to awesome PICO-8 and TIC-80.

Pyxel is open souce 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 4 image banks
  • 4 channels with 64 definable sound banks
  • Keyboard, mouse, and joystick(WIP) inputs
  • Image and sound editor (WIP)

How to Install


After installing Python3, the following pip command installs Pyxel:

pip install pyxel


After installing Python3 and glfw, 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.


pacman -S python python-pip glfw portaudio
pip install pyxel


apt-get install python3 python3-pip glfw libportaudio2 libasound-dev
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)
    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

  • 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)
    Operate the image bank img(0-3) (see the Image class)
    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 rectanble 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-3) to (x, y). If negative value is set for w and/or h, it will reverse horizontally and/or vertically. If colkey is speficied, 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)
    Read png image 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-3) to (x, y)

Sound Class

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

  • tone
    List of tone(0:Triagnle / 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 efffect 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')