I had an earlier post deleted because there are similar posts. I appreciate that but because I am so inexperienced with pygame (I literally began using it last week), I cant make heads or tails of the code. Also, I am finding it difficult to apply to my game. Firstly, I do not need it to relate to a moving player character as they will always travel from a set position (400, 450). Also, I preferably need it to do this when the left mouse button is pressed but if it is easier to use a key then that is fine. I simply do not have the expertise to use past posts and apply it to my program. Thanks. Just to clarify, my game is going to be a duck hunt-like target shooter game.
#Setting window dimensions and caption (Module 1)
pygame.init()
window = pygame.display.set_mode((800, 575))
pygame.display.set_caption("TARGET PRACTICE")
#Colour variables (Module 1)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)
exec = True
#Target class created (Module 5)
class Target:
def __init__(self, x, y, h, w, v):
self.x = x
self.y = y
self.h = h
self.w = w
self.v = v
#Instantiation of targets (Module 5)
target_1 = Target(0, 80, 60, 40, 0.5)
target_2 = Target(0, 100, 60, 40, 0.5)
target_3 = Target(0, 50, 60, 40, 0.5)
target_4 = Target(0, 75, 60, 40, 0.5)
target_5 = Target(0, 45, 60, 40, 0.5)
target_6 = Target(0, 85, 60, 40, 0.5)
#Declaring variables to be used in the while loop (Module 5)
clock = 0
target_2_threshold = 500
target_3_threshold = 1000
target_4_threshold = 1500
target_5_threshold = 2000
target_6_threshold = 2500
#Setting player sprite dimension variables (Module 6)
player_sprite_x = 357.5
player_sprite_y = 450
player_sprite_h = 125
player_sprite_w = 85
while exec:
pygame.time.delay(1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
#Defines movement of targets and sets delay between drawings (Module 5)
clock += 1
target_1.x += target_1.v
if clock > target_2_threshold:
target_2.x += target_2.v
if clock > target_3_threshold:
target_3.x += target_3.v
if clock > target_4_threshold:
target_4.x += target_4.v
if clock > target_5_threshold:
target_5.x += target_5.v
if clock > target_6_threshold:
target_6.x += target_6.v
#Fill the background (Module 5)
window.fill(RED)
#Redraw each target in every frame (Module 5)
pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
if clock > target_2_threshold:
pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))
if clock > target_3_threshold:
pygame.draw.rect(window, BLUE, (target_3.x, target_3.y, target_3.h, target_3.w))
if clock > target_4_threshold:
pygame.draw.rect(window, BLUE, (target_4.x, target_4.y, target_4.h, target_4.w))
if clock > target_5_threshold:
pygame.draw.rect(window, BLUE, (target_5.x, target_5.y, target_5.h, target_5.w))
if clock > target_6_threshold:
pygame.draw.rect(window, BLUE, (target_6.x, target_6.y, target_6.h, target_6.w))
#Draw the player sprite (Module 6)
pygame.draw.rect(window, BLUE, (player_sprite_x, player_sprite_y, player_sprite_w, player_sprite_h))
pygame.display.update()
pygame.quit()
Here are some brief notes to get you pointed in the right direction. People often write questions that amount to "Gimme teh codez!", so very open and broad questions are often greeted (quite rightly) with negativity.
So...
First you need to grab the mouse cursor. This is achieved by handling the mouse events in your main event-loop:
while exec:
#pygame.time.delay(1) # <-- DON'T DO THIS
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
elif event.type == pygame.MOUSEBUTTONUP: # mouse button released
mouse_position = pygame.mouse.get_pos()
# TODO: handle mouse click at <mouse_position>
Note: I like to use MOUSEBUTTONUP rather than DOWN, because this is how modern GUIs tend to work - on-screen operations activate on release, but it's up to you.
Now you have the click-position, how do you launch a bullet from the bottom-centre of the screen to the mouse co-ordinates?
Well, first what is bottom-centre? It's half the width of the window, and maybe some factor from the bottom. In PyGame the top-left corner of the screen is (0, 0), and the bottom-left is ( 0, window_height-1 ). I always store the window size in variables, so computing this position is easy, and it frees the code from having to be modified if the window/screen size changes.
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 575
# Firing position is 98% bottom, middle of the window/screen.
start_position = ( ( WINDOW_WIDTH // 2, int( WINDOW_HEIGHT * 0.98 ) )
So then given a mouse-click, the code needs to make the bullet travel from start_position to mouse_position. This can be calculated, by working out an x and y speed which should be applied, each update, to the projectile. Obviously a projectile travelling straight down has a speed of ( 0, something ), and a projectile going directly right has a speed of ( something, 0 ). Obviously if travelling up or left, the something would be negative because of the way PyGame lays-out its co-ordinates. The point is that there are separate components of change: x for the horizontal movement, and y for the vertical .
To calculate this x and y speed (technically a velocity vector), the code needs to determine the line from start to end, and then normalise it (a fancy way of saying "divide it by it's length").
I'm assume you know the line-length formula already, so this part should be easy. It makes the calculations simpler if the code temporarily offsets both points as-if the origin was at (0,0), since the direction is still the same.
Once the code has the velocity vector (x, y), each animation update-cycle simply add these component-speeds to the co-ordinate of the projectile. You may need to store the co-ordinates as real numbers, since adding small amounts (e.g.: 0.2) to an integer tends to throw away the change. This is because some-integer + 0.2 -> some-integer.
Anyway, see how you go with this information. If trouble persists ... ask another question!
Use event pygame.MOUSEBUTTONDOWN to get mouse click and its position.
You can use pygame.math.Vector2() to create vector between mouse and player. And then you can use normalize() to create value which you can use as bullet's direction.
And keep in variable or list bullet's position and bullet's direction
all_bullets = []
while exec:
pygame.time.delay(1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
print("[shoot!] mouse position:", event.pos)
dx = event.pos[0] - (player_sprite_x+ player_sprite_w//2)
dy = event.pos[1] - player_sprite_y
direction = pygame.math.Vector2(dx, dy).normalize()
bullet = {'x': player_sprite_x+42, 'y': player_sprite_y, 'direction': direction}
all_bullets.append(bullet)
Later you can use for-loop to move every bullet on list and keep only bullets which are still on screen
all_bullets_keep = []
for item in all_bullets:
item['x'] += item['direction'][0] # item['direction'][0] * 2
item['y'] += item['direction'][1] # item['direction'][1] * 2
# keep bullet if it is still on screen
if 0 < item['x'] < 800 and 0 < item['y'] < 575:
all_bullets_keep.append(item)
all_bullets = all_bullets_keep
#print(len(all_bullets), end='\r')
Finally you can use for-loop to draw all bullets
for item in all_bullets:
pygame.draw.rect(window, BLUE, (item['x']-5, item['y']-5, 10, 10))
It still need to check collision with targets but it would be easier if you would keep targets on list and use pygame.Rect()` to keep position and size because it has special methods to check collisions.
So now you have work to use lists with tagets and pygame.Rect()
import pygame
pygame.init()
window = pygame.display.set_mode((800, 575))
pygame.display.set_caption("TARGET PRACTICE")
#Colour variables (Module 1)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)
exec = True
#Target class created (Module 5)
class Target:
def __init__(self, x, y, h, w, v):
self.x = x
self.y = y
self.h = h
self.w = w
self.v = v
#Instantiation of targets (Module 5)
target_1 = Target(0, 80, 60, 40, 0.5)
target_2 = Target(0, 100, 60, 40, 0.5)
target_3 = Target(0, 50, 60, 40, 0.5)
target_4 = Target(0, 75, 60, 40, 0.5)
target_5 = Target(0, 45, 60, 40, 0.5)
target_6 = Target(0, 85, 60, 40, 0.5)
#Declaring variables to be used in the while loop (Module 5)
clock = 0
target_2_threshold = 500
target_3_threshold = 1000
target_4_threshold = 1500
target_5_threshold = 2000
target_6_threshold = 2500
#Setting player sprite dimension variables (Module 6)
player_sprite_x = 357.5
player_sprite_y = 450
player_sprite_h = 125
player_sprite_w = 85
all_bullets = []
while exec:
pygame.time.delay(1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
print("[shoot!] mouse position:", event.pos)
dx = event.pos[0] - (player_sprite_x+ player_sprite_w//2)
dy = event.pos[1] - player_sprite_y
direction = pygame.math.Vector2(dx, dy).normalize()
bullet = {'x': player_sprite_x+42, 'y': player_sprite_y, 'direction': direction}
all_bullets.append(bullet)
#Defines movement of targets and sets delay between drawings (Module 5)
clock += 1
target_1.x += target_1.v
if clock > target_2_threshold:
target_2.x += target_2.v
if clock > target_3_threshold:
target_3.x += target_3.v
if clock > target_4_threshold:
target_4.x += target_4.v
if clock > target_5_threshold:
target_5.x += target_5.v
if clock > target_6_threshold:
target_6.x += target_6.v
all_bullets_keep = []
for item in all_bullets:
item['x'] += item['direction'][0] # item['direction'][0] * 2
item['y'] += item['direction'][1] # item['direction'][1] * 2
# keep bullet if it is still on screen
if 0 < item['x'] < 800 and 0 < item['y'] < 575:
all_bullets_keep.append(item)
all_bullets = all_bullets_keep
#print(len(all_bullets), end='\r')
#Fill the background (Module 5)
window.fill(RED)
#Redraw each target in every frame (Module 5)
pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
if clock > target_2_threshold:
pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))
if clock > target_3_threshold:
pygame.draw.rect(window, BLUE, (target_3.x, target_3.y, target_3.h, target_3.w))
if clock > target_4_threshold:
pygame.draw.rect(window, BLUE, (target_4.x, target_4.y, target_4.h, target_4.w))
if clock > target_5_threshold:
pygame.draw.rect(window, BLUE, (target_5.x, target_5.y, target_5.h, target_5.w))
if clock > target_6_threshold:
pygame.draw.rect(window, BLUE, (target_6.x, target_6.y, target_6.h, target_6.w))
for item in all_bullets:
pygame.draw.rect(window, BLUE, (item['x']-5, item['y']-5, 10, 10))
#Draw the player sprite (Module 6)
pygame.draw.rect(window, BLUE, (player_sprite_x, player_sprite_y, player_sprite_w, player_sprite_h))
pygame.display.update()
pygame.quit()
Related
so I am making a code where there is a character(A rectangle) and and Balloon(A circle) and the character has to catch the balloons before it hits the ground. Everything worked fine until I tried making the game look a little better and used the blit function to add an image. For some reason my text keeps buffering now.
Code:
import random
import pygame
from pygame.locals import *
pygame.init()
#Variables
white = (255, 255, 255)
blue = (70,130,180)
black = (0,0,0)
red = (255,0,0)
x = 400
y = 450
score = 0
cooly = 100
randomx = random.randint(100,800)
clock = pygame.time.Clock()
#screen stuff
screenwidth = 800
screenheight = 600
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption("Balloon Game!")
#end of screen stuff
#Initializing font
def show_text(msg, x, y, color,size):
fontobj= pygame.font.SysFont("freesans", size)
msgobj = fontobj.render(msg,False,color)
screen.blit(msgobj,(x, y))
#Game loop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
# Draw Character
screen.fill(blue)
character = pygame.draw.rect(screen, red, (x, y, 60, 60))
#End of Drawing Character
#Draw Balloons
balloon = pygame.draw.circle(screen, (black), (randomx, cooly), 30, 30)
cooly = cooly + 2
# Making Arrow Keys
keyPressed = pygame.key.get_pressed()
if keyPressed[pygame.K_LEFT]:
x -= 3
if keyPressed[pygame.K_RIGHT]:
x += 3
#Drawing Cool Stuff
Cloud = pygame.image.load('Cloud.png')
screen.blit(Cloud,(100,75))
pygame.display.update()
#End of making arrow keys
show_text("Score:",130,0,black,50)
show_text(str(score),250,0,black,50)
#Collision
if balloon.colliderect(character):
randomx = random.randint(100,800)
cooly = 100
score = score + 1
#end of collision
#Ending
if cooly >= 600:
screen.fill(blue)
show_text("Game Over!", 200, 250, black, 100)
show_text("Score :", 200, 350, black, 75)
show_text(str(score), 400, 350, black, 75)
#Polishing
if score == score + 5:
cooly += 1
x += 3
pygame.display.update()
clock.tick(250)
The problem is caused by multiple calls to pygame.display.update(). An update of the display at the end of the application loop is sufficient. Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering.
Remove all calls to pygame.display.update() from your code, but call it once at the end of the application loop.
Do not create the font object and do not load the images in the application loop. This are very expensive operatios, because the filed have to be read and interpreted:
fontobj= pygame.font.SysFont("freesans", size) #<-- INSERT
def show_text(msg, x, y, color,size):
# fontobj= pygame.font.SysFont("freesans", size) <-- DELET
msgobj = fontobj.render(msg,False,color)
screen.blit(msgobj,(x, y))
Cloud = pygame.image.load('Cloud.png') #<-- INSERT
# [...]
while True:
# [...]
# Cloud = pygame.image.load('Cloud.png') <-- DELETE
screen.blit(Cloud,(100,75))
# pygame.display.update() <-- DELETE
# [...]
pygame.display.update()
clock.tick(250)
So I am a bit stuck on how to implement the pipes spawning offscreen and making them move across the screen so that they can collide the bird and then DE spawning off screen. Do I need to give the pipes acceleration or something else?
I am fairly new to code but I have some ides on how to do it but I don't really know how to implement it or how to make a pipes randomly generate.
#Floppy disk
import sys, pygame
from pygame import mixer
import time
pygame.init()
pygame.mixer.init()
FRAMERATE = 60
clock = pygame.time.Clock()
mixer.music.load('africa-toto.wav')
mixer.music.play(1, 0.0, 3000)
size = width, height = 1000, 1000
speed = [2,2]
power = [0.1, 0.1]
white = 255, 255, 255
black = 0, 0, 0
blue = 0, 255, 200
green = 0, 200, 0
dy = 2
dx =2
screen = pygame.display.set_mode(size)
player1 = pygame.image.load("floppy1.jpg")
pygame.key.set_repeat(1,1)
player = pygame.draw.rect(screen, blue, (500, 500,10, 10))
playerrect = player1.get_rect()
background_image = pygame.image.load("circuit.jpeg").convert()
def obstacles():
obst1 = pygame.draw.rect(screen, green, (500, 600, 100, 450))
obst2 = pygame.draw.rect(screen, green, (500, 0, 100, 450))
obst3 = pygame.draw.rect(screen, green, (700, 0, 100, 400))
obst4 = pygame.draw.rect(screen, green, (700, 550, 100, 500))
obstacles()
while True:
clock.tick(FRAMERATE)
print(dy)
if dy > 0:
dy *= 1.03
if dy < 2:
dy *= 1.03
if dy < 0:
dy *= 0.9
if dy > -1.3:
dy *= 0.95
if dy < 0 and dy > -0.6: #Deceleraiton point
dy *= -1.2
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
## if event.key == pygame.K_LEFT:
## speed[0] -= power[0]
## if event.key == pygame.K_RIGHT:
## speed[0] += power[0]
if event.key == pygame.K_UP:
dy = -10
#speed[1] -= power[1]
if event.key == pygame.K_DOWN:
speed[1] += power[1]
if playerrect.bottom > height:
dy = -20
if playerrect.top < 0:
dy = 15
playerrect = playerrect.move(0, dy)
#screen.fill(white)
screen.blit(background_image, [0,0])
screen.blit(player1, playerrect, obstacles())
pygame.display.flip()
pygame.display.update()
for multiple things that do very similar things i would highly recommend the use of classes: https://docs.python.org/3/tutorial/classes.html
# you don't need to declare those variables globally, it's only one of multiple ways.
# a cleaner way would be to declare those as class variables, you can check out the
# documentation (linked above) for more information.
# random needs to be imported
spawn_timer = 0
movement_speed = 2
x_size = 50
gap_size = 300
pipes = []
# screen, width and height have already been declared
class Pipe:
def __init__(self, x_pos=width):
random_height = random.randint(0, height - gap_size)
self.upper_rect = pygame.Rect(x_pos, 0, x_size, random_height)
self.lower_rect = pygame.Rect(x_pos, random_heigt - gap_size,
x_size, height - random_height - gap_size)
def draw(self):
pygame.draw.rect(screen, green, self.upper_rect)
pygame.draw.rect(screen, green, self.lower_rect)
def collide(self, rect):
return self.lower_rect.colliderect(rect) or self.upper_rect.colliderect(rect)
def update(self)
self.upper_rect.move_ip(-movement_speed, 0)
self.lower_rect.move_ip(-movement_speed, 0)
# in the main loop:
spawn_timer += 1
if spawn_timer >= 200: # use different values for distance between pipes
pipes.append(Pipe())
spawn_timer = 0
for pipe in pipes:
pipe.draw()
pipe.update()
if pipe.collide(playerrect):
print('GAME OVER') # reset the game
if pipes and pipes[0].upper_rect.right < 0: # first pipe will be leftmost pipe.
pipes.pop(0)
also i noticed that the falling was not feeling as clean.
for a more natural movement, i would recommend adding something to the dy value instead of multiplying it.
if you have any questions, please write a comment.
EDIT: fixed list index out of range bug.
EDIT: fixed 'module' object is not callable
This question already has an answer here:
How do I continuously trigger an action at certain time intervals? Enemy shoots constant beam instead of bullets in pygame [duplicate]
(1 answer)
Closed 2 years ago.
I am programming a target shooter game for a school project. In the game, you click and a bullet flies from the player sprite to your cursor. I currently have programmed target drawing, player sprite drawing and a bullet function however I would like to limit how many times, say, per second the player can shoot. This is partly to avoid spam shooting ruining the game's performance and also making it more challenging than just rapidly left clickign everywhere. I would assume that I could use a 'pygame_clock' command but I'm not quite sure how. Below is the code:
import pygame
#Setting window dimensions and caption. (Module 1)
pygame.init()
window = pygame.display.set_mode((800, 575))
pygame.display.set_caption("TARGET PRACTICE")
#Colour variables. (Module 1)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)
#py_clock tracks framerate of program for other 'pygame.time' commands. (Module 8)
py_clock = pygame.time.Clock()
#Target class created. (Module 5)
class Target:
def __init__(self, x, y, h, w, v):
self.x = x
self.y = y
self.h = h
self.w = w
self.v = v
#Instantiation of targets. (Module 5)
target_1 = Target(0, 80, 60, 40, 0.5)
target_2 = Target(0, 100, 60, 40, 0.5)
target_3 = Target(0, 50, 60, 40, 0.5)
target_4 = Target(0, 75, 60, 40, 0.5)
target_5 = Target(0, 45, 60, 40, 0.5)
target_6 = Target(0, 85, 60, 40, 0.5)
#Declaring variables to be used in the while loop. (Module 5)
clock = 0
target_2_threshold = 500
target_3_threshold = 1000
target_4_threshold = 1500
target_5_threshold = 2000
target_6_threshold = 2500
#Setting player sprite dimension variables. (Module 6)
player_sprite_x = 357.5
player_sprite_y = 450
player_sprite_h = 125
player_sprite_w = 85
#all_bullets list to store bullets made by function inside loop. (Module7)
all_bullets = []
exec = True
while exec:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
#'IF' statement to trigger the shooting function. (Module 7)
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
dx = event.pos[0] - (player_sprite_x+ player_sprite_w//2)
dy = event.pos[1] - player_sprite_y
direction = pygame.math.Vector2(dx, dy).normalize()
bullet = {'x': player_sprite_x+42, 'y': player_sprite_y, 'direction': direction}
all_bullets.append(bullet)
#Defines movement of targets and sets delay between drawings. (Module 5)
clock += 1
target_1.x += target_1.v
if clock > target_2_threshold:
target_2.x += target_2.v
if clock > target_3_threshold:
target_3.x += target_3.v
if clock > target_4_threshold:
target_4.x += target_4.v
if clock > target_5_threshold:
target_5.x += target_5.v
if clock > target_6_threshold:
target_6.x += target_6.v
#all_bullets_keep list combined with FOR loop retains only bullets in the arena. (Module 7)
all_bullets_keep = []
for item in all_bullets:
item['x'] += item['direction'][0] # item['direction'][0] * 2
item['y'] += item['direction'][1] # item['direction'][1] * 2
if 0 < item['x'] < 800 and 0 < item['y'] < 575:
all_bullets_keep.append(item)
all_bullets = all_bullets_keep
#Fill the background (Module 5)
window.fill(RED)
#Redraw each target in every frame. (Module 5)
pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
if clock > target_2_threshold:
pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))
if clock > target_3_threshold:
pygame.draw.rect(window, BLUE, (target_3.x, target_3.y, target_3.h, target_3.w))
if clock > target_4_threshold:
pygame.draw.rect(window, BLUE, (target_4.x, target_4.y, target_4.h, target_4.w))
if clock > target_5_threshold:
pygame.draw.rect(window, BLUE, (target_5.x, target_5.y, target_5.h, target_5.w))
if clock > target_6_threshold:
pygame.draw.rect(window, BLUE, (target_6.x, target_6.y, target_6.h, target_6.w))
#Draw the player sprite. (Module 6)
pygame.draw.rect(window, BLUE, (player_sprite_x, player_sprite_y, player_sprite_w, player_sprite_h))
#Draw each item in all_bullets. (Module 7)
for item in all_bullets:
pygame.draw.rect(window, BLUE, (item['x']-5, item['y']-5, 10, 10))
pygame.display.update()
#tick_busy_loop limits number of times the game can refresh per second. (Module 8)
py_clock.tick_busy_loop(120)
pygame.quit()
A possibility is to limit the number of bullets. e.g:
if event.button == 1 and len(all_bullets) < 5:
dx = event.pos[0] - (player_sprite_x+ player_sprite_w//2)
dy = event.pos[1] - player_sprite_y
direction = pygame.math.Vector2(dx, dy).normalize()
bullet = {'x': player_sprite_x+42, 'y': player_sprite_y, 'direction': direction}
all_bullets.append(bullet)
An other option would be to ensure that a certain amount of time is passed between 2 clicks. Use pygame.time.get_ticks() to get the current time in milliseconds. When a new bullet has been spawned, then compute the time when the next bullet is allowed to be spawned.
Define the minimum time spawn between 2 bullets and init the time point for the 1st bullet by 0:
bullet_delay = 500 # 0.5 seconds
next_bullet_time = 0
Get the current time in the application loop:
current_time = pygame.time.get_ticks()
On click, verify of the current time is grater than next_bullet_time. If the condition is fulfilled, then spawn the bullet and compute the time point for the next bullet:
if event.button == 1 and current_time > next_bullet_time:
next_bullet_time = current_time + bullet_delay
e.g.:
bullet_delay = 500 # 0.5 seconds
next_bullet_time = 0
while exec:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1 and current_time > next_bullet_time:
next_bullet_time = current_time + bullet_delay
dx = event.pos[0] - (player_sprite_x+ player_sprite_w//2)
dy = event.pos[1] - player_sprite_y
direction = pygame.math.Vector2(dx, dy).normalize()
bullet = {'x': player_sprite_x+42, 'y': player_sprite_y, 'direction': direction}
all_bullets.append(bullet)
I am currently coding a simple computer game for a school coursework project and have encountered an issue in pygame. In my game, the player simply has to shoot at targets which fly through the air, almost a reverse space invaders. My current issue is that I can not have two shapes in the arena at once without one of them flickering and lagging. Below is my code, any help is welcomed. Cheers.
Also, does anyone know how I can add delay between each drawing being drawn. As I insinuated above, I aim to have targets fairly space out without overlaps but I do want multiple on the screen at the same time. Cheers.
import pygame
#Setting window dimensions and caption (Module 1)
pygame.init()
window = pygame.display.set_mode((800, 575))
pygame.display.set_caption("TARGET PRACTICE")
#Colour variables (Module 1)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)
#Target coordinates and dimensions (Module 3)
#target_x = 0
#target_y = 80
#target_w = 60
#target_h = 40
#target_v = 1
exec = True
class Target:
def __init__(self, x, y, h, w, v):
self.x = x
self.y = y
self.h = h
self.w = w
self.v = v
target_1 = Target(0, 80, 60, 40, 0.1)
target_2 = Target(0, 100, 60, 40, 0.1)
target_3 = Target(0, 50, 60, 40, 1)
clock = 0
while exec:
pygame.time.delay(1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exec = False
#Target Movement (Module 4)
window.fill(RED)
#Background and target drawing (Module 2)
target_1.x += target_1.v
pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
clock += 1
if clock%2 == 0:
target_2.x += target_2.v
pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))
pygame.display.update()
pygame.quit()```
target_2 is flashing, because it is just drawn in every 2nd frame. Change the position of target_2 in every 2nd frame, but draw it in every frame:
while exec:
# [...]
# update positions
target_1.x += target_1.v
if clock%2 == 0:
target_2.x += target_2.v
clock += 1
# clear window (fill in rED)
window.fill(RED)
# draw all the objects of the scene in every frame
pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))
# update display
pygame.display.update()
Note, the scene has to be redrawn in every frame. First the background is cleared filled window.fill(RED), then the entire scene has to be drawn and finally the display has to be updated (pygame.display.update()).
If you want to delay the target_2, then you have to draw and update the position after clock has reached a certain limit:
clock = 0
target_2_threshold = 500
while exec:
# [...]
# update positions
clock += 1
target_1.x += target_1.v
if clock > target_2_threshold and clock % 2 == 0:
target_2.x += target_2.v
# clear window (fill in rED)
window.fill(RED)
# draw all the objects of the scene in every frame
pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
if clock > target_2_threshold:
pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))
# update display
pygame.display.update()
I am writing a simple "game" and I have three questions for you:
How can I make all the balls moving independetly?
When I drag a ball with a mouse and click on the screen, how can i make the ball stay there. I want to draw it on that specific coordinate where the mouse key was pressed. It has to stay there all the time.
If a small ball touches the large one it shoud become a large one and dissapear after 10 seconds.
I have no idea how to do this. Can you please help me.
My code:
import pygame
import sys
from pygame.locals import *
import random
pygame.init()
width = 800
height = 600
fps = 25
clock = pygame.time.Clock()
black = (0, 0, 0)
white = (255, 255, 255)
display_window = pygame.display.set_mode((width, height))
pygame.display.set_caption('Bouncy')
game_over = False
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
x_cor = random.randint(15, width - 15)
y_cor = random.randint(15, height - 15)
x_change = random.randint(3, 7)
y_change = random.randint(3, 7)
coordinates = []
for i in range(10):
x = random.randint(0, width)
y = random.randint(0, height)
coordinates.append([x, y])
while not game_over:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == pygame.mouse.get_pressed():
pass
x_cor += x_change
y_cor += y_change
display_window.fill(white)
mouse_x, mouse_y = pygame.mouse.get_pos()
for coordinate in coordinates:
pygame.draw.circle(display_window, (r, g, b), (coordinate[0], coordinate[1]), 15, 0)
pygame.draw.circle(display_window, black, (mouse_x, mouse_y), 25, 0)
pygame.draw.circle(display_window, (r, g, b), (x_cor, y_cor), 15, 0)
if x_cor > (width - 15) or x_cor < 15:
x_change = x_change * -1
if y_cor > (height - 15)or y_cor < 15:
y_change = y_change * -1
clock.tick(fps)
pygame.display.update()
First and foremost, do the research required before you post here (see the help documents on the intro tour). There are many tutorials on the Internet, and many answered questions in SO (StackOverflow) that deal with moving objects. To get you started in general:
You move the balls independently by keeping a separate set of coordinates for each ball. On each iteration of the game clock, you have to reiterate the new coordinates of each ball.
To make a ball stay in one place, simply do not change its coordinates.
To change the size of a ball, draw it with a larger radius. This means that you also have to remember the radius of each ball. To give it a 10-second lifetime, keep a "lifespan" for each ball; decrement it on each tick of the game clock.
Bascially, you need a Ball object (make a class Ball); instantiate a new object for each ball you need. Write methods to change the position, size, and life span of each ball.