In the following code, there is not just one circle on the screen at any given point in time.
I want to fix this to make it so that it looks like there is only one circle, instead of leaving a smudge trail where ever the mouse cursor has been.
import pygame,sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((640,400),0,32)
radius = 25
circle = pygame.Surface([radius*2]*2,SRCALPHA,32)
circle = circle.convert_alpha()
pygame.draw.circle(circle,(25,46,100),[radius]*2,radius)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.blit(circle,(pygame.mouse.get_pos()[0],100))
pygame.display.update()
pygame.time.delay(10)
You need to specifically erase the circle before you blit it again. Depending on how complicated your scene is, you may have to try different methods. Generally what I do is have a "background" surface that a blit to the screen every frame and then blit the sprites/other surfaces in their new positions (blits in Pygame are very fast, so even in fairly large screens I haven't had speed issues doing this). For your code above, it's simple enough just to use surface.fill(COLOR) where COLOR is your background color; eg, (255,255,255) for white:
# ...
screen = pygame.display.set_mode((640,400),0,32)
backgroundColor = (255,255,255)
# ...
while True:
# ...
screen.fill(backgroundColor)
screen.blit(circle,(pygame.mouse.get_pos()[0],100))
pygame.display.update()
pygame.time.delay(10)
Edit in answer to your comment: It is possible to do this in a more object-oriented way.
You will need to have a background Surface associated with your screen (I usually have a Display or Map class (depending on the type of game) that does this). Then, make your object a subclass of pygame.sprite. This requires that you have self.image and self.rect attributes (the image being your surface and the rect being a Pygame.rect with the location). Add all of your sprites to a pygame.group object. Now, every frame, you call the draw method on the group and, after you update the display (ie, with pygame.display.update()), you call the clear method on the group. This method requires that you provide both the destination surface (ie, screen above) and a background image.
For example, your main loop may look more like this:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
circle.rect.center = (pygame.mouse.get_pos()[0],100)
circleGroup.draw(screen)
pygame.display.update()
circleGroup.clear(screen, backgroundSurface)
pygame.time.delay(10)
See the documentation on the Sprite and Group classes for more information.
Related
i have started a new project in python using pygame and for the background i want the bottom half filled with gray and the top black. i have used rect drawing in projects before but for some reason it seems to be broken? i don't know what i am doing wrong. the weirdest thing is that the result is different every time i run the program. sometimes there is only a black screen and sometimes a gray rectangle covers part of the screen, but never half of the screen.
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAY=pygame.display.set_mode((800,800))
pygame.display.set_caption("thing")
pygame.draw.rect(DISPLAY, (200,200,200), pygame.Rect(0,400,800,400))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
You need to update the display.
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().
See pygame.display.flip():
This will update the contents of the entire display.
While pygame.display.flip() will update the contents of the entire display, pygame.display.update() allows updating only a portion of the screen to updated, instead of the entire area. pygame.display.update() is an optimized version of pygame.display.flip() for software displays, but doesn't work for hardware accelerated displays.
The typical PyGame application loop has to:
handle the events by calling 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 (draw all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage with pygame.time.Clock.tick
import pygame
from pygame.locals import *
pygame.init()
DISPLAY = pygame.display.set_mode((800,800))
pygame.display.set_caption("thing")
clock = pygame.time.Clock()
run = True
while run:
# handle events
for event in pygame.event.get():
if event.type == QUIT:
run = False
# clear display
DISPLAY.fill(0)
# draw scene
pygame.draw.rect(DISPLAY, (200,200,200), pygame.Rect(0,400,800,400))
# update display
pygame.display.flip()
# limit frames per second
clock.tick(60)
pygame.quit()
exit()
repl.it/#Rabbid76/PyGame-MinimalApplicationLoop See also Event and application loop
simply change your code to:
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAY=pygame.display.set_mode((800,800))
pygame.display.set_caption("thing")
pygame.draw.rect(DISPLAY, (200,200,200), pygame.Rect(0,400,800,400))
pygame.display.flip() #Refreshing screen
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
it should help
I'm following a very basic pygame tutorial, which I've done before. I'm suspecting there's a version issue, though I'm at a loss how to move forward.
macOS 10.14.4
Python 3.7.2
pip 18.1 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
code:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((800,600))
surf = pygame.Surface((75,25))
surf.fill((125,125,125))
# What does this rect do?
rect = surf.get_rect()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.blit(surf, (400,300))
pygame.display.flip()
The only question I have there is what is that rect assignment for? I can't blit the rect, so it appears to have no purpose.
I've gone through a couple other tutorials, copy-pasted code and I get the same result with each one: a white screen with no rectangles. It's as if the display code works, but any other surface just don't appear.
No errors in the console. I'm really not sure how to debug at this point.
There is nothing to debug here. rect = surf.get_rect() is not used, maybe like martineau said in the comment will be used later in the tutorial.
What the code is doing is to draw a small gray rectangle on a gray surface (that's why you do not see anything).
surf = pygame.Surface((75,25))
This creates a small gray surface, which is blit later in the main loop at coordinates (top-left corner) 400, 300:
screen.blit(surf, (400,300))
As I said, the reason you do not see it is because surf il filled with gray (this line):
surf.fill((125,125,125))
and your background is gray too. I do not know if this is system dependent, on my linux the background is black and the rectangle is clearly visible.
So try to change the color of the rectangle to something clearer or darker, or fill the display surface with black before the main loop by doing:
screen.fill((0, 0, 0))
I just found out about pygame.surface.scroll() and what I understand from the pygame documents that scroll() is for moving surface without the need to rebuild the background again to cover the old surface, just like pygame.rect.move_ip() but for surfaces.
Anyway, I don't know how to use it and the examples in the pygame documents are hard to me to understand as long as I am beginner and, after searching for long time, I couldn't found anything useful to understand how to use it.
Here is my code.
import pygame
from pygame.locals import*
screen=pygame.display.set_mode((1250,720))
pygame.init()
clock=pygame.time.Clock()
boxx=200
boxy=200
image = pygame.Surface([20,20]).convert_alpha()
image.fill((255,255,255))
while True :
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT :
pygame.quit()
quit()
image.scroll(10,10)
screen.blit(image,(boxx,boxy))
pygame.display.update()
clock.tick(60)
EDIT: Your image and screen variables are backwards. That is also causing you some confusion I'm sure..
Your problem may is that you are trying to scroll an all black background. It is probably scrolling, and you just don't know it because the white box you used blit() to draw on the screen is stationary.
Try using something you can see scroll, like an image file. If you wanna move the white box, you can add a counter as a speed variable. Read this, then run it.
import pygame
from pygame.locals import*
screen=pygame.display.set_mode((1250,720))
pygame.init()
clock=pygame.time.Clock()
boxx=200
boxy=200
image = pygame.Surface([20,20]).convert_alpha()
image.fill((255,255,255))
speed = 5 # larger values will move objects faster
while True :
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT :
pygame.quit()
quit()
image.scroll(10,10)
# I did modulus 720, the surface width, so it doesn't go off screen
screen.blit(image,((boxx + speed) % 720, (boxy + speed) % 720))
pygame.display.update()
clock.tick(60)
I can't say for sure the scroll function is working or not, learn to use an image as your background so you can see it moving first.
I am trying to create a simple program in which a user can move a shape on the screen using his finger (on a touchscreen).
this is my code so far:
import pygame
def main():
pygame.init()
DISPLAY = pygame.display.set_mode((1000,500),0,32)
WHITE = (255,255,255)
blue = (0,0,255)
DISPLAY.fill(WHITE)
pygame.mouse.set_visible(False)
pygame.draw.rect(DISPLAY, blue,(480,200,50,250))
pygame.display.update()
pygame.mouse.set_pos(480, 200)
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
pygame.draw.rect(DISPLAY, blue, (pos[0]-25,pos[1], 50, 250))
pygame.display. update()
DISPLAY.fill(WHITE)
main()
The problem is that when I touch the screen, nothing will happen until I move my finger. If I print the events I can see that there is no event listed until I start moving my finger, so that is probably the reason.
I want to be able to register the finger press (as an event I guess) on the screen even before it starts to move, is there anyway to do this using PyGame?
Thanks.
In case anyone is stumbling across this later, in pygame 2 there is much better touch support. You can install with
pip install pygame==2.0.0.dev6
(check the pygame github for the most recent version) And there are three new event types. pygame.FINGERDOWN, pygame.FINGERUP, and pygame.FINGERMOTION. The pygame.FINGERUP event registers the touch input right when the screen is touched instead of when the screen is released like pygame.MOUSEBUTTONDOWN
I have made a game that utilises a computer touch screen and manages the touch quite well by handling two types of events. One is pygame.MOUSEMOTION and the other one is pygame.MOUSEBUTTONDOWN. Both of them contain the attribute event.pos. Problem is, at least when it comes to my touch screen (Lenovo), that the initial touch is not registered by the event handler of pygame.
You can confirm this by printing all the events to the terminal while touching your screen. I get nothing until I release or move my finger but on release I get the event pygame.MOUSEBUTTONDOWN rapidly followed by pygame.MOUSEBUTTONUP.
I know that this doesn't really solve your problem, but it might perhaps help you in some way. Otherwise, check out Kivy. There might be a solution there.
import pygame
def main():
pygame.init()
DISPLAY = pygame.display.set_mode((1000,500),0,32)
WHITE = (255,255,255)
blue = (0,0,255)
DISPLAY.fill(WHITE)
pygame.mouse.set_visible(False)
pygame.draw.rect(DISPLAY, blue,(480,200,50,250))
pygame.display.update()
pygame.mouse.set_pos(480, 200)
while True:
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN or event.type == MOUSEMOTION:
pos = event.pos
pygame.draw.rect(DISPLAY, blue, (pos[0]-25,pos[1], 50, 250))
pygame.display. update()
DISPLAY.fill(WHITE)
main()
I've just started learning how to use pygame yesterday. I was read this one book that was super helpful and followed all its tutorials and examples and stuff. I wanted to try making a really simple side scroller/platforming game but the book sorta jumped pretty fast into 3D modeling with out instructing how to make changing sprites for movement of up down left and right and how to cycle through animating images.
I've spent all today trying to get a sprite to display and be able to move around with up down left and right. But because of the simple script it uses a static image and refuses to change.
Can anyone give me some knowledge on how to change the sprites. Or send me to a tutorial that does?
Every reference and person experimenting with it ha always been using generated shapes so I'm never able to work with them.
Any help is very appreciated.
Added: before figuring out how to place complex animations in my scene I'd like to know how I can make my 'player' change to unmoving images in regards to my pressing up down left or right. maybe diagonal if people know its something really complicated.
Add: This is what I've put together so far. http://animania1.ca/ShowFriends/dev/dirmove.rar would there be a possibility of making the direction/action set the column of the action and have the little column setting code also make it cycle down in a loop to do the animation? (or would that be a gross miss use of efficiency?)
Here is a dumb example which alernates between two first images of the spritesheet when you press left/right:
import pygame
quit = False
pygame.init()
display = pygame.display.set_mode((640,480))
sprite_sheet = pygame.image.load('sprite.bmp').convert()
# by default, display the first sprite
image_number = 0
while quit == False:
event = pygame.event.poll()
no_more_events = True if event == pygame.NOEVENT else False
# handle events (update game state)
while no_more_events == False:
if event.type == pygame.QUIT:
quit = True
break
elif event.type == pygame.NOEVENT:
no_more_events = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
image_number = 0
elif event.key == pygame.K_RIGHT:
image_number = 1
event = pygame.event.poll()
if quit == False:
# redraw the screen
display.fill(pygame.Color('white'))
area = pygame.Rect(image_number * 100, 0, 100, 150)
display.blit(sprite_sheet, (0,0), area)
pygame.display.flip()
I've never really used Pygame before so maybe this code shoudln't really be taken as an example. I hope it shows the basics though.
To be more complete I should wait some time before updating, e.g. control that I update only 60 times per second.
It would also be handy to write a sprite class which would simplify your work. You would pass the size of a sprite frame in the constructor, and you'd have methodes like update() and draw() which would automatically do the work of selecting the next frame, blitting the sprite and so on.
Pygame seems to provide a base class for that purpose: link text.
dude the only thing you have to do is offcourse
import pygame and all the other stuff needed
type code and stuff..........then
when it comes to you making a spri
class .your class nam here. (pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.init(self)
self.image=pygame.image.load(your image and path)
self.rect=self.image.get_rect()
x=0
y=0
# any thing else is what you want like posistion and other variables
def update(self):
self.rect.move_ip((x,y))
and thats it!!!! but thats not the end. if you do this you will ony have made the sprite
to move it you need
I don't know much about Pygame, but I've used SDL (on which Pygame is based).
If you use Surface.blit(): link text
You can use the optional area argument to select which part of the surface to draw.
So if you put all the images that are part of the animation inside a single file, you can select which image will be drawn.
It's called "clipping".
I guess you will have a game loop that will update the game state (changing the current image of the sprite if necessary), then draw the sprites using their state.