pygame-community / pygame-ce

🐍🎮 pygame - Community Edition is a FOSS Python library for multimedia applications (like games). Built on top of the excellent SDL library.
https://pyga.me
930 stars 154 forks source link

Add "surfaces of uncertain size" (May be called "FreeSurface"?) #2282

Closed Python-ZZY closed 1 year ago

Python-ZZY commented 1 year ago

Sometimes it is very difficult to flexibly expand the surface size. Let's say I want to build a surface, the size of this surface is not fixed, it may grow larger or smaller over the course of the game. It's easy to make a surface smaller, but it's not easy to make it bigger. I want to have a "surface of indeterminate size" that has the flexibility to resize based on what's in it, so that when the blit method is called, the excess content is not discarded, but the surface is enlarged so that the drawn content can fit inside.

AndreyVarvar commented 1 year ago

This sounds unnecessary, considering you can write your own function that does the resizing of the surface in just 2 lines of code. Instead of making a new type, maybe adding a function to the Surface class called resize(size). Maybe it will even accept additional parameters regarding of aligning the image on the initial surface.

Python-ZZY commented 1 year ago

This sounds unnecessary, considering you can write your own function that does the resizing of the surface in just 2 lines of code. Instead of making a new type, maybe adding a function to the Surface class called resize(size). Maybe it will even accept additional parameters regarding of aligning the image on the initial surface.

You are right, but I don't know how to write the resize function either. I don't know anything about how surfaces work

AndreyVarvar commented 1 year ago

Yeah, sure. But in my opinion, making a whole other Surface type, which i'm pretty sure both of us won't be able to implement, is way worse than just enhancing what we already have. Plus, the resizing function is so simple, it could just be:

def resize(surf, size):
        resized_surf = pg.Surface(size)
        resized_surf.blit(surf, (0, 0))
        return resized_surf
Python-ZZY commented 1 year ago

Yeah, sure. But in my opinion, making a whole other Surface type, which i'm pretty sure both of us won't be able to implement, is way worse than just enhancing what we already have. Plus, the resizing function is so simple, it could just be:

def resize(surf, size):
        resized_surf = pg.Surface(size)
        resized_surf.blit(surf, (0, 0))
        return resized_surf

I also found a problem. If you just keep resizing, you must estimate the size in advance, which is sometimes impossible.For example, call the function in pg.draw to enlarge the surface according to the size of the drawing. But pg.draw will discard pixels that are out of range.

bilhox commented 1 year ago

I want to have a "surface of indeterminate size" that has the flexibility to resize based on what's in it, so that when the blit method is called, the excess content is not discarded, but the surface is enlarged so that the drawn content can fit inside.

This looks like how Textures work, you can use them with pygame._sdl2.

zoldalma999 commented 1 year ago

I think I disagree with this idea.

For one I can't think of a lot of situations where this would be needed. Most of the time, you will know how big a sprite will be, or the size of a UI element, or how big to draw something you make dynamically.

This would also be inefficient. We would need to recreate the surfaces internally every time we need to change the size, reallocating the memory, and then blitting it to the new surface. Because of the way the pixel data is laid out, we can't easily just "add a bit to it".

We would also need to somehow know that we need to change it. This is (again) not easy to do, and would involve code in a lot of different places. Overall it would just bring us clutter. And even that would not be a 100% perfect.

There is also a fair amount of ambiguity between different functions. Sure, lets say blitting something and it ends outside, we just resize. What if one wants to do Surface.set_at and it is not inside the surface? Do we resize then? Do we resize if someone makes a surfarray and indexes into an out of bounds pixel?

I don't think I would like to see this being in pygame-ce. I'll probably wait for one or more opinions before closing it, but I am not in support of this.

This looks like how Textures work, you can use them with pygame._sdl2.

Are you sure? Textures require a fixed size when created, which then stays the same until you destroy it and create a new one - just like surfaces.

oddbookworm commented 1 year ago

Yeah, sure. But in my opinion, making a whole other Surface type, which i'm pretty sure both of us won't be able to implement, is way worse than just enhancing what we already have. Plus, the resizing function is so simple, it could just be:

def resize(surf, size):
        resized_surf = pg.Surface(size)
        resized_surf.blit(surf, (0, 0))
        return resized_surf

I also found a problem. If you just keep resizing, you must estimate the size in advance, which is sometimes impossible.For example, call the function in pg.draw to enlarge the surface according to the size of the drawing. But pg.draw will discard pixels that are out of range.

I generally create a surface larger than I expect I need, then use pygame.Surface.get_bounding_rect to get the final size I need (if I really can't figure out the final size first, but it's usually some pretty quick math) https://pyga.me/docs/ref/surface.html#pygame.Surface.get_bounding_rect

Starbuck5 commented 1 year ago

Seconding zoldalma's motion, I'm going to close this issue as not planned. For the reasons brought up before.

Thank you for submitting an enhancement idea! It brought up some good ideas and different methods to do things.