Automatically Resizing Pygame Images

Question:
I’m creating a game with Pygame, and I’m working on resizizing the screen. However, my program has a ton of individual blits at this point (for various grouped lists/dicts), so I want to know if there’s some way to detect the aspect ratio difference and automatically adjust every image appropiately.

code snippet

Also, this was my first time posting a question, so sorry about the empty code snippet…

Hello,
you can edit your original post, and providing a link to your repl can be helpful.

In your question, by “resizing” pygame images do you mean changing their position?
I am assuming you are mainly talking about UI controls.
To do this, you must anchor each control based on the dimensions of the screen. An easy way is to use get_rect() and pygame.Rect properties.
However, you might also want to change the size of the controls. Here, all controls should be a fraction of the screen’s size.
(To detect the resizing of the window, use the pygame.WINDOWSIZECHANGED event)

All of this is quite a hassle, and I’d recommend a few alternatives:

  1. Don’t allow resizing of the window. It can be a lot of work to implement and maintain, and pygame is not super convenient for UI. For high resolution monitors, pygame offers pygame.SCALED flag to automatically scale up the window.
  2. Only allow fixed aspect ratios or fixed dimensions. With a fixed aspect ratio, a simple scaling of the screen and of pygame event positions will work. pygame.SCALED also does this I think.

These ways, you scale all of the images at once so it is much easier.

1 Like

I can’t seem to find the edit button, and I’ll try to be more specific.
Replit: https://replit.com/@JonathanNitzan/Storyshift#Storyshift/main.py

I’m not sure if I need to do anything to allow people to view it from the link, so let me know. When I talk about resizable, I’m just giving an example. I have a original screen resolution of 320 x 240, which the images/positions are tailored to. I want the pygame window to scale to any resolution I want, and for all images displayed on that window (i.e. the entire game basically) to maintain the same aspect ratio to the screen size.

1 Like

(The link works fine)
Allowing any resolution for your window is usually too much work to implement, but you would specify your image sizes and positions anchored to corners, to other images, etc. Take a look at HTML positions, try zooming in and out, resizing window, at any website to see what it might look like. That is what allowing any resolution should look like.
However, you’d have to do this for every image (time consuming). Even just trying to implement the system is a challenge in pygame.

There are easier ways.
Only allowing scaled resolutions but with a fixed aspect ratio is much easier, you could just scale the entire UI surface with a single transform. (You’d need to scale events too.) You could allow multiple, discrete aspect ratios possibly.
The pygame.SCALED flag is experimental but I think it is also good for scaling up the window. I’d recommend this, along with a non-resizable window.

I’ve been experimenting with the SCALED flag (using the FULLSCREEN and RESIZABLE flags to change the size of the window as a reference), and the resolution won’t scale smoothly. From what I understand, the SCALED flag acts like a pygame.transform.scale, and not pygame,transform.smoothscale. Are there any workarounds?

A post was split to a new topic: Help against abuse

I have not used the SCALED flag before. If it does use pygame.transform.scale, then I don’t think there is a way to change it to pygame.transform.smoothscale. Though that would probably be a useful addition to the experimental API.

Here, you will just have to scale it manually. Choose your preferred scaling transform. Check that your scaling function is fast enough to use in replit.
The window must not be resizable manually. Then, allow the user some options for resolutions (or scale factors). Of course, some scale factors look better than others. Use your scaling function on the entire screen before displaying it. (Smoothscale might not be accelerated on some processors, but replit processors seem to have SSE for it.)
In addition to this, event positions for some events must be scaled too. (If you need help on this, I have an implementation of something very similar.)
This probably gives you much more control than the flag. You may want to get the current monitor size to create a window that best fits the space. (Note than in the replit editor, the “monitor size” can change and is the size of the output pane.)

Yeah, that sadly makes alot of sense. The reason I was kind of hoping for the flag is it doesn’t change the actual pygame window size technically speaking. In a game like mine where there’s no mouse control, it becomes perfect. It autoscales events and such for me, and just does pixel calculations based on resolution difference from the original window.

I have no idea if I could edit the original flag or something (I believe it’s written in cpython?) Additionally, it seems plausible to replace the resizable flag to go to the nearest scale factor (in whole numbers, which solves the .SCALED quality loss)

  • For starters, I have technological restrictions which disallow non-approved websites. So I can’t really Google some of this.

A. Can you explain the loss of information from image scaling. I don’t understand why it can’t change the size of the pixels and change the positioning, forming a smaller image

B. How do apps/sites like Adobe succeed in smooth scaling, and can it be replicated in Pygame (bypassing this whole issue)

C. How do I read/edit the Pygame surface files (Which file in the editor is it?)

D. Is it plausible to change the normal pygame.transform.scale fuction or the pygame.SCALED flag to utilize the answer to question B?

By the way, thank you for keeping consistent in your replies! This is getting more and more complex, so just thanks!

(it is unfortunate that there are technological restrictions because much of programming is searching for information on one’s own)

A. Sorry, it’s actually not really lossy vs lossless, but rather how good the image looks when resized. Obviously, scaling up an image by 2x or 1.5x might look better than 1.7x or 2.39x.
But, for the image to look good, you should start with a high resolution and scale down, because of course low res images scaled up look bad. This means your original, programmatic size should be 1280x960 instead of 320x240 (still aspect ratio 4:3). (Consider other aspect ratios such as 16:9, 1280x720.)
pygame.transform.scale is, according to the docs, a very fast transform. Smoothscale sacrifices speed for quality.

B. These sites probably use high resolution images with a smoothscale algorithm. The pygame equivalent is pygame.transform.smoothscale, probably.

C. Eh, not really sure what you mean. Pygame surfaces only exist at runtime, but they can be edited during runtime. Pygame surfaces are often just loaded from file images (that are in the editor).

D. I do not know of a way to change pygame.SCALED flag to be “smooth”, but I might check the source code later. The “smooth” scale function in pygame is pygame.transform.smoothscale, so this is probably what you might have to use to be like apps/sites.

For C, I’m talking about the core module for Pygame. (I.E. the class).
I’m looking into vector images as an alternative. But I keep getting the PEP 517 wheel error for installing PyCairo

Oh, well that’s probably not possible because basically all of the source code is not python, most of it delegates to SDL (Simple Direct Media Layer, I think). However, you can subclass the pygame.Surface class and only use that.
Vector images might not be very compatible with pygame, usually it’s just converted to normal pixel images first. If you are using PyCairo, you have to use two different libraries at once and it is probably not very compatible. Probably, just use a higher or medium “starting” resolution and then scale from there.
(If you do need to install PyCairo, search the ask forums, or ask me for more help.)

1 Like

I have one last question on this topic. What event can I call to resize a pygame window. I can find the event which detects when a pygame window is resized, but if I wanted to resized it to (x, y), how can I do it?

You just call pygame.display.set_mode() again with the new size. I think the display might be cleared to black by this.
Tips:
Your original display surface reference still points to the current display, so there is no need to update a display variable I think.
Giving a size of (0,0) will cause the size to default to the current screen dimensions, which is similar to fullscreen without fullscreening.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.