I want to be able to stretch a screen without needing to stretch each image individually.
I have a image I use as the screen, then when I have the final product I transform the image to the size of the screen and blit it to the screen.
But the images blit onto the main image do not transform with the main image, and comes out as its first size.
You can find the current version here:
https://gist.github.com/gideonjvisser/eca7506f483c51edf93c/
Here's the script:
import pygame
from pygame.locals import Color
chosen_resolution = (400,200)
screen = pygame.display.set_mode(chosen_resolution)
screen_rect = screen.get_rect()
in_game_resolution = (800,600)
screen_image = pygame.Surface(in_game_resolution)
screen_image_rect = screen_image.get_rect()
image_on_in_game = pygame.image.load("image.png").convert_alpha()
image_on_in_game = pygame.transform.scale(image_on_in_game, (469,669)) #to fit on in_game_resolution
print screen_rect
print screen_image_rect
while(True):
screen_image.fill(Color('white'))
screen_image.blit(image_on_in_game, (0,0))
screen_image = pygame.transform.scale(screen_image, chosen_resolution)
screen.blit(screen_image, (0,0))
pygame.display.flip()
This code almost works. The issue is that, in your while loop, you overwrite your static resolution intermediate surface with the scaled version. Try replacing the while loop with this:
while True:
screen_image.fill(Color('white'))
screen_image.blit(image_on_in_game, (0,0))
screen.blit(pygame.transform.scale(screen_image, chosen_resolution), (0,0))
pygame.display.flip()
Now the pre-scaled buffer should remain the right size and actually be scaled to fit the real screen's size.
Related
Hello everyone I am learning the basics of pygame.
I recently ran into a problem;
I decided to load an image and gave it a random location well within the pygame window.But the problem was that sometimes it just wont appear in the window. So I drew a black pointer at the place where the image was to be loaded. Then I found out that the black pointer doesnot coincide with the image and hence the image is not appearing in the location I want it to be in.
So I want help solving this problem.
Thank you in advance.
Code:
import pygame
import random
pygame.init()
#Pygame starters
display_width = 800
display_height = 600
game_display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Blob runner")
clock = pygame.time.Clock()
targetpng = pygame.image.load("target.png")
#Quit checker
crashed = False
#COLOURS
white = (255, 255, 255)
black = (0, 0, 0)
def draw_environment(x,y):
game_display.fill(white)
#Image
game_display.blit(targetpng,(x, y))
#Black pointer
pygame.draw.circle(game_display, black, (x, y), 5 )
pygame.display.update()
x, y = random.randrange(0,display_width), random.randrange(0,display_height)
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
# print(event)
draw_environment(x,y)
clock.tick(30)
pygame.quit()
quit()
Image:
The image has a size. it may happen that the image is out of the window at the right or at the bottom. The origin of the blit puts the the top left corner of the image to the specified position.
If you wan that the image is centered at (x, y), the you have to get a pygame.Rect with the size of the image (get_rect) and set the center of the rectangle to the specified position (keyword argument). Use the rectangle to specify the position for the blit operation.
img_rect = targetpng.get_rect(center = (x, y))
game_display.blit(targetpng, img_rect)
Th image has a size, thus the random position for the image has to be in range [image_size/2, window_sizw - image_size/2].
The width and height of a pygame.Surface can be get by get_width()/get_height() or get_size(). For instance:
img_size = targetpng.get_size()
x = random.randrange(img_size[0]//2, display_width - img_size[0]//2)
y = random.randrange(img_size[1]//2, display_height - img_size[1]//2)
I now understand what went wrong with the insight provided by #Rabbid76.
The thing is I drew the picture in paint and then opened the file in gimp to convert whites in the image to alpha(the checkerboard-like background) . But the problem occurred when I did not clear of the unwanted alpha as I thought the computer will not recognise the alpha but as matter of fact it does.
So when I loaded the image, the corner of the image is not of the actual "target spot" but of the entire image, so the corner will be on the alpha. The black dot was pointing at the corner of the image all along and the image sometimes did not appear because the corner was too close to the border so the image would trespass to the un-displayed portion of the window.
So the fix is to clear of the alpha or the white background to minimum and only then convert it into alpha. Then do as #Rabbid76 says :D.
I have been trying to make an image rotate in pygame, using python 3.6, however when I do it either distorts the image into an unrecognizable image, or when it rotates it bumps all over the place
Just using pygame.transform.rotate(image, angle) makes the distorted mess.
And using something like:
pygame.draw.rect(gameDisplay, self.color, [self.x, self.y, self.width, self.height]) makes the image bump all over the place.
I have looked at many questions on this site and others and so far none of them have worked perfectly.
To anyone who is interested here is the link to my code so far.
https://pastebin.com/UQJJFNTy
My image is 64x64.
Thanks in advance!
Per the docs (http://www.pygame.org/docs/ref/transform.html):
Some of the transforms are considered destructive. These means every time they are performed they lose pixel data. Common examples of this are resizing and rotating. For this reason, it is better to re-transform the original surface than to keep transforming an image multiple times.
Each time you call transform.rotate you need to do it on the original image, not on the previously rotated one. For example, if I want the image rotated 10 degrees each frame:
image = pygame.image.load("myimage.png").convert()
image_clean = image.copy()
rot = 0
Then in your game loop (or object's update):
rot += 10
image = pygame.transform.rotate(image_clean, rot)
Here's a complete example. Don't modify the original image and in the while loop use pygame.transform.rotate or rotozoom to get a new rotated surface and assign it to another name. Use a rect to keep the center.
import sys
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
BG_COLOR = pg.Color('darkslategray')
# Here I just create an image with per-pixel alpha and draw
# some shapes on it so that we can better see the rotation effects.
ORIG_IMAGE = pg.Surface((240, 180), pg.SRCALPHA)
pg.draw.rect(ORIG_IMAGE, pg.Color('aquamarine3'), (80, 0, 80, 180))
pg.draw.rect(ORIG_IMAGE, pg.Color('gray16'), (60, 0, 120, 40))
pg.draw.circle(ORIG_IMAGE, pg.Color('gray16'), (120, 180), 50)
def main():
clock = pg.time.Clock()
# The rect where we'll blit the image.
rect = ORIG_IMAGE.get_rect(center=(300, 220))
angle = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
# Increment the angle, then rotate the image.
angle += 2
# image = pg.transform.rotate(ORIG_IMAGE, angle) # rotate often looks ugly.
image = pg.transform.rotozoom(ORIG_IMAGE, angle, 1) # rotozoom is smoother.
# The center of the new rect is the center of the old rect.
rect = image.get_rect(center=rect.center)
screen.fill(BG_COLOR)
screen.blit(image, rect)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pg.quit()
sys.exit()
I'm writing a class in pygame to create a sprite object, and I'd like to be able to rotate it. It works fine with an image, and rotates without issue. But when rotating a surface with a plain colour, the box appears to grow and shrink. I know that this is a result of the surface changing size to fit the vertices of the rectangle inside, but how do I stop it? I'd like to see a visual rotation.
I've created some sample code to show the problem that I'm facing, running it causes the box to simply change in size.
import sys, pygame
from pygame.locals import *
pygame.init()
SCREEN = pygame.display.set_mode((200, 200))
CLOCK = pygame.time.Clock()
surface = pygame.Surface((50 , 50))
surface.fill((0, 0, 0))
rotated_surface = surface
rect = surface.get_rect()
angle = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
SCREEN.fill((255, 255, 255))
angle += 5
rotated_surface = pygame.transform.rotate(surface, angle)
rect = rotated_surface.get_rect(center = (100, 100))
SCREEN.blit(rotated_surface, (rect.x, rect.y))
pygame.display.update()
CLOCK.tick(30)
How do I fix this issue, to make the surface rotate how I want?
Any help would be appreciated!
You have to create the Surface objects you create to stamp on the display surface in a way they use transparency information (That is - they have to have an alpha channel).
To do that, is just a question of passing the appropriate flag when creating your surface objects - simply replace this:
surface = pygame.Surface((50 , 50))
with:
surface = pygame.Surface((50 , 50), pygame.SRCALPHA)
and it should work.
I'm trying to resize an image in pygame. I want my background image to fill the entire screen. I'd like to setup the entire screen based on the new (stretched) dimensions of the background. The following isn't working and I'm trying to figure out why.
Suggestions?
background = pygame.image.load("data/stars.bmp")
pygame.transform.scale(background, (1200,800)) #or some size x,y here.
bgRect = background.get_rect()
size = width, height = bgRect.width, bgRect.height
screen = pygame.display.set_mode(size)
screen.blit(background, bgRect)
pygame.display.flip()
#pygame.transform.scale(background, (1200,800)) #or some size x,y here.
background = pygame.transform.scale(background, (1200,800))
Is there any way to clear a surface from anything that has been blitted to it?
If what you want is to make a pygame Surface object "clean", that is erase all images blited to it, to blit new images to it every game loop and keep the peer pixel alpha without creating a new surface, you can fill it, but instead of a solid color, use a transparent color
from pygame import Color, Surface
empty = Color(0,0,0,0) #The last 0 indicates 0 alpha, a transparent color
field = Surface((width, height), flags=SRCALPHA)
#Inside the game loop
field.fill(empty)
*Sorry is my english is bad, still learning
When I dont care about performance, I use:
mysurface.fill((0,0,0))
Which will draw the specified color (black in this case) across the entire surface. Is that what you meant by "clear"?
Oh, and you need, of course, to "flip" the surface after doing this for it to be visible on the screen.
I don't know what API you're using, so here's a vague answer:
In virtually all cases "clearing" a surface simply blits a coloured quad of the same size as the surface onto it. The colour used is whatever you want your clear colour to be.
If you know how do blit, just blit a white quad of the same size onto the surface.
You can't undo one graphic written over the top of another graphic any more than you can undo one chalk illustration drawn over the top of another chalk illustration on the same board.
What is typically done in graphics is what you'd do with the chalkboard - clear the whole lot, and next time only redraw what you want to keep.
I had this problem too
To create the surface:
mask=pygame.Surface((180,100),pygame.SRCALPHA)
To clear the surface:
mask.fill
mask.set_alpha(255)
Draw your lines/images etc
Then blit this surface onto your main surface using the Alpha Blend flag
screen.blit(mask,(0,0),special_flags=(pygame.BLEND_RGBA_ADD))
.fill((255,255,255,0)) appears to work for me anyway.
I used the following in a game I made:
self.image = 0 #to empty it
self.image = pygame.image.load("image")
For pygame you can use Surface.fill
If you want to clear a surface before blitting, you can first fill the surface with a unlikely random color, set the alpha (colorkey) with that color, and then blit the original sprite with the transparent background back onto the surface.
idle_image = pg.image.load("sprite.png") #sprite with transparent background
temp_color = pg.Color(132, 23, 213, 255) #random unlikely replacement color
def clear_surface(surface):
surface.fill(st.temp_color)
surface.set_colorkey(st.temp_color)
surface.blit(idle_image, (0,0))
You can clear a surface by making it transparent.
Below is how I used the empty color RGB to make text blink by setting the surface to switch to a transparent version.
from __future__ import absolute_import, division, print_function
from itertools import cycle
import pygame
VISITOR_TTF_FILENAME = 'pixelFont.ttf'
BLINK_EVENT = pygame.USEREVENT + 0
empty = (255,255,255,0)
def main():
pygame.init()
try:
screen = pygame.display.set_mode((800, 600))
screen.fill((255,255,255))
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
font = pygame.font.Font(VISITOR_TTF_FILENAME, 50)
on_text_surface = font.render(
'Press Any Key To Start', True, pygame.Color('green3')
)
blink_rect = on_text_surface.get_rect()
blink_rect.center = screen_rect.center
off_text_surface = pygame.Surface(blink_rect.size)
off_text_surface.fill(empty)
blink_surfaces = cycle([on_text_surface, off_text_surface])
blink_surface = next(blink_surfaces)
pygame.time.set_timer(BLINK_EVENT, 1000)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == BLINK_EVENT:
blink_surface = next(blink_surfaces)
screen.blit(blink_surface, blink_rect)
pygame.display.update()
clock.tick(60)
finally:
pygame.quit()
if __name__ == '__main__':
main()
When I want to get rid of something I use
screen.fill("Gray")
every time I update! So it hides it behind the gray screen.
Gray is not the only color available, so here is a list of all of the available colors you can use for pygame
Hope it helped!
Fill the surface with fill, then make it transparent with set_alpha
surface.fill
surface.set_alpha(255)