Difference between revisions of "Complete Roguelike Tutorial, using python3+pysdl2, part 1"

From RogueBasin
Jump to navigation Jump to search
m (remove font fixed size on code blocks)
(removed non-related content)
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
<center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C" width="60%"><tr><td><center>
This tutorial is a draft, an unfinished tutorial. Feel free to talk and edit but do it knowing that much is yet to be done.
</center></td></tr></table></center>
<center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C"><tr><td><center>
<center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C"><tr><td><center>
This is part of a series of tutorials; the main page can be found [[Complete Roguelike Tutorial, using python3+pysdl2|here]].
This is part of a series of tutorials; the main page can be found [[Complete Roguelike Tutorial, using python3+pysdl2|here]].
Line 7: Line 12:


<center><h1>'''Graphics'''</h1></center>
<center><h1>'''Graphics'''</h1></center>
== Setting it up ==
Ok, now that we got that out of our way let's get our hands dirty!
=== Windows ===
==== Python ====
If you haven't already done so, [https://www.python.org/downloads/release/python-352/ download and install Python 3.5]. Any version of Python 3.x up to 3.5.x should be fine, but its not guaranteed to work.
PySDL2 is currently not working with Python 3.6.
This tutorial was written and tested using Windows 7 x64, Python 3.5.2 x86, PySDL2 0.9.5 and SDL2 x86 2.0.5.
It is advisable to go with 32 bit for compatibility's sake.
==== PySDL2 ====
The easiest way to install PySDL2 is using pip:
<syntaxhighlight lang="bash">
$ python -m pip install pysdl2
</syntaxhighlight>
If you would like another form of installation you can look for it at [http://pysdl2.readthedocs.io/en/rel_0_9_5/install.html PySDL2's installing instrunctions].
==== SDL2 ====
Download the latest release of [https://www.libsdl.org/download-2.0.php SDL2] and extract it somewhere. Be warned that both Python and SDL2 must either be <b>both 32 bit</b>, or <b>both 64 bit</b>.  If you get dll loading errors, getting this wrong is the most likely cause. The SDL2 should be added to your PATH environment variable or placed at the project's folder.
Another option is to tell PySDL2 where the library is located. You can do that py adding those lines at the start of your main python file (explained below):
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
import os
os.environ["PYSDL2_DLL_PATH"] = "C:\\lib\\SDL2-2.0.5-win32-x86"
</syntaxhighlight></div>
== Choice of code editor ==
If you're just starting out with Python, you'll find that many Python coders just use a simple editor and run their scripts from a console to see any debugging output. Most Python coders don't feel the need to use a fancy IDE! On Windows, Notepad++ is an excellent bet; most Linux programmers already have an editor of choice. Almost all editors allow you to configure shortcut keys (like F5 for instance) to quickly run the script you're editing, without having to switch to a console.
[[Complete Roguelike Tutorial, using Python+libtcod, extras#A neat Python shortcut for Notepad++|See this page]] if you want to set up a Notepad++ shortcut with a couple of nice features for debugging, or if you tried to roll your own and hit the infamous "module not found" error.
Personally I'm using [https://www.sublimetext.com/3 Sublime Text 3] with the installed packages: [https://github.com/srusskih/SublimeJEDI Jedi - Python autocompletion]; [https://github.com/dreadatour/Flake8Lint Python Flake8 Lint]; [https://github.com/MattDMo/PythonImproved Python Improved]. Coloring, highlighting, linting, extending it pretty much however you want, etc. makes it like work like a fancy IDE - but lighter. It runs on my toaster! :)
==== Your project folder ====
Now create your project's folder. Inside it, create two empty files ''constants.py'' and ''manager.py''.  It'll make the tutorial easier to just use the same names for now, and you can always rename it later.
+-pysdl2-roguelike-tutorial/
  |
  +-constants.py
  |
  +-manager.py
If you chose to keep the SDL2 library at the project folder, it should now look like this:
+-pysdl2-roguelike-tutorial/
  |
  +-constants.py
  |
  +-manager.py
  |
  +-README-SDL.txt
  |
  +-SDL2.dll (.dll for Windows, .so for Linux).
We will omit the sdl library and txt from now on when we list the folder's content. If you have it, just remember that you will have those two additional files on top of what is shown.
You're ready to start editing stuff!
== Defining constants ==
It's good practice to define constants, special numbers that might get reused. ''Constants are usually defined on a module level and written in all capital letters with underscores separating words'', according to [https://www.python.org/dev/peps/pep-0008/ Python's style guide] - its not required, but it should make your code more readable for other people, so we're following this style. Let's create a file named ''constants.py'' at our project's folder and write on it:
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
"""Game constants."""
# size of a (square) tile's side in pixels.
TILE_SIZE = 32
# the width of the screen in pixels.
SCREEN_WIDTH = 1024
# the height of the screen in pixels
SCREEN_HEIGHT = 768
# maximum frames per second that should be drawn
LIMIT_FPS = 30
# the window's background color (RGBA, from 0-255)
WINDOW_COLOR = (0, 0, 0, 255)
</syntaxhighlight></div>
Now that we have our contants defined is time to create our scene manager!
== Wait, manager? Ain't we making a game?. ==
SDL2 is a C library. PySDL2 is a python wrapper for that library. But remember we've said at the tutorial introduction that SDL2 is not a game engine? We're going to create some classes to make our lives easier - make it game engine'ish, in an Object-Oriented way. It will take a few lines before we can see our character on the screen, but it will save us lots of time in the future.
If you don't care about the implementation of the ''Manager'' and related classes just download the [https://github.com/LukeMS/pysdl2-roguelike-tutorial/releases/tag/v0.1.1 0.x release] (pre-part 1 implementation of our tutorial's code is released as 0.x'ish versions) of the project on GitHub and skip to the next section. The code should be reasonably well described, with lots of docstrings and comments (file an issue if something is not described well enough :) so that you may be able to understand it all just by looking at (actually, reading) it.
Before we deal with the ''Manager'', we're going to work on a ''Clock'', the class that will control our frame rate among time.
=== Tick the Clock ===
Pygame had a Clock, using SDL v1.x. pygame-sdl2 adapted [https://github.com/renpy/pygame_sdl2/blob/master/src/pygame_sdl2/pygame_time.pyx it] to SDL 2, but using Cython (this could actually be considered good, considering performance, but at this tutorial we're aiming at pure Python). PySDL2, which is pure Python, lacks one. So, instead of reinventing the wheel, with a few syntax modifications and lots of docstrings, we're going to use a python version of the cython one. You can see its implementation [[Complete Roguelike Tutorial, using python+pysdl2, part 1 code#util/time.py|here]] or just download it from [https://github.com/LukeMS/pysdl2-roguelike-tutorial/raw/master/util/time.py here]. Make sure its placed under ''util/time.py''.
You're still here? Then let's edit ''manager.py''.
=== Manager, at least ===
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
# ctypes will be required for a single time, don't let it scare you!
import ctypes
import os
# tell sdl2 where your library is
os.environ["PYSDL2_DLL_PATH"] = "C:\\lib\\SDL2-2.0.5-win32-x86"
# import sdl2
import sdl2
# and sdl2.ext, where the pythonic part of the pysdl2 resides
import sdl2.ext
# import the constants we've defined
from constants import (SCREEN_WIDTH, SCREEN_HEIGHT, TILE_SIZE, LIMIT_FPS,
                      WINDOW_COLOR)
#
from util.time import Clock
</syntaxhighlight></div>
'''TODO: describe the Manager and BaseScene creation, modified utilites rect and time, etc.'''


== Showing the character on screen ==
== Showing the character on screen ==


Time to work with ''rl.py'' - the truly useful lines of our game. Create it in the project's folder. Create it in the project's folder.
Time to work with ''rl.py'' - the shiny part our game. Create it in the project's folder.
Now we should have something like tis:


For this step we're going to need a character sprite. Don't worry, we will draw some letters in the tradition of roguelikes later on. But for now lets use an image.
For this step we're going to need a character sprite. Don't worry, we will draw some letters in the tradition of roguelikes later on. But for now lets use an image.
I'm using art by David E. Gervais, available [http://pousse.rapiere.free.fr/tome/tiles/DO/tome-domonsterstiles.htm here] under [https://creativecommons.org/licenses/by/3.0/ CC BY 3.0 license]. Specifically I'm using ``HalfOgreFighter3.png``, because, well, they look mighty!
We're using art by David E. Gervais, available [http://pousse.rapiere.free.fr/tome/tiles/DO/tome-domonsterstiles.htm here] under [https://creativecommons.org/licenses/by/3.0/ CC BY 3.0 license]. Specifically we're using ``HalfOgreFighter3.png``, because, well, they look mighty!
Note that those sprites are in 54x54 resolution. And they have a pink background. A [https://github.com/LukeMS/pysdl2-roguelike-tutorial/blob/master/resources/HalfOgreFighter3.PNG proper sized version with transparent background] is available at the project's GitHub. If you downloaded the 0.x release above you should already have it in your project's folder.
Note that those sprites are in 54x54 resolution. And they have a pink background. A [https://github.com/LukeMS/pysdl2-roguelike-tutorial/blob/master/resources/HalfOgreFighter3.PNG proper sized version with transparent background] is available at the project's GitHub. Create a ''resources'' folder and save the image on it. Save the [https://github.com/LukeMS/pysdl2-roguelike-tutorial/raw/master/resources/davir_gervais_tileset.license license] there too, so that we do not forget to give the author its deserved credits.


And by now our folder should look like this:
By now your project's folder should look like this:
  +-pysdl2-roguelike-tutorial/
  +-pysdl2-roguelike-tutorial/
   |
   |
Line 157: Line 32:
   +-resources/
   +-resources/
   | |
   | |
   | +-davir_gervais_tileset.license
   | +-[https://github.com/LukeMS/pysdl2-roguelike-tutorial/raw/master/resources/davir_gervais_tileset.license davir_gervais_tileset.license]
   | |
   | |
   | +-HalfOgreFighter3.png
   | +-[https://github.com/LukeMS/pysdl2-roguelike-tutorial/raw/master/resources/HalfOgreFighter3.png HalfOgreFighter3.png]
   |
   |
   +-util/
   +-util/
    |
    +-dir_tree.py
     |
     |
     +-time.py
     +-time.py


Since we created some nice interface classes for ourselves (''Manager'', ''SceneBase'') we won't even need to import sdl2 for now.
Because we did some hard work creating our ''Manager'', ''SceneBase'', etc., we won't even need to import sdl2 for this part. All we need is to import those classes (and ''Resources'') from ''manager'':
All we need is to import the mentioned classes (and ''Resources'') from ''manager'':
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
from manager import Manager, SceneBase, Resources
from manager import Manager, SceneBase, Resources
</syntaxhighlight></div>
</syntaxhighlight></div>


We're aiming at a Object-Oriented design, because Python's OO rocks and because we can abstract part of our code (as we just did) and keep it separate from our game logic. What we're going to do now is create a subclass of ''SceneBase'':
 
Let's put Inheritance to work by subclassing ''SceneBase'':


<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
Line 200: Line 73:
         self.manager.spriterenderer.render(sprites=self.sprite)
         self.manager.spriterenderer.render(sprites=self.sprite)
</syntaxhighlight></div>
</syntaxhighlight></div>
 
That would be all for now.
And at the end of the ''rl.py'', we're adding:
To test, at the end of the ''rl.py'', adding the belo lines and run it:
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
if __name__ == '__main__':
if __name__ == '__main__':
Line 220: Line 93:
[[File:Roguelike_tutorial_pysdl2-part1-character_on_screen.png|center]]
[[File:Roguelike_tutorial_pysdl2-part1-character_on_screen.png|center]]


== Show me the @!!! ==
In this tutorial we're using a bitmap created from a regular font. I've done this myself and you can download it here.
Now, something libtcod-specific: we're going to use a custom font! It's pretty easy. libtcod comes bundled with a few fonts that are usable right out of the box. Remember however that they can be in different '''formats''', and you'll need to tell it about this. This one is "grayscale" and using the "tcod layout", most fonts are in this format and thus end with ''_gs_tc''. If you wanna use a font with a different layout or make your own, the [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_set_custom_font.html?c=false&cpp=false&cs=false&py=true&lua=false docs on the subject] are really informative. You can worry about that at a later time though. Notice that the size of a font is automatically detected.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)</syntaxhighlight></div>
This is probably the most important call, initializing the window. We're specifying its size, the title (change it now if you want to), and the last parameter tells it if it should be fullscreen or not.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod tutorial', False)</syntaxhighlight></div>
For a real-time roguelike, you wanna limit the speed of the game (frames-per-second or FPS). If you want it to be turn-based, ignore this line. (This line will simply have no effect if your game is turn-based.)
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #D0FFC2"><syntaxhighlight lang="python">libtcod.sys_set_fps(LIMIT_FPS)</syntaxhighlight></div>
Now the main loop. It will keep running the logic of your game as long as the window is not closed.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">while not libtcod.console_is_window_closed():</syntaxhighlight></div>
For each iteration we'll want to print something useful to the window. If your game is turn-based each iteration is a turn; if it's real-time, each one is a frame. Here we're setting the text color to be white. [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/color.html?c=false&cpp=false&cs=false&py=true&lua=false There's a good list of colors you can use here], along with some info about mixing them and all that. The zero is the console we're printing to, in this case the screen; more on that later.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">    libtcod.console_set_default_foreground(0, libtcod.white)</syntaxhighlight></div>
Don't forget the indentation at the beginning of the line, it's extra-important in Python. '''Make sure you don't mix tabs with spaces for indentation!''' This comes up often if you copy-and-paste code from the net, and you'll see an error telling you something about the indentation (that's a pretty big clue right there!). Choose one option and stick with it. In this tutorial we're using the 4-spaces convention, but tabs are easy to work with in many editors so they're a valid choice too.
Now print a character to the coordinates (1,1). Once more the first zero specifies the console, which is the screen in this case. Can you guess what that character is? No, it doesn't move yet!
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">    libtcod.console_put_char(0, 1, 1, '@', libtcod.BKGND_NONE)</syntaxhighlight></div>
At the end of the main loop you'll always need to present the changes to the screen. This is called ''flushing'' the console and is done with the following line.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">    libtcod.console_flush()</syntaxhighlight></div>
Ta-da! You're done. Run that code and give yourself a pat on the back!
<center><table border="0" cellpadding="10" cellspacing="0" style="background:#F0E68C" width="65%"><tr><td><center>
<b>Common reasons the code won't run.</b></center>
* On Windows? Is either of the libtcod or SDL dlls not found?<br/><i>Make sure your Python and libtcod are either BOTH 32 bit, or BOTH 64 bit.</i>
* Python errors? Using Python 3?<br/><i>We said above that this tutorial is only for Python 2.  So use Python 2, with Python 3 you are on your own.  They're different languages, it won't just magically work!</i>
* Still blocked?  Check out the [[Complete_Roguelike_Tutorial,_using_Python+libtcod,_problems|problems page]].
</td></tr></table></center>
Note that since we don't have any input handling code, the game may crash on exit (it won't process the OS's requests to close). Oops! Don't worry though, this problem will go away as soon as we add keyboard support.
[[Complete Roguelike Tutorial, using python+libtcod, part 1 code#Showing the @ on screen|Here]]'s the complete code so far.
== Moving around ==
That was pretty neat, huh? Now we're going to move around that @ with the keys!
First, we need to keep track of the player's position. We'll use these variables for that, and take the opportunity to initialize them to the center of the screen instead of the top-left corner. This can go just before the main loop.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">playerx = SCREEN_WIDTH/2
playery = SCREEN_HEIGHT/2</syntaxhighlight></div>
There are functions to check for pressed keys. When that happens, just change the coordinates accordingly. Then, print the @ at those coordinates. We'll make a separate function to handle the keys.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">def handle_keys():
    global playerx, playery
   
    #movement keys
    if libtcod.console_is_key_pressed(libtcod.KEY_UP):
        playery -= 1
       
    elif libtcod.console_is_key_pressed(libtcod.KEY_DOWN):
        playery += 1
       
    elif libtcod.console_is_key_pressed(libtcod.KEY_LEFT):
        playerx -= 1
       
    elif libtcod.console_is_key_pressed(libtcod.KEY_RIGHT):
        playerx += 1</syntaxhighlight></div>
Done! These are the arrow keys, if you want to use other keys here's a [http://roguecentral.org/doryen/data/libtcod/doc/1.5.1/html2/console_keycode_t.html?c=false&cpp=false&cs=false&py=true&lua=false reference] (pay attention to the Python-specific notes).
While we're at it, why not include keys to toggle fullscreen mode, and exit the game? You can put this at the beginning of the function.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python"> 
    key = libtcod.console_check_for_keypress()
    if key.vk == libtcod.KEY_ENTER and key.lalt:
        #Alt+Enter: toggle fullscreen
        libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
       
    elif key.vk == libtcod.KEY_ESCAPE:
        return True  #exit game</syntaxhighlight></div>
From now on, we'll show code for a <span style="background-color: #D0FFC2">'''real-time game'''</span> with a green background, and code for a <span style="background-color: #DFEEFF">'''turn-based game'''</span> with a blue background.
Notice a subtle difference here. The ''console_is_key_pressed'' function is useful for real-time games, since it checks if a key is pressed with no delays. ''console_check_for_keypress'', on the other hand, treats the key like it's being typed. So after the first press, it will stop working for a fraction of a second. This is the same behavior you see when you type, otherwise pressing a key would result in you typing 3 or 4 letters! It's useful for all commands except movement, which you usually want to react as soon as possible with no delays, and continue for as long as you press the movement keys.
Now here's an important thing: you can use that first line to distinguish between real-time and turn-based gameplay! See, ''console_check_for_keypress'' won't block the game. But if you replace it with this line:
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #DFEEFF"><syntaxhighlight lang="python">    key = libtcod.console_wait_for_keypress(True)</syntaxhighlight></div>
Then the game won't go on unless the player presses a key. So effectively you have a turn-based game now.
Now, the main loop needs to call this function in order for it to work. If the returned value is True, then we "break" from the main loop, ending the game. The inside of the main loop should now look like this:
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">
    libtcod.console_set_default_foreground(0, libtcod.white)
    libtcod.console_put_char(0, playerx, playery, '@', libtcod.BKGND_NONE)
   
    libtcod.console_flush()
   
    #handle keys and exit game if needed
    exit = handle_keys()
    if exit:
        break</syntaxhighlight></div>
The reason why we draw stuff before handling key input is that, in a turn-based game, the first screen is shown before the first key is pressed (otherwise the first screen would be blank).
One more thing! If you try that, you'll see that moving you leave around a trail of little @'s. That's not what we want! We need to clear the character at the last position before moving to the new one, this can be done by simply printing a space there. Put this just before ''exit = handle_keys()''.
<div style="padding: 5px; border: solid 1px #C0C0C0; background-color: #F0F0F0"><syntaxhighlight lang="python">        libtcod.console_put_char(0, playerx, playery, ' ', libtcod.BKGND_NONE)</syntaxhighlight></div>
[[Complete Roguelike Tutorial, using python+libtcod, part 1 code#Moving around|Here]]'s a rundown of the whole code so far.
[[Complete Roguelike Tutorial, using python+libtcod, part 2|Go on to the next part]].


[[Category:Developing]]
[[Category:Developing]]

Latest revision as of 16:14, 2 December 2017

This tutorial is a draft, an unfinished tutorial. Feel free to talk and edit but do it knowing that much is yet to be done.


This is part of a series of tutorials; the main page can be found here.


Graphics

Showing the character on screen

Time to work with rl.py - the shiny part our game. Create it in the project's folder.

For this step we're going to need a character sprite. Don't worry, we will draw some letters in the tradition of roguelikes later on. But for now lets use an image. We're using art by David E. Gervais, available here under CC BY 3.0 license. Specifically we're using ``HalfOgreFighter3.png``, because, well, they look mighty! Note that those sprites are in 54x54 resolution. And they have a pink background. A proper sized version with transparent background is available at the project's GitHub. Create a resources folder and save the image on it. Save the license there too, so that we do not forget to give the author its deserved credits.

By now your project's folder should look like this:

+-pysdl2-roguelike-tutorial/
  |
  +-constants.py
  |
  +-manager.py
  |
  +-rl.py
  |
  +-resources/
  | |
  | +-davir_gervais_tileset.license
  | |
  | +-HalfOgreFighter3.png
  |
  +-util/
    |
    +-time.py

Because we did some hard work creating our Manager, SceneBase, etc., we won't even need to import sdl2 for this part. All we need is to import those classes (and Resources) from manager:

from manager import Manager, SceneBase, Resources


Let's put Inheritance to work by subclassing SceneBase:

class RogueLike(SceneBase):
    """An aspiring Roguelike game's scene."""

    def __init__(self, **kwargs):
        """Initialization."""
        # Nothing there for us but lets call super in case we implement
        # something later on, ok?
        super().__init__(**kwargs)

        # pass the name of the resource to the sdl2.ext.Resources instance on
        # manager.py
        fname = Resources.get("HalfOgreFighter3.png")

        # use the pysdl2 factory to create a sprite from an image
        self.sprite = self.factory.from_image(fname)

        # set it to a position to look better on our screenshot :)
        self.sprite.position = (128, 128)

    def on_update(self):
        """Graphical logic."""
        # use the render method from manager's spriterenderer
        self.manager.spriterenderer.render(sprites=self.sprite)

That would be all for now. To test, at the end of the rl.py, adding the belo lines and run it:

if __name__ == '__main__':
    # create a game/Manager instance
    # we're using an arbitrary size to put our half-ogre right in the middle 
    # of the screen
    m = Manager(width=288, height=288)

    # pass our created RogueLike scene to the Manager
    m.set_scene(scene=RogueLike)

    # make it fly!
    m.run()

And now we should be able to see a mighty half-ogre in the middle of a black screen:

Roguelike tutorial pysdl2-part1-character on screen.png