Advertisement

Should I drop pygame?

Started by May 04, 2017 06:49 PM
18 comments, last by Lucas_Cage 7 years, 6 months ago

Before you go any further I would like you to look at the files in this repo. I have used Pygame in this Windows utility.

Use the code if you wish to but give me som credit.. :)

https://bitbucket.org/diliupg/file_rename_new

I've been making a game in Pygame but I recently read the post "is my Idea Possible with Pygame". Since I've been struggling just to make a button class with Pygame

This is normal, and in fact happens to everybody until the day they stop programming.

I want to make a game working (it's broken now), and I have only vague ideas how to do that. I have code, but it doesn't work. I have never solved this problem before. Yes my problem is an order of magnitude bigger than yours, but the idea is the same.
You want to achieve something, you are trying, but it's not doing what you want it to do. This is to a large part, programming. You solve stuff you've never done before, and at first it seems possible, then it appears really more complicated than it looked, if you're unlucky, you find even more nasty corners where you don't want to go. How do you cope with that? Mostly, stick with it. This problem is not going to win.
I try to solve it one way. The problem deflects my attempt, it doesn't work. At this moment, I stop, and analyze why my attempt failed. Why can't I make it work, what am I missing? The next question is then "How to avoid this from happening again?". The answer to that is where you learn. That's progress.
Then regroup, and attack again, with this new knowledge. At some point, the problem will run out of new nasty corners that I haven't seen. Then I'll win.

The "how to avoid" question has many possible answers.
Running away to another language or programming system is not the answer. The same thing will happen there again, at some point. For a CS study, I'd say it's not even an option. Your job will be fighting problems, you're eventually supposed to know how to do that. Fire fighters also don't say "euhm, big fire eh? Let's go elsewhere, find a smaller one".
Don't see your program as the sure-fire solution to whatever complicated problem you're trying to solve. It doesn't work that way. You're fighting a problem you have never seen before, let alone that you understand it. Coding a solution is therefore likely to fail. It's like going on a holiday, and when you board the plane, they say, oh, you seem smart, can you fly the plane for us, that would be lovely! They throw you into the cockpit, and lock the door. "Good luck!".
Is flying a plane a solvable problem? Yep, you can see these things flying all around the world. Can you just do it on your first attempt? Not bloody likely.
So how do you get to the destination then? Simple, you experiment. You try a few knobs, read some labels, etc. In some time you manage to taxi around the airport. Eventually, you can fly this thing, given enough attempts.
Now a small problem in real-life is that plane crashes tend to be lethal. Therefore, it's not so likely you will be able to reach your holiday destination, I am sorry to say. In computer systems, not so much. most problems can be tried over and over again, in all possible scenarios. In programming, doing experiments works. While they generally fail to control the problem, they do give you information about the problem in how they fail, and you use that new knowledge in the next experiments. Eventually, you covered all basic problems, and it flies! Oh man, such a sweet moment if the thing you're coding actually works!

One of the reasons I've become wary about Pygame because in the thread it was mentioned that Pygame is best for small short projects. I don't let myself have (too many) grandiose plans but I'd like something I can easily just continue working with indefinitely.

"Easy" and "indefinitely" don't work well together. Bigger problems become exponentially harder as they grow in size. A bicycle is simple to get to your holiday destination (it's not so fast, but definitely simple). A car is much less simple (gears, clutch, gasoline, rules of how to use the road, signs, etc etc), and an airplane, euhm yeah, next to impossible, I'd say.
What you consider "small and short" is probably much less small and short than you think.

To sum up, my question is what should I do at this point, stick with Pygame, or learn C# and use unity, or maybe work with some completely different sort of game-making software.

A good strategy in surviving anything complicated is to reduce scale. Don't try the big thing until you know at least some of the small parts. You don't go out on the high way with a car driving lesson before you know about gears and clutches. Same applies in programming. Start small to build basic knowledge before you tackle the big thing. It's not working? If it is not a simple mistake you know how to correct, it might be still too big. Make it smaller. Failures is learning experience, success is confirmation that you know enough of the problem to control it for the case you tried.

Obviously, scaling down doesn't always work. In that case, invent another experiment, or understand why it doesn't work, and adapt. Be flexible, find that attacking angle that avoids all problems you are aware of, and bring that problem down to its knees.

C# and Unity will shuffle more problems onto your plate, which is in the wrong direction with respect to scaling down. While they appear to make it simpler (and from what I heard they do), but it's mostly in the ground-work. Things like "let's order some bricks and wood now, since you're building a house, surely these will be needed.
They do not decide for you what house to build.

Start small, stick with Python and py-game, they give you enough trouble, you don't need more trouble, you need less.

BTW, Python and C# have a lot of common ideas. Sure, Python looks different than C# (and it will feel different as well), but knowledge in one language can generally at least partly be transferred to another language, in particular your knowledge how to fight problems that aren't very co-operative!

Advertisement

Much good advice above. I'll reiterate the following:

  • Python is a good language, worth knowing. Any syntax problems that you're currently having in Python will be matched in number (and more besides) in any other language you use. The best skill you can acquire is the ability to overcome these problems.
  • Pygame is indeed limited but that doesn't matter. If you're making a "small short project" then finish it with your current language. You can consider something different for the next project.
  • Any good programmer is going to have to learn a handful of languages in order to be productive. There's no such thing as learning the 'wrong' one or being stuck in a dead-end because the skill of learning new ones is one you'll have to cultivate. Luckily, moving between the more popular languages like Java, C#, and C++ is very easy, and Python is not much different to those. You don't need to worry now about languages you might need in 3, 5, 10 years time. It's not like natural languages. You can pick a new one up every couple of months if you like.
  • GUI programming is awkward. Finding it tricky to create a button that works in the way you expect is not a sign that you are a bad programmer or that the language or library is broken. There's a lot of complexity in there - rendering, input handling, data structures - that go towards making a functional GUI. Do feel free to ask specific questions about implementation, and if you'd rather not be spoon-fed the answers, you can just say that in your question and ask for hints instead. :)

Wow, I'm a little amazed at all the responses. Okay, if everyone here argues I should stick with Pygame/Python for now, I can be pretty sure that's the right thing to do. I'll redesign my project to something smaller and with a definite finish point. Thanks for the advice everyone. I really appreciate it.

I'll redesign my project to something smaller and with a definite finish point.

That will certainly help, but I think based on your descriptions you would be even better served by finding a good mentor in the language or an online course that includes real people who can help you understand the course material.

Having issues with things like creating a class or returning correct values are at a more fundamental level than writing a game. Before you can write a game you need to know how to write code in general. Learn to crawl before learning to walk and all that.

I'll redesign my project to something smaller and with a definite finish point.

That will certainly help, but I think based on your descriptions you would be even better served by finding a good mentor in the language or an online course that includes real people who can help you understand the course material.

Having issues with things like creating a class or returning correct values are at a more fundamental level than writing a game. Before you can write a game you need to know how to write code in general. Learn to crawl before learning to walk and all that.

I understand how to create classes and return correct values. I am sure having a mentor would help me, but I'm having trouble with Pygame, not Python in general. My issue is that I want to return a pygame event into the game loop and I don't understand how to do that or how to get around it if it's not possible.

Here is the function I'm trying to use to handle how clicking buttons affects the game:


def butts(isClick, screenList):
    """handles buttons"""
    if isClick[0] == True:
        rat = pg.mouse.get_pos()

        for eItem in screenList:
            for ei in eItem:
                # if button-X + button Width > mouse-X > button-X
                # and button-Y + button Width > mouse-Y > button-Y
                if ei[0] + ei[2] > rat[0] > ei[0] \
                        and ei[1] + ei[3] > rat[1] > ei[1]:
                    if ei[-1] == "Exit":
                        return pg.QUIT

My Button class:


import pygame as pg

class Button:
    """
    Creates a button
    """
    _buttList = []
    def __init__(self, x, y, w, h, imgAddr, name):
        """
        x and y are ints and
        indicate where the top right corner of the button will be
        
        w is an int that
        represents how wide the button will be
        
        h is an int that
        represents the height of the button
        
        imgAddr is a string that holds the image address on it
        it is used to create a pygame image object
        
        name is a string indicating button function
        """
        # inits self._image to pygame image object
        self._image     = pg.image.load(imgAddr)

        #pygame x y coordinates
        self._x         = x
        self._y         = y

        #width and height of button
        self._w         = w
        self._h         = h

        self._buttList = []
        self._buttList.append((self._x, self._y, self._w, self._h, self._image, name))
        #self._index = 0

    def draw(self, surf):
        """
        draws a button the window
        :param surf: 
        surf is the pygame surface window the button is drawn to
        """
        # draws button to screen
        surf.blit(self._image, ((self._x, self._y), (self._w, self._h)))

    def __getitem__(self, index):
        """
  
        :param index:
        int that finds proper index
    
        """
        #print(index)
        #print("button list:",self._buttList)
        result = self._buttList[index]
        return result

my MainMenu class:


"""
Contains classes to handle the various screens of the game
"""
__author__ = "RidiculousName"
__date__ = "4/22/17"
#imports Button class
from button import Button as b
import pygame as pg
class MainMenu:
    """
    Class that handles the main menu screen
    """
    def __init__(self, surf):
        """
        surf is a pygame.surface object that
        the buttons, images, etc. are blitted to
        
        isClick is a pygame mouse object that
        determines whether the mouse has been clicked
        """
        # where main menu images are located
        self._i = "images/mainMenu/"
        self._surf = surf
        self._surf.fill((0,0,0))    #fill surface with white

        #list of main menu buttons
        # x value, y value, width, height, image path, surface, button type
        self._mmList = [
        b(150, 300, 200, 80, self._i + "mmResume.png",
                         "Resume"),
        b(150, 400, 200, 80, self._i + "mmStart.png",
                        "Start"),
        b(150, 500, 200, 80, self._i + "mmLoad.png",
                       "Load"),
        b(150, 600, 200, 80, self._i + "mmCreate.png",
                         "Create"),
        b(150, 700, 200, 80, self._i + "mmExit.png",
                       "Exit"),
        b(600, 100, 400, 160, self._i + "mmTitle.png",
                        "Title")
        ]

        # blits buttons to screen
        for ei in self._mmList:
            b.draw(ei,surf)

    def getScreenList(self):
        return self._mmList


and my main function, where I try to put it all together:


def main():
    """ set up the game and run the main game loop """
    pg.init()  # prepare pygame module for use
    surfW = 1600  # window width
    surfH = 900  # window height

    # create window
    surf = pg.display.set_mode((surfW, surfH))

    #set window caption
    pg.display.set_caption("Aztlan")

    while True:
        #opens first screen
        mm = MainMenu(surf)

        #print(type(butts(pg.mouse.get_pressed(), mm.getScreenList())))

        butts(pg.mouse.get_pressed(), mm.getScreenList())

        ev = pg.event.poll()    # look for any event



        if ev.type == pg.QUIT:  # window close button clicked?
            break



        pg.display.flip()

    pg.quit()


if __name__ == "__main__":
    main()

It doesn't return an error. I just can't get the exit button to work regardless.

Advertisement

Your bug is in not catching and processing a returned value, but I'd like to suggest a bit cleanup first.


def butts(isClick, screenList):
    """handles buttons"""
    if isClick[0] == True:
        rat_x, rat_y = pg.mouse.get_pos()

        for eItem in screenList:
            if eItem._x + eItem._w > rat_x > eItem._x \
                    and eItem._y + eItem._h > rat_y > eItem._y:
                if eItem._name == "Exit":
                    return "quit"

    return "continue"

The 'screenList' is a list buttons, and you can simply access fields from the button. That makes your code a whole lot more readable.

I also replaced your magic "pg.QUIT" value by a piece of text.

In the main function


while True:
    ....
    butts(pg.mouse.get_pressed(), mm.getScreenList())   

You are not getting the returned value from the 'butts' call. The value that you return from the function is just lost thus.

With my 'quit' string return value, the call would be something like


while True:
    ....
    next_action = butts(pg.mouse.get_pressed(), mm.getScreenList())
    if next_action == 'quit':
        break

Note that values like pygame.QUIT look like magic, but they're not. They are simple numeric values given a name, as you can simply try:


Python 3.5.3 (default, Apr 24 2017, 13:32:13)
[GCC 6.3.1 20161221 (Red Hat 6.3.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygame
>>> pygame.QUIT
12

See, it's just the number 12 in disguise.

It is usually best to make your own ways to return results from the functions. It gives you more freedom in expressing what you exactly want.

Thanks Alberth! I was so sure there would be a way to just return pygame.QUIT. I don't think I did a great job explaining myself in this thread so thank you for explaining this to me.

I was so sure there would be a way to just return pygame.QUIT
Oh you can definitely return pyame.QUIT, but it's not doing anything by itself; computers are terribly stupid, you have to literally spell everything out for them :)

You're welcome. For the nex time, ask about some debugging techniques, so you can point out the problem more precisely.

A third option is to switch from pygame to PySDL2. Unfortunately the API is quite different, but it's mostly function name changes, the fundamental principles are the same. Pygame/SDL 1.2 are quite old, which does have some advantages I suppose, but working with SDL 1.2 would give me the feeling that I'm working with something that's been replaced, and missing out on useful features, even if the old version is still being supported and maintained.

This topic is closed to new replies.

Advertisement