i want to use python to create an animation of an enlarged raidus of a circle.
i use two ways to accomplish this, one way is success, the another is failed.
i want to know why, is there anyone can help.
version 1:
import pygame
global DISPLAYSURF, FPSCLOCK
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWNWIDTH, WINDOWNHEIGHT))
radius = 1
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
radius = radius + 1
pygame.draw.circle(DISPLAYSURF, RED, (100, 100), radius)
pygame.display.update()
FPSCLOCK.tick(1)
version2:
import pygame
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWNWIDTH, WINDOWNHEIGHT))
for radius in range(0, 100, 2):
pygame.draw.circle(DISPLAYSURF, RED, (100, 100), radius)
pygame.display.update()
FPSCLOCK.tick(1)
while True:
just_wait = True
the version is what i want , the version2 can not work
i run the code on macOs 10.13.1 High Sierra with python3 , why!!!
I think you put code with wrong indentions and it should be
for radius in range(0, 100, 2):
pygame.draw.circle(DISPLAYSURF, RED, (100, 100), radius)
pygame.display.update()
FPSCLOCK.tick(1)
while True:
just_wait = True
And it means you run while True loop inside for loop.
But while True loop is endless loop - you never leave it.
So it never go back to draw new circle and update screen.
You can put print() in code and you will see it.
First version is preferred version because it not only draw animation but it checks events so you can leave program in any time.
On some systems if you will not use pygame.event.get(): to get events from system then system will think that program hung up and system can kill program.
Related
I am using the cv2.imread() function to make a a level editor in pygame that works with images, the only problem is that cv2.imread() gives me information on pixels thus I can only display one rect per pixel.This makes the code really slow and makes it impossible to work with it. I have tried storing all the values in a list but the problem is in the pygame rect function because it foes not have the ability to display all the pixels with collisions and all.
code:
import sys
import pygame
from pygame import *
import cv2
pygame.init()
screen = pygame.display.set_mode((388, 404))
lib = ['Map1.png']
Read = list(cv2.imread(lib[0]))
clock = pygame.time.Clock()
while True:
screen.fill((15, 15, 15))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
for i in range(len(Read)):#y coords
for j in range(len(Read[i])):#x coords
blue = list(Read[i][j])[0]
green = list(Read[i][j])[0]
red = list(Read[i][j])[0]
if blue > 240 and green > 240 and red > 240:
pygame.draw.rect(screen, (255,255,255), pygame.Rect(j, i, 32,32))
else:
pygame.draw.rect(screen, (0), pygame.Rect(j, i, 32, 32))
pygame.display.update()
clock.tick(120)
map1:
I recommend to use pygame.image.load and a pygame.mask.Mask:
Create a mask form the surface (pygame.mask.from_surface)
Invert the mask (invert())
Create a black and whit Surfcae from the mask (to_surface())
Scale up the black and white Surface (pygame.transform.scale)
import sys
import pygame
from pygame import *
pygame.init()
screen = pygame.display.set_mode((388, 404))
read_surf = pygame.image.load("Map1.png")
w, h = read_surf.get_size()
mask = pygame.mask.from_surface(read_surf)
# mask.invert() # optional
mask_surf = pygame.transform.scale(mask.to_surface(), (w*32, h*32))
clock = pygame.time.Clock()
while True:
screen.fill((15, 15, 15))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(mask_surf, (0, 0))
pygame.display.update()
clock.tick(120)
This question already has answers here:
Why is nothing drawn in PyGame at all?
(2 answers)
Closed 1 year ago.
I'm fairly new to pymunk and I wanted to make physics engine for my future games, there's just a small problem, My code won't draw the circle that pygame is trying to visualize. Here's my code.
import pygame
import pymunk
import sys
def create_item(space):
body = pymunk.Body(1, 100, body_type = pymunk.Body.DYNAMIC)
body.position = (450, 50)
shape = pymunk.Circle(body, 80)
space.add(body, shape)
return shape
def draw_items(items):
for item in items:
pygame.draw.circle(screen, item_color, item.body.position, 80)
def quit():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
def display_update():
screen.fill(bg_color)
clock.tick(FPS)
space.step(1/60)
pygame.display.flip()
# Constructor
pygame.init()
# Constants and Variables
WIDTH = 900
HEIGHT = 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
FPS = 60
clock = pygame.time.Clock()
# Colors
bg_color = 30, 30, 40
item_color = 200, 200, 200
# Pymunk Variables
space = pymunk.Space()
space.gravity = (0, 500)
items = []
items.append(create_item(space))
# Loops
def main():
running = True
while running:
quit()
display_update()
draw_items(items)
main()
I don't really know what the problem is here, it doesn't give me an error or something like that and I only get a clean blank canvas with my bg color.(also sorry for the bad comments)
You have to draw the objects before updating the display
def main():
running = True
while running:
quit()
screen.fill(bg_color)
draw_items(items)
pygame.display.flip()
clock.tick(FPS)
space.step(1/60)
You are actually drawing on a Surface object. If you draw on the Surface associated to the PyGame display, this is not immediately visible in the display. The changes become visibel, when the display is updated with either pygame.display.update() or pygame.display.flip().
The typical PyGame application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage
I am currently following a beginner pygame tutorial on YouTube here but even though I copied the code exactly from the tutorial my pygame window only stays open for about a second and then closes.
note: someone asked this question about three years ago here but it didn't fix my problem.
my code is below
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption('hello world')
Your script is ending and so pygame closes everything.
You have to create a loop in order for your game to continue running, with a condition to exit the loop.
You also need to initialize the display with pygame.display.init()
import pygame
pygame.init()
pygame.display.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption('hello world')
clock = pygame.time.Clock()
FPS = 60 # Frames per second.
# Some shortcuts for colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
# For example, display a white rect
rect = pygame.Rect((0, 0), (32, 32))
image = pygame.Surface((32, 32))
image.fill(WHITE)
# Game loop
while True:
# Ensure game runs at a constant speed
clock.tick(FPS)
# 1. Handle events
for event in pygame.event.get():
# User pressed the close button ?
if event.type == pygame.QUIT:
quit()
# Close the program. Other methods like 'raise SystemExit' or 'sys.exit()'.
# Calling 'pygame.quit()' won't close the program! It will just uninitialize the modules.
# 2. Put updates to the game logic here
# 3. Render
win.fill(BLACK) # first clear the screen
win.blit(image, rect) # draw whatever you need
pygame.display.flip() # copy to the screen
I'm making a game analyser, and I thought it would be nice if I had a user iterface instead of just using text and raw input to communicate. I am having problems with 'blitting' an image to my screen.
My image is inside the pycharm file called 'CATANYLISER' as is my code.
import pygame
pygame.init()
# py-game variables
(width, height) = (1000, 600)
window = pygame.display.set_mode((width, height))
window_title = pygame.display.set_caption('the CATANALYSER')
does_quit = False
# py-game images
empty_board = pygame.image.load('empty_board.png')
# py-game window loop
while not does_quit:
# receives input from window
for event in pygame.event.get():
# stops program when red x clicked
if event.type == pygame.QUIT:
does_quit = True
window.blit(empty_board, (0, 0))
pygame.display.update()
# activates when the loop finishes, just makes sure everything shuts down properly
pygame.quit()
The expected result is the image on the screen in the top left corner. However when I run the program, I have an empty screen (pygame.QUIT still works).
When I run this code there is no error message, and I am completely lost about how to fix this.
first, make sure that the empty_board.png is in your working directory.
Second, you have to clear the screen before each frame using window.fill([255, 255, 255])
Finally, you could try using pygame.display.flip() instead of update()
My code would look like:
import pygame
pygame.init()
window = pygame.display.set_mode([640, 480])
doQuit = False
board = pygame.image.load("empty_board.png")
while not doQuit:
window.fill([255, 255, 255])
window.blit(board, (0, 0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
doQuit = True
pygame.quit()
I'm trying to create "end credits" like the ones at the end of a movie, using pygame. I've googled for other ways to achieve this using python, but I haven't found any yet.
I've almost achieved this with the following code: http://pastebin.com/nyjxeDYQ
#!/usr/bin/python
import time
import threading
import pygame
from pygame.locals import *
# Initialise pygame + other settings
pygame.init()
pygame.fastevent.init()
event_get = pygame.fastevent.get
pygame.display.set_caption('End credits')
screen = pygame.display.set_mode((1920, 1080))
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((255, 255, 255))
fontsize = 40
font = pygame.font.SysFont("Arial", fontsize)
x = 0
def main():
global x
credit_list = ["CREDITS - The Departed"," ","Leonardo DiCaprio - Billy","Matt Damon - Colin Sullivan", "Jack Nicholson - Frank Costello", "Mark Wahlberg - Dignam", "Martin Sheen - Queenan"]
going = True
while going:
events = event_get()
for e in events:
if e.type in [QUIT]:
going = False
if e.type in [KEYDOWN] and e.key == pygame.K_ESCAPE:
going = False
# Loop that creates the end credits
ypos = screen.get_height()
while ypos > (0 - len(credit_list)*50) and x == 0: # Loop through pixel by pixel, screenheight + height of all the textlines combined
drawText(credit_list,ypos)
ypos = ypos - 1
x = 1
pygame.quit()
def drawText(text,y):
for line in text:
text = font.render(line, 1, (10, 10, 10))
textpos = text.get_rect()
textpos.centerx = background.get_rect().centerx
background.blit(text, (textpos.x,y))
y = y + 45
# Blit all the text
screen.blit(background, (0, 0))
pygame.display.flip()
time.sleep(0.0001) # Sleep function to adjust speed of the end credits
# Blit white background (else all the text will stay visible)
background.fill((255, 255, 255))
screen.blit(background, (0, 0))
pygame.display.flip()
if __name__ == '__main__': main()
The problem is that the scrolling text is flickering. This is because I use a time.sleep()-function to control the speed of the scrolling. When I use a value like 0.04 sec, it works pretty well, but the text moves too slow and there is still a bit of flickering. When I use a much lower value, like: 0.001 sec, the text is moving at a speed that I like, but there is a lot more flickering going on.
There is another value I can use to adjust the speed of the scrolling: the number of pixels to move. But when I set this to anything higher than 1, the scrolling isn't smooth anymore.
Does anyone know a solution to this problem? I don't necessarily have to use pygame, I do have to use python though.
Many thanks in advance!
Albrecht
Here are some simpe rule you should follow that will help you with your problem:
Don't call pygame.display.flip() more than once per frame
Don't use time.sleep() to control the speed of something in your application
Use a Clock to control the framerate
Here's a cleaned up, minimal working example:
#!/usr/bin/python
import pygame
from pygame.locals import *
pygame.init()
pygame.display.set_caption('End credits')
screen = pygame.display.set_mode((800, 600))
screen_r = screen.get_rect()
font = pygame.font.SysFont("Arial", 40)
clock = pygame.time.Clock()
def main():
credit_list = ["CREDITS - The Departed"," ","Leonardo DiCaprio - Billy","Matt Damon - Colin Sullivan", "Jack Nicholson - Frank Costello", "Mark Wahlberg - Dignam", "Martin Sheen - Queenan"]
texts = []
# we render the text once, since it's easier to work with surfaces
# also, font rendering is a performance killer
for i, line in enumerate(credit_list):
s = font.render(line, 1, (10, 10, 10))
# we also create a Rect for each Surface.
# whenever you use rects with surfaces, it may be a good idea to use sprites instead
# we give each rect the correct starting position
r = s.get_rect(centerx=screen_r.centerx, y=screen_r.bottom + i * 45)
texts.append((r, s))
while True:
for e in pygame.event.get():
if e.type == QUIT or e.type == KEYDOWN and e.key == pygame.K_ESCAPE:
return
screen.fill((255, 255, 255))
for r, s in texts:
# now we just move each rect by one pixel each frame
r.move_ip(0, -1)
# and drawing is as simple as this
screen.blit(s, r)
# if all rects have left the screen, we exit
if not screen_r.collidelistall([r for (r, _) in texts]):
return
# only call this once so the screen does not flicker
pygame.display.flip()
# cap framerate at 60 FPS
clock.tick(60)
if __name__ == '__main__':
main()