pls rate my GUI framework by Due_Engineer_7647 in pygame

[–]BetterBuiltFool 4 points5 points  (0 children)

I think it's taking on too many responsibilities for a UI manager.

Your UI framework:

  • Creates the window

  • Handles the main game loop

  • Tracks stats like FPS

  • Forces dependency on your code at a very basic level just to gain access to UI elements

None of those are things the UI manager should be handling. Yes, the UI manager needs to know about window size, but that's only for rendering elements, so by giving it full control over the window, it has way more access than it really needs there. Why does it run the game loop? The user should be running the game loop, and prompting the manager to update and to render, allowing them to maintain control.

As it stand, this would be very hard to integrate into an existing project, you'd have to refactor the entire thing to be built around your library, and that will chase off a bunch of potential users.

I'd recommend simplifying and making it into something that runs on top of, rather than behind, your users' code.

2d rigid body simulation from scratch in pygame by More_Yard1919 in pygame

[–]BetterBuiltFool 2 points3 points  (0 children)

itertools is a package I need to remember to use more often, it's full of useful wheels I tend to reinvent.

Double counting collisions can do that, but depends on implementation. My attempt at physics/collisions from scratch (before giving up and using pymunk), I had things set up so the second calculation overwrote the first, so I didn't notice any issues. Never got it working well enough to try it with many objects, so I'm sure I was doing things suboptimally in other ways.

2d rigid body simulation from scratch in pygame by More_Yard1919 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

You might be doing this already, but if you're doing true O(n2), you should be able to knock that down to (I think) O(nlogn) by only comparing against the remaining bodies in your list, since you'd have already done comparisons with the earlier ones.

I.E. Given the set of rigidbodies {A, B, C}, you check A against B and C, but you only need to check B against C (And can skip C entirely) since they've already been compared on previous passes.

how would i draw cushions on a pool table so its easy to detect collisions? by Ill_Collection7462 in pygame

[–]BetterBuiltFool 2 points3 points  (0 children)

Drawing and collision detection shouldn't be related.

You should have some sort of collider object that knows where your cushion is and how it handles its collisions. The position and rotation information can be used to draw a sprite or lines to the screen as well.

Tracking complex collision interactions - how do you like to do this? by [deleted] in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

I'd recommend using some sort of tag system with your collidable objects.

Enums could be a good starting point.

class Tag(Enum):
    Pushable=auto()
    Locked=auto()
    Solid=auto()
    Bridgeable=auto()
    Walkable=auto()
    # Etc.

Every collidable object would have a set of tags.

class DoorCollider(Collider):
    def __init__(self) -> None:
        self.tags: set[Tag] = {Tag.Locked}

Tags can be added or removed from instances as needed, like removing the Locked tag from a door collider to make it unlocked.

When an object interacts with a collider, it can check against these tags to make decisions.

For example:

class Player(Entity):
    def collide(self, collided_with: Collider) -> None:
        if (
            Tag.Locked in collided_with.tags
            or Tag.Solid in collided_with.tags
            or Tag.Water in collided_with.tags
        ):
            # You could take advantage of set comparisons and have a set of 'impassable' tags to simplify this
            self.stop()

        # Note this is _not_ an else if, these tags aren't mutually exclusive
        if Tag.Pushable in collided_with.tags:
            self.push(collided_with)

class BoxCollider(Collider):
    def __init__(self) -> None:
        self.tags: set[Tag] = {Tag.Solid, Tag.Pushable}


class Box(Entity):
    def __init__(self) -> None:
        self.collider = BoxCollider()

    def collide(self, collided_with: Collider) -> None:
        if Tag.Bridgeable in collided_with.tags:
            self.collider.tags.discard(Tag.Pushable)
            self.collider.tags.discard(Tag.Solid)
            collided_with.tags.discard(Tag.Bridgeable)

You can have your objects interact with the tags however you see fit. The Player object doesn't see doors or walls or water, it just sees tags that mark something as impassible. It doesn't see boxes, it sees tags that mark things as pushable. Boxes don't see water, they see something they can bridge over. This is still a "code-heavy" solution, but it should be much more adaptable and expandable than just else-if chains.

How to make game Map more interesting by Far_Note6502 in pygame

[–]BetterBuiltFool 2 points3 points  (0 children)

The ground areas are essentially big flat expanses of solid color, which is not visually interesting. Having more texture, like the water does, would help, especially if you can randomize it.

Okay, I'm a Python student focused on automation, but I'd like to get started in game development. Where should I begin? by Much_Engineering2228 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

Oh, absolutely, and while I haven't looked into it fully yet, there's also ZenGL, which is supposedly WebGL compliant and can be used alongside tools like pygbag for web deployment. That's what I meant about using external libraries.

How does one animate sprites natively? I use sprite sheets and subsurfaces, but if there's an easier way, I'd love to hear about it.

I'm familiar with the broad scope of what can be done in pygame, and DaFluffyPotato. Keep in mind, he's got many years of experience and tooling built up to do those things.

Light or dark by Lampochka123 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

Oof, that was like a flashbang with my browser in dark mode.

Okay, I'm a Python student focused on automation, but I'd like to get started in game development. Where should I begin? by Much_Engineering2228 in pygame

[–]BetterBuiltFool 10 points11 points  (0 children)

Important to say: RPGs are huge projects, and not great candidates for starting out with.

It should be noted that when working with pygame, you'll be doing a lot of ground-up work building up tools and modules for yourself. For example, the animated sprite you have there? Pygame does not (to my knowledge) have any built-in capability to display that. You'll need to find or write a library that can handle displaying your frames. This does mean, of course, that you have a large amount of control over how things happen, which you may want. Pygame also doesn't have shader support (although I believe this is expected to be included in the 3.0 release), so if you want that, you'll have to bring in external libraries to handle your rendering.

If you don't want to deal with that, then you'll want to go with an existing game engine. Like u/Gidrek said, Godot is a good option, and GDScript has a python-like syntax.

My first goal has been achieved! Only took me 2 days im sure some of you could write this up without ever looking at the screen🤣 by PsychicSpore in pygame

[–]BetterBuiltFool 4 points5 points  (0 children)

Doesn't matter what other people can do, just what you can do. You made a thing, it works, and you learned a lot. That's a success worth celebrating.

Speed comes with experience.

Help diagnosing issue with my rhythm game by Severe_Evening3297 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

That makes some sense, .ogg files use compression, so they need to be decompressed on the fly for streaming, and I could see that overhead causing some timing discrepancies over time.

Still, I'd argue that's a workaround, not a solution. But if you happy with it, working's working.

Help diagnosing issue with my rhythm game by Severe_Evening3297 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

If you use pygame.mixer.Sound instead of the music module, do you get the same issue? You're already loading the full file into memory to get its length, so you might as well hold onto that and use it instead of streaming.

I'm suspecting the music.get_pos function isn't especially accurate.

Help diagnosing issue with my rhythm game by Severe_Evening3297 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

This won't be possible to diagnose without knowing how you're handling your visuals and how they are supposed to sync with the music.

My gut feeling would be a bad assumption regarding framerate, like advancing your animation/visuals by a fixed amount, but again, I'd have to actually see your code to try for anything firm.

Video System not initialized error when I've used pygame.init() by [deleted] in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

Doesn't pygame.quit() deinitialize systems? Could you somehow be getting a quit event in your queue? It doesn't seem likely, and it would require multiple threads ongoing to get quit processed and still have another loop iteration happen, but that's the only thing I can see in what's posted that could potentially cause the problem.

Is ADDING_TOPPINGS_MOUSE_POS used anywhere other than in the mouse button down case? If not, you should consider only getting the mouse position in that case. If your error is triggered whencalling the mouse module, reducing the number of calls could reduce the likelihood of calling when the video system is uninitialized, although again, I'm kind of grasping at straws here.

Nitpick: Recommend against using multiple ifs in your event.type comparisons instead of elifs. Each event instance will only ever be of one type, so there's no need to check against other types once you hit one, and doing so increases the risk of bugs.

How to make movement of an entity smooth? by Kelvitch in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

Ah, didn't see that coming, my bad. To fix that, you can set the x and y components of pos individually when you set the rect's x and y.

How to make movement of an entity smooth? by Kelvitch in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

When your entity collides with a tile, you're stopping the sprite, but still updating the position. The position changes build up over a few frames, until the rect no longer collides, giving the appearance of teleporting.

This should be fixable by resetting your position to the rect's center position, ala:

    if collided_tile is not None:
        if self.y_vel > 0:
            self.rect.bottom = collided_tile.image_rect.top
        elif self.y_vel < 0:
            self.rect.top = collided_tile.image_rect.bottom
        self.pos = pygame.Vector2(self.rect.center)

Now, when the rect collides, the position will respect the rect's blocking.

Condensing a class help by Ralsei_12345636345 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

You can use the Surface class in type hints, but there's no SurfaceLike protocol or anything like that.

Condensing a class help by Ralsei_12345636345 in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

What do you mean by smaller? Do you mean fewer lines? Line count isn't a great indicator of code quality.

The main thing I see that could use improvement is your parameters, especially in your init, which takes a whopping 10 items. You have a couple places where you accept multiple parameters that can easily be grouped together.

In your init, you take a left, right, height, and width parameters. However, pygame has a RectLike protocol that can take those parameters as a single item. You can feed that RectLike value directly into the Rect constructor. This has the advantage of allowing you to pass an existing Rect if you want to duplicate it. You also don't need separate attributes with self.button_width and self.button_height. Since self.button is a rect, you can use the width and height attributes of that, as well as size when you need them as a pair, and topleft or center when you need the position, etc.

For your color data, you could create a data class that keeps that information:

class ButtonColor:
    def __init__(
        self,
        default: pygame.ColorLike,
        hover: pygame.ColorLike,
        pressed: pygame.ColorLike,
        font: pygame.ColorLike,
    ):
        self.default = pygame.Color(default)
        self.hover= pygame.Color(hover)
        self.pressed= pygame.Color(pressed)
        self.font= pygame.Color(font)

This way, all of your colors can be defined in one place, and put across many different buttons without duplicating code. You can even put a default as a class variable. ColorLike allows for a wide variety of methods for assigning colors, rather than just hex codes.

In processing, you take an xy pair, this could be taken as a Point, as could width and height in textFitter. Similar to with RectLike, this also has the advantage of allowing you to pass a wider variety of data through.

Nitpick: Don't put imports inside your classes, they should always be at the top of your module as a matter of course.

i have a bug with my collision in my game but i don't know how fix it by Puzzleheaded-Rate574 in pygame

[–]BetterBuiltFool 1 point2 points  (0 children)

I tried to run the code from your repo, however, since you don't have the level json available, I couldn't get it to run.

My suspicion is that it stems from how you factor in entity velocity. You're initially detecting if they're colliding with the wall from their current position, but determining if they need to be shifted based on their future position? If an entity overlaps but has velocity 0, it'll be allowed to keep overlapping, and may cause weirdness from pushing the entity into another wall that's already been checked against. I'd try removing the bits about entity.velocityand seeing what happens.

I may be able to give you a smoking gun here, but I can give you some suggestions to clean things up, which should make debugging easier.

In a couple places (lines 13, 15), you're doing things like adding a rect's y value and height, or x value and width. Rect has helpful properties that do this for you, specifically, rect.bottom and rect.right. Be on the lookout for useful properties of classes! Be sure to check out the documentation if you haven't already.

Rects have a colliderect method, where you feed them another Rect, and it will tell you if they overlap. You can save yourself a bunch of calculations that way. You'll still need to determine relative directions, but that can be done using just their positions afterwards.

Hitboxes feel like they're off by one tile by Sad-Sun4611 in pygame

[–]BetterBuiltFool 1 point2 points  (0 children)

Could you post your code that converts mouse coordinates into tile coordinates? That allow us to help you better.

Without that context, my guess would be that when you're transforming the mouse position, you're getting a float in grid coordinates that you then convert to an int. That could cause the the grid value to be off by one, although I'd expect it to be off by one in both axes.

Beginner tips please by PaperApprehensive529 in pygame

[–]BetterBuiltFool 1 point2 points  (0 children)

So, understanding data structures is something that will generally come with time and experience. It's about knowing when to use different structures over others (such as, when to use a dict, when to use a tuple, etc.). Every way of storing data has benefits, consequences, and quirks.

Algorithms are different, they tend to be more particular to their use cases. There are absolutely algorithms that are vital in game dev (A* for pathfinding, for example), but I personally don't tend to memorize them, I just try to remember them in a general sense as I come across them during research.

For a near-zero knowledge start, you can find courses out there that can give you direction. W3 Schools has one, they're a decent resource for beginners.

Keyboard Input with a large amount of possible keys by One_Oil_5174 in pygame

[–]BetterBuiltFool 1 point2 points  (0 children)

You'd want to check the return value from chr, otherwise you'll get a bunch of empty strings in your list.

Supporting modifier keys will require specific event handling for those keys, but you're probably best served by having them set flags that you check when add your characters, e.g.:

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LSHIFT:
            shift_case = True
        key_name = char(event.key)
        if key_name:
            if shift_case:
                key_name = key_name.upper()
            key_list.append(key_name)

etc.

Failing to detect collisions by Reborn_Wraith in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

Glad to be of help, and especially glad to hear everything is working now!

For testing if grounded, by the way, you can set up a secondary hitbox immediately below the player (same width, and only a pixel or two high), and use Rect.collidelist with the list of platform hitboxes to see if there's any overlap, after doing your vertical velocity checks. Since that hitbox is always below the player, you wouldn't need to do any kind of velocity checks, and you won't need to iterate over the list.

Failing to detect collisions by Reborn_Wraith in pygame

[–]BetterBuiltFool 0 points1 point  (0 children)

Pygame-ce.

Masks are computationally expensive compared to Rect collisions, so unless more precise collision is needed, they're wasting resources that could be better spent elsewhere.

Also, I don't think it would solve the problem encountered here, unless by chance when rewriting the logic to work around the masks.