Why isn't Pygame more used?

Singaia

Member
Dec 15, 2018
136
67
I'm curious. Although Ren'py, which uses Pygame, seems to have plenty of use, Pygame by itself doesn't. I don't think I've seen a Pygame game on this site, and there are competent developers around.

So, is it Pygame too much hassle for a single developer? Or perhaps it doesn't have enough features for anything beyond a bare-bones game?

I might give it a try, since I want to brush up my Python skills and I dislike visual novels, but perhaps it's not worth it?
 
  • Like
Reactions: Marzepain

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,376
15,289
So, is it Pygame too much hassle for a single developer? Or perhaps it doesn't have enough features for anything beyond a bare-bones game?
Technically, it's none of that. It's just that why should one pass time to redo everything that is already done by Ren'py ?
Ren'py is a multi-OS interface between PyGame and the world, in perpetual development since now 15 years. Using it make you have both the potential power of PyGame, while not having to pass month to write the base of the interface. And it come with a bonus, the base features come with years of testing and improvements.
By using Ren'py, you know that your game will save and load correctly, whatever the supported OS is used by the player. By using your own save/load system on top of PyGame, you'll cross your finger that it will works, that you'll not encounter a rare case that will break it or, worse, silently corrupt it.
It possible to do this, but for the first year, you'll pass 90% of your time working on the interface, not on the game itself.


I might give it a try, since I want to brush up my Python skills and I dislike visual novels, but perhaps it's not worth it?
You can totally give it a try... by using Ren'Py.

It's a myth to believe that it's limited to visual novels, especially if you're ready to deal directly with PyGame. Ren'py come with features letting you create your own statements, so you can benefit from its lexer will still using your own addition.

Lets say that you want to make vertical scroller, you can add statements like :
defSprite that will define... the sprites used,
posSprite that will place if on the screen,
spritePattern that will define the patern you can assign to a sprite,
startLevel that will start the level, taking care of collision, movement and all.
Then have your code like :
Code:
defSprite minion1:
   img "this file"
   resistance 1
   power 1
defSprite minion2:
   img "that file"
   resistance 3
   power 2
defSprite boss: 
   img "another file"
   resistance 50
   power 10
   [...]

spritePattern spiral:
   angle 90 for 5
   angle -180 for 3
   angle 0 for 5
   [...]

label level1:
    posStrp:
       minion1
       x 1
       y 1
       start 1
       pattern spiral
    posStrp:
       minion1
       x 2
       y 1
       start 1
       pattern spiral
    posStrp:
       minion1
       start 1
       pattern spiral
    posStrp:
       minion1
       start 1
       pattern spiral
   [...]

   startLevel
You can use, or not, part of Ren'py's internal behind each statement, address directly PyGame when needed, while still have the benefit of all the strongest points of Ren'py.
startLevel can be, by example, a variation of the call screen statement, including a collision test before each refresh of the screen, and having a better handling of the keyboard interception.

It's probably even possible to directly use the screens. You just need to add two screens statements, one that will deal with the collision, and one that will move the sprites. Which would lead to something like :
Code:
screen allLevel:
   default x = 10
   default y = 150
   default bgOffset = 0

    timer 0.5 repeat True action If( bgOffset >= bgSize, SetScreenVariable( "bgOffset", bgOffset - 1 ), Return() )

    key "UP" action If( y > 10, SetScreenVariable( "y", y + 1 ), NullAction() )
    key "DOWN" action If( y < height, SetScreenVariable( "y", y - 1 ), NullAction() )
    key "LEFT" action If( x > 10, SetScreenVariable( "x", x - 1 ), NullAction() )
    key "RIGHT" action If( x < width, SetScreenVariable( "x", x - 1 ), NullAction() )

    add background offset bgOffset

    add collisionLoop
    add movingLoop

    for s in sprites:
       add s.img  pos s.pos
     
    add MCsprite xpos x ypos y
To be really efficient, it's probably better to rewrite If or have a dedicated statement replacing key, but that's all. You can definitively use the base that Ren'py already provide as interface between PyGame and the system, and add you own features on top of it.
 

Singaia

Member
Dec 15, 2018
136
67
Thank you very much for the detailed answer :). I'm guessing I'd be in for a world of hurt if it were not for your advice.

When I have more time available, I'm thinking about making some sort of RPG. Something like RPG Maker would be completely fine for what I have in mind, but I have no interest on JavaScript, and I'm doing this to develop my programming skills.

Would you have any general advice for developing RPGs on Ren'py? I intend to have keyboard movement, so I'll save your suggested code somewhere.
 

lobotomist

Active Member
Sep 4, 2017
834
746
Thank you very much for the detailed answer :). I'm guessing I'd be in for a world of hurt if it were not for your advice.

When I have more time available, I'm thinking about making some sort of RPG. Something like RPG Maker would be completely fine for what I have in mind, but I have no interest on JavaScript, and I'm doing this to develop my programming skills.

Would you have any general advice for developing RPGs on Ren'py? I intend to have keyboard movement, so I'll save your suggested code somewhere.
If you're going for an rpg why not use a game engine? godot uses a python like languaje
 
  • Like
Reactions: Singaia

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,491
7,036
You can totally give it a try... by using Ren'Py.
Just to add to anne O'nymous 's excellent answer, it's worth pointing out that the PyGame that's bundled inside Ren'py is not a full implementation, which does impose some limitations. Anne will probably correct me, but as I understand it, PyGame was originally based on , and originally Ren'py used that as-is. Eventually (2017?) SDL2 came out, which had a lot of improvements over the original SDL. Well prior to SDL2's being finished, however, PyTom took some of their in-progress work and created , his own partial remake of just the parts of PyGame that he depended on, using the SDL2 features. This allowed him to pick up on some of the "good bits" of SDL2 (better OpenGL support, Android, iOS, etc.) without having to wait for SDL2 to be done. But, when he did this, he didn't reimplement everything in PyGame in SDL2 - only the parts that he actually needed. As such, if you dive down into the PyGame classes from Ren'Py (easy to do in a custom Displayable, for example) you'll find that some methods aren't implemented. I ran into this when I was doing some custom transitions "back when."

All that being said, however, Anne's 100% correct that you can absolutely use Ren'py as a platform on which to experiment with PyGame, since it takes care of a lot of the nitty gritty dirty work of getting things up and running.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,376
15,289
Would you have any general advice for developing RPGs on Ren'py?
Keep It Simply Stupid.
Ren'py can do it. There's, somewhere on this forum, a RPG maker emulator made with Ren'py that prove it. But like it's an emulator, it's also an over complicated code, way more than what is needed natively by Ren'py.


Basically, giving a map system to Ren'py just need something like this :
Python:
init python:

    def movePlayer( direction, availability ):
        # At first we move it virtually.
        x = store.xPlayer
        y = store.yPlayer

        # Move according to the asked direction.
        if   direction == "up":    y -= 1
        elif direction == "down":  y += 1
        elif direction == "left":  x -= 1
        elif direction == "right": x += 1

        # The new case must be on the screen.
        if not 0 < y < len( availability ):    return
        if not 0 < x < len( availability[0] ): return

        # The new case must not be an obstacle.
        if availability[y][x] is False: return

        # The player can be on the case, validate the movement.
        store.xPlayer = x
        store.yPlayer = y

default xPlayer = 0
default yPlayer = 0

# False if the case is an obstacle, True else.
default map1Availability = [
    # First row.
    [ False, False, True, False, [...] ],
    # Second row.
    [ False, True, True, True, [...] ],
    [...]
    ]

# The map itself.
#  I use direct reference to the image, but it can be a displayable (which
# give support for animated tiles), or an ID to something.
default map1 = [
    # First row.
    [ "images/map/tree.png", "images/map/tree.png", "images/map/grass.png", "images/map/tree.png", [...]
    # Second row.
    [ "images/map/tree.png", "images/map/grass.png", "images/map/road.png", "images/map/grass.png", [...]

screen mapDisplayer( map, availability ):

    key "UP"    action Function( movePlayer, "up", availability )
    key "DOWN"  action Function( movePlayer, "down", availability )
    key "LEFT"  action Function( movePlayer, "left", availability )
    key "RIGHT" action Function( movePlayer, "right", availability )

    # Will automatically display the image a the right place
    # x = len of a row.
    # y = number of rows.
    grid len( map[0] ), len( map ):
        for y in range( 0, len( map ) ):
            for x in range( 0, len( map[0] ):
                add map[y][x]

    add player pos( xPlayer, yPlayer )


label whatever:
    call screen mapDisplayer( map1, map1Availability )
With this code, the map must be limited to the size of the screen, but it don't need big changes to deal with a map higher than the screen.
You just need to keep the coordinate of the top/left corner tile, then use them to limit the two for loops, and adjust the position of the player.

If you replace the add map[y][x] by something like :
Code:
    imagebutton:
        idle map[y][x]
        if availability[y][x] is True:
            action autoMove( x, y )
        else:
            action NullAction()
and add a custom displayable (or a timer code) to manage the automatic movement of the player, you can even move by clicking on a tile.

If you replace the entries in the map by an object, you can have the tiles and availability all in one. Make the object callable, and you can have direct interactions :
Code:
class myTile( renpy.python.RevertableObject ):
    def __init__( self, tile, obstacle, interact=store.autoMove ):
        self._tile = tile
        self._available = not obstacle
        self._interact = interact
    @property
    def tile( self ):
        return self._tile
    @property
    def available( self ):
        return self._available or not self._interact is None
    def __call__( self, x, y ):
        self._interact( x,  y )
And change the imagebutton :
Code:
    imagebutton:
        idle map[y][x].tile
        action Function( map[y][x], x, y )
Obviously, all this is basic code (and there's probably few errors in it since I wrote it on the fly). But the idea is here. You don't really need more than that to have a basic RPG-like map system, and it's a good base for an advanced one.


Anne will probably correct me,
Why correct something that is right ? Well, as long as I understood it myself.
It will perhaps change in the future (the 8.x versions), since pyTom intend to make it use Python 3.x. He'll perhaps use the occasion to change this... or not. But he just started working on it, so there's time, a lot of time.
 

Singaia

Member
Dec 15, 2018
136
67
If you're going for an rpg why not use a game engine? godot uses a python like languaje
Thanks for the tip. It indeed looks like an excellent engine, and it's also free. Right now I'm looking to know more about Python modules, functions, etc, and I may even do some completely unnecessary stuff merely for the sake of learning. Still, if I ever get bored with it, I may look more into this engine.

Basically, giving a map system to Ren'py just need something like this :

Again, thank very much for the help! Sometime soon I should be able to try out the code you sent and see how it goes. I also need to study Ren'py's API for a while to understand better what you just posted. I'm a motivated learner, but not a developer, so I'll need to do this gradually. I'll let you know how it goes, if I indeed try it.

By the way, you probably meant "Keep it simple, stupid" :D
 

lobotomist

Active Member
Sep 4, 2017
834
746
Thanks for the tip. It indeed looks like an excellent engine, and it's also free. Right now I'm looking to know more about Python modules, functions, etc, and I may even do some completely unnecessary stuff merely for the sake of learning. Still, if I ever get bored with it, I may look more into this engine.




Again, thank very much for the help! Sometime soon I should be able to try out the code you sent and see how it goes. I also need to study Ren'py's API for a while to understand better what you just posted. I'm a motivated learner, but not a developer, so I'll need to do this gradually. I'll let you know how it goes, if I indeed try it.

By the way, you probably meant "Keep it simple, stupid" :D
Bear in mind that the reason nobody makes more advanced games with python is its low performance. It may be good for visual novels, but for rpgs you're gonna need a bit more potency, case in point: https://f95zone.to/threads/rpgm2renpy-a-rpgmaker-emulator-in-renpy.19426/

I would personally recommend unity, thou.