How can I make a moving rectangle by pressing 1 key? - python

I am trying to make code to move a rectangle by pressing a key. In my code I made a while loop to keep drawing a rectangle that moves to the right in steps of 10 pixels but my progrem only shows the drawing execution of the end of the while loop.
Does anybody knows what I am doing wrong or how to fix it.
See my code below:
x=10
pygame.draw.rect(DISPLAYSURF, GREEN, (0, 10, 10,10))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
while x<=380:
pygame.time.wait(100)
x = x + 20
print(x)
DISPLAYSURF.fill(BLACK)
pygame.draw.rect(DISPLAYSURF, GREEN, (x, 10, 10,10))
pygame.display.update()

See Pygame window not responding after a few seconds.
Note, the display is updated when pygame.display.update(), but to make the timing and display update proper work, you've to handle the events between the updates of the display by either pygame.event.get() or pygame.event.pump(). Avoid loops which do some drawing inside the game loop. Use the game loop to perform the animations.
You don't need the inner while loop at all. You've a game loop. Add a state move and initialize it by False.
move = False
When the key is pressed then change the state to True:
if event.key == pygame.K_RIGHT:
move = True
If move is stated and as long x <= 380 increment x:
while True:
# [...]
if move and x <= 380:
x += 20
The game loop should look like this:
x = 0
move = False
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
move = True
if move and x <= 380:
x += 20
pygame.time.wait(100)
DISPLAYSURF.fill(BLACK)
pygame.draw.rect(DISPLAYSURF, GREEN, (x, 10, 10,10))
pygame.display.update()

You need to do do pygame.display.update() every time you draw. Move that line to be called inside your while loop after pygame.draw.rect

Related

How do you make your sprite not replicate itself in the screen? How do you make your sprite go away or start again, once the text appears?

So, I got stuck again, but I use this as a last resort when nothing's working after extensive research. Please don't roast me for this, I am a newbie. So, basically I am trying to make my sprite move (yoyo), but the frames keep replicating as the yoyo moves up and down. So, I don't know how to fix that. If the yoyo touches the borders of the game window, it collides and it's supposed to display a text and then the game starts over again. However, when the yoyo collides with the window border, it restarts, but the yoyo that got stuck is still being displayed and a new yoyo appears. The text is displayed but doesn't go away after 2 seconds.
import pygame
import time
pygame.init()
width = 900
height = 900
red = (255,0,0)
text = "game over"
screem = pygame.display.set_mode((width,height))
pygame.display.set_caption("yoyo")
clock = pygame.time.Clock()
background = pygame.image.load("room.png").convert()
win.blit(background, [0,0])
yoyo= pygame.image.load("yoyo.png").convert()
def Yoyo (x,y):
win.blit(yoyo, [x,y])
def mainloop():
x = 87
y = 90
yc = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Exit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
Yoyo(x,y)
y += yc
if y > 23 or y < -90:
pygame.display.update()
clock.tick(60)
mainloop()
pygame.quit()
quit()
Redraw the entire scene in every frame. This means you've to draw the background in every frame, too.
Draw (blit) the background in the main loop, before anything else is drawn:
while not Exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Exit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame. K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
y += y_change
if y > 405 or y < -200:
collision()
GameLoop()
win.blit(bg, [0,0]) # <----- draw background
Bee(x,y) # <----- draw the bee on the background
# [...] all further drawing has to be done here
pygame.display.update()
clock.tick(60)

How to make paddles move in pygame pong?

I am a beginner of pygame. Recently I code a Pong game.
However, I cannot make paddles move when I press the certain keys in keyboard. Can someone helps me check the code. I think maybe I have some problems in giving paddles' new position. But I cannot fix it. And hopefully give me some hints about that.
Thanks!
Code below:
import pygame, sys, time,math
from pygame.locals import *
# User-defined functions
def main():
# Initialize pygame
pygame.init()
# Set window size and title, and frame delay
surfaceSize = (500, 400) # window size
windowTitle = 'Pong' #window title
frameDelay = 0.005 # smaller is faster game
# Create the window
pygame.key.set_repeat(20, 20)
surface = pygame.display.set_mode(surfaceSize, 0, 0)
pygame.display.set_caption(windowTitle)
# create and initialize red dot and blue dot
gameOver = False
color1=pygame.Color('white')
center1 = [250, 200]
radius1=10
score=[0, 0]
speed1=[4,1]
location1=[50, 150]
location2=[450, 150]
size=(5, 100)
position1=(0,0)
position2=(350,0)
rect1=pygame.Rect(location1,size)
rect2=pygame.Rect(location2,size)
# Draw objects
pygame.draw.circle(surface, color1, center1, radius1, 0)
# Refresh the display
pygame.display.update()
# Loop forever
while True:
# Handle events
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# Handle additional events
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
location1[1] =+ 1
if event.key == pygame.K_p:
location2[1] =+ 1
if event.key == pygame.K_a:
location1[1] =- 1
if event.key == pygame.K_i:
location2[1] =- 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_q:
location1[1] =+ 0
if event.key == pygame.K_p:
location2[1] =+ 0
if event.key == pygame.K_a:
location1[1] =- 0
if event.key == pygame.K_i:
location2[1] =- 0
# Handle additional events
# Update and draw objects for the next frame
gameOver = update(surface,color1,center1,radius1,speed1,rect1,rect2,score,position1,position2)
# Refresh the display
pygame.display.update()
# Set the frame speed by pausing between frames
time.sleep(frameDelay)
def update(surface,color1,center1,radius1,speed1,rect1,rect2,score,position1,position2):
# Check if the game is over. If so, end the game and
# returnTrue. Otherwise, erase the window, move the dots and
# draw the dots return False.
# - surface is the pygame.Surface object for the window
eraseColor=pygame.Color('Black')
surface.fill(eraseColor)
moveDot(surface,center1,radius1,speed1,score,position1,position2)
pygame.draw.circle(surface,color1,center1,radius1,0)
r1=pygame.draw.rect(surface, color1, rect1)
r2=pygame.draw.rect(surface, color1, rect2)
if r1.collidepoint(center1) and speed1[0]<0:
speed1[0]=-speed1[0]
if r2.collidepoint(center1) and speed1[0]>0:
speed1[0]=-speed1[0]
def moveDot(surface,center,radius,speed,score,position1,position2):
#Moves the ball by changing the center of the ball by its speed
#If dots hits left edge, top edge, right edge or bottom edge
#of the window, the then the ball bounces
size=surface.get_size()
for coord in range(0,2):
center[coord]=center[coord]+speed[coord]
if center[coord]<radius:
speed[coord]=-speed[coord]
if center[coord]+radius>size[coord]:
speed[coord]=-speed[coord]
if center[0]<radius:
score[0]=score[0]+1
drawScore(center,surface,score,position2,0)
if center[0]+radius>size[0]:
score[1]=score[1]+1
drawScore(center,surface,score,position1,1)
def drawScore(center1,surface,score,position,whichscore):
FontSize=30
FontColor=pygame.Color('White')
String='Score : '
font=pygame.font.SysFont(None, FontSize, True)
surface1=font.render(String+str(score[whichscore]), True, FontColor,0)
surface.blit(surface1,position)
main()
You always use the rects rect1 and rect2 to draw your paddles. But to update their position, you try to change values in the lists location1 and location2.
Stop it. Just alter the rects. The easiest way is to use move_ip to change the rects in place.
Also, if you want to keep your paddles moving while the players keep the movement keys pressed, use pygame.key.get_pressed to get a list of all pressed keys (since pressing a key only generates a single KEYDOWN event, unless you mess with pygame.key.set_repeat, which you shouldn't).
So your code should look like this:
...
while True:
# Handle events
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pressed = pygame.key.get_pressed()
if pressed[pygame.K_q]: rect1.move_ip(0, -1)
if pressed[pygame.K_a]: rect1.move_ip(0, 1)
if pressed[pygame.K_p]: rect2.move_ip(0, -1)
if pressed[pygame.K_i]: rect2.move_ip(0, 1)
gameOver = ...
...

Pygame - why my game repeats instead of closing?

First of all, sorry for my noob question.
So I'm trying to learn pygame, and to do so I created a """game""' that is supposed to quit whenever someone clicks the close button ("x" button") in the top corner of the window, but instead the whole game restarts itself.
I use "Game = False" to point that the game needs to close, since everything that the game does is located in a loop that only starts with "Game = True", and at the end of the script (after the loop ends) there is a "pygame.quit()" and a "sys.exit()". This was was working fine, but recenlty I added the following lines:
if x < 0 or x > display_width - spacecore_width:
game_over()
Those are supposed to call a "game_over" function, that resets the game by calling the another function that covers the whole game (the loop is located inside of this function). But this is not supposed to happen when someone clicks the "x" button to quit the game, and I have no idea of why this also happens when such thing is done (besides working as intended, by only repeating the game if "x < 0 or x > display_width - spacecore_width".
I already know how to avoid it (I just need to replace "Game = False" with those quit commands) but I would like to know why the problem happens in the first place.
Here's the full code:
import pygame, sys, time
pygame.init()
display_width = 800
display_height = 600
DISPLAY = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Não enconste nas bordas da tela")
WHITE = (255,255,255)
RED = (255,0,0)
SPACECORE = pygame.image.load("spacecore.png")
spacecore_width = 100
clock = pygame.time.Clock()
def text_and_rect(text,font):
text_surface = font.render(text,True,RED)
return text_surface, text_surface.get_rect()
def message_display(text):
font = pygame.font.Font("freesansbold.ttf",50)
text_surf, text_rect = text_and_rect(text,font)
text_rect.center = ((display_width/2),(display_height/2))
DISPLAY.blit(text_surf,text_rect)
pygame.display.update()
time.sleep(2)
def game_over():
message_display("Você morreu de morte morrida")
game_loop()
def player(x,y):
DISPLAY.blit(SPACECORE,(x,y))
def game_loop():
Game = True
x = display_width * 0.5
y = display_height * 0.8
mod_x = mod_y = 0
while Game == True:
pygame.display.update()
DISPLAY.fill(WHITE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
Game = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
mod_x = -5
if event.key == pygame.K_RIGHT:
mod_x = 5
if event.key == pygame.K_UP:
mod_y = -5
if event.key == pygame.K_DOWN:
mod_y = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
mod_x = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
mod_y = 0
x += mod_x
y += mod_y
clock.tick(60)
player(x,y)
if x < 0 or x > display_width - spacecore_width:
game_over()
game_loop()
pygame.quit()
sys.exit()
Make sure you're breaking out of the loop and then calling the loop function again:
while Game == True:
# some here code
if x < 0 or x > display_width - spacecore_width:
break # leave while loop
# proceed elsewhere
game_over()
Or alternatively cut the flow back to game_loop in game_over:
def game_over():
message_display("Você morreu de morte morrida")
# game_loop() # removed
Currently you're never breaking out of loops when game is over - you're just calling other functions (which in turn active another loop) in a mutually-recursive manner, effectively this never ends any game.
Also, if you receive a quit event you may want to break out of the for loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Game = False
break

Python/Pygame; MOUSEBUTTONDOWN event

Okay I'm pretty new to using Pygame, I'm really just playing around with some of the methods and events. So far i pretty much have an image that moves around the pygame frame and bounces off any of the edges of the frame when it hits it. if the image touches the top of the frame it will increase a count variable by 1 which will be displayed on the screen. I then wanted to add a feature whereby if I clicked the image which was moving it would also add one onto the count variable. When i added this code in however (I think because the function operates on a loop), depending how long you hold the mouse down, count increases by a multiple of 8. I want to make it so that no matter how long i hold the mouse down for, the event stored inside the MOUSEBUTTONDOWN handler will only fire once. what am I doing wrong?
import pygame, sys
from pygame.locals import *
pygame.init()
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Hello World!')
screen =pygame.display.set_mode((600,400))
ball = pygame.image.load("homers.png")
ball = pygame.transform.scale(ball,(225,200))
x=200
y=100
left = True
up = True
color = 67,143,218
def text_objects(text,font):
text_surface = font.render(text,True, color)
return text_surface,text_surface.get_rect()
def message_display(text,x,y,z):
largeText = pygame.font.Font('freesansbold.ttf',z)
TextSurf,TextRect = text_objects(text,largeText)
TextRect.center = (x,y)
screen.blit(TextSurf,TextRect)
def hi(x,y,p,z):
message_display(x,y,p,z)
count = 0
message_count = str(count)
while True: # main game loop
screen.fill((180,0,0))
screen.blit(ball,(x,y))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
hi(message_count,x,y,140)
hi("How Many Times Has Homer Hit His Head?",300,200,20)
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
if ball.get_rect().collidepoint(x, y):
count = count+1
if event.type == pygame.MOUSEBUTTONUP:
0
if left == True:
x=x-10
if x == -100:
left =False
if left == False:
x=x+10
if x == 450:
left = True
if up == True:
y=y-10
if y == -20:
up =False
count = count+1
message_count = str(count)
hi(message_count,x,y,140)
if up == False:
y=y+10
if y== 230:
up =True
pygame.display.update()
You have to fix the indentation of your code:
while True: # main game loop
screen.fill((180,0,0))
screen.blit(ball,(x,y))
hi(message_count,x,y,140)
hi("How Many Times Has Homer Hit His Head?",300,200,20)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
# this has to be part of the for loop
if event.type == pygame.MOUSEBUTTONDOWN:
if ball.get_rect().collidepoint(x, y):
count = count+1
...

Multiple missiles/bullets in a space invader clone (First go at a game with python)

I'm a beginner programmer and my first language is Python 2.7, I'm trying to make a space invader type game but i want to have multiple bullets at once and cant find a way to do that. so i made my own way here is my code ill explain more after you see it
if event.type ==pygame.KEYDOWN and event.key==K_SPACE:
if m < 5:
m+=1
if m==1:
m1a=1
m1x=ls
if m==2:
m2a=1
m2x=ls
if m==3:
m3a=1
m3x=ls
if m==4:
m4a=1
m4x=ls
if m==5:
m5a=1
m5x=ls
print m
#missle 1
if m1a==1:
screen.blit(rship,(m1x,m1))
if m1>=0:
m1-=1
else:
m-=1
m1a=0
m1=460
#missle 2
if m2a==1:
screen.blit(rship,(m2x,m2))
if m2>=0:
m2-=1
else:
m-=1
m2a=0
m2=460
#missle 3
if m3a==1:
screen.blit(rship,(m3x,m3))
if m3>=0:
m3-=1
else:
m-=1
m3a=0
m3=460
#missle 4
if m4a==1:
screen.blit(rship,(m4x,m4))
if m4>=0:
m4-=1
else:
m-=1
m4a=0
m4=460
#missle 5
if m5a==1:
screen.blit(rship,(m5x,m5))
if m5>=0:
m5-=1
else:
m-=1
m5a=0
m5=460
I'm sure its laughably noobish but I'm just learning but the problem is the first and second missile are fine its the third and beyond that get messed up. when you fire the third it moves the second over the where your shooting from and then if you fir again the code wont go back down to 1 it stays at 2 and gets even more glitches. If you need me to try and explain it better I gladly will. Just trying to Learn.
Full code here: pastebin.com/FnPaME6N
You should make your "bullets" sprites and then add them to a group called bullets or something. Calling the update method on the group will update all your bullets in a single go.
Here is some working code, but I wouldn't call it great.
import pygame
import math
from pygame.locals import *
background_colour = (122, 100, 155)
(width, height) = (500, 500)
pygame.init()
#ship = pygame.image.load('lolol.jpeg')\
rship = pygame.image.load('js.jpg')
mis = pygame.image.load('lot.jpg')
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('A.N.T.O.N.I.A.')
screen.fill(background_colour)
pygame.display.flip()
running = True
MAX_MISSILES = 5
ls = 250 # Horizontal ship location
LEFT = False
RIGHT = False
def move(ls, RIGHT, LEFT):
'''Moves the ship 3 pixels to the left or right.
Only moves if just one direction key is down, and not both.
Also, will not move if the ship is at either horizontal screen edge.
ls is the ship location.
'''
if LEFT and not RIGHT:
if ls >= 10:
ls -= 3
elif RIGHT and not LEFT:
if ls <= 440:
ls += 3
return ls
def fire_missile(ls, missiles):
'''Fire a missile, as long as we are not at the maximum number.
We use a list to hold our missile locations.
'''
if len(missiles) >= MAX_MISSILES:
return
else:
missiles.append((ls, 460))
def draw_missiles(missiles):
'''Draw all the missiles.'''
if missiles:
for missile in missiles:
screen.blit(mis, (missile))
def move_missiles(missiles):
'''If there are any missiles, move them up 1 pixel, and append
them to the newlist. The new list will replace the old list.
'''
if missiles:
newmissiles = []
for missile in missiles:
# Do not append the missile to the new list if it is going
# off the screen
if missile[1] > 0:
newmissiles.append((missile[0], missile[1] - 1))
return newmissiles
else:
return missiles
missiles = []
while running:
screen.blit(rship, (ls, 450))
pygame.display.flip()
screen.fill(background_colour)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
if event.type == pygame.KEYDOWN and event.key == K_ESCAPE:
# You can now quit with the escape key.
pygame.quit()
running = False
if event.type == pygame.KEYDOWN and event.key == K_LEFT:
LEFT = True
# LEFT is True untli you let up in the LEFT key
if event.type == pygame.KEYUP and event.key == K_LEFT:
LEFT = False
if event.type == pygame.KEYDOWN and event.key == K_RIGHT:
RIGHT = True
if event.type == pygame.KEYUP and event.key == K_RIGHT:
RIGHT = False
if event.type == pygame.KEYDOWN and event.key == K_SPACE:
fire_missile(ls, missiles)
ls = move(ls, RIGHT, LEFT)
draw_missiles(missiles)
missiles = move_missiles(missiles)
Any time you find yourself making variables with numbers in them, it's a code smell, and means you probably should use a different data type.
As has been suggested, you'll probably want to look into the sprite and group modules, but this will at least do what you were trying to do so far.

Categories

Resources