I am trying to get the ball object to bounce around inside the screen, I have been testing different things for hours, looking at other pong game source code and other questions on here but I just can't seem to figure it out. Could someone give some pointers on where to start? Should I make separate functions for the different movements?
# ----- Game Loop ----- #
# Setting the loop breakers
game_exit = False
# ball positon/velocity
ball_x = DISP_W/2
ball_y = DISP_H/2
velocity = 5
# Game loop
while not game_exit:
# Gets all events
for event in pygame.event.get():
# Close event
if event.type == pygame.QUIT:
# Closes game loop
game_exit = True
# Background fill
GAME_DISP.fill(black)
# Setting positions
ball.set_pos(ball_x, ball_y)
# ceil.set_pos(0, 0)
# floor.set_pos(0, DISP_H - boundary_thickness)
ball_y += velocity
# Drawing sprites
ball_group.draw(GAME_DISP)
# collision_group.draw(GAME_DISP)
pygame.display.update()
# Setting FPS
clock.tick(FPS)
# ----- Game exit ----- #
pygame.quit()
quit()
FULL CODE: http://pastebin.com/4XxJaCvf
I would have a look at the pygame sprite class. It has a lot of handy methods to help with collisions and other stuff: https://www.pygame.org/docs/ref/sprite.html
Related
I am currently making a fighting game and was wondering how command inputs could be added. I understand it is kind of irrelevant and many substitutes are possible, but it would be nice to use familiar fighting game inputs.
I currently have something like this:
keys = pygame.key.get_pressed()
if keys[pygame.K_DOWN]:
commandcount +=1
if commandcount > 0 and commandcount < 30 and keys[pygame.K_RIGHT] and keys[pygame.K_z]:
player1.projectile = True
The "commandcount" helps keep the window of action available until a certain amount of time.
The main problem with this is that you could still press the inputs in whatever order and the projectile would still come out.
Thanks
Try using the pygame.KEYDOWN events instead of pygame.key.get_pressed() so the order can be observed. Use a list to keep track of the order of these KEYDOWN events. When the order matches a specific combo then execute the move and reset the list. The list also gets reset after a certain amount of time with a combo. I made an example program with the combo down, right, z activating a fireball.
import pygame
# pygame setup
pygame.init()
# Open a window on the screen
width, height = 600, 600
screen = pygame.display.set_mode((width, height))
def main():
clock = pygame.time.Clock()
black = (0, 0, 0)
move_combo = []
frames_without_combo = 0
while True:
clock.tick(30) # number of loops per second
frames_without_combo += 1
if frames_without_combo > 30 or len(move_combo) > 2:
print("COMBO RESET")
frames_without_combo = 0
move_combo = []
screen.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
move_combo.append(event.key) # Only keys for combos should be added
if move_combo == [pygame.K_DOWN, pygame.K_RIGHT, pygame.K_z]:
print("FIRE BALL")
frames_without_combo = 0
print(move_combo)
pygame.display.update()
main()
I tried different codes from here and other places but I just can't seem to get my end screen to work.
I've tried many times to transition to end screen but either the code fails completely or my sprites appear on top of the end screen. This is what I have right now because it allows my code to run.
collide = pygame.sprite.spritecollide(player, enemy_list, False)
if collide:
run = False
I want it to be game over when the enemy sprite touches the player sprite but because of the codes above which makes the enemy sprite follow the player sprite, an error always appears: "float division 0". It's probably just my fault for using the wrong code though.
I'm not sure if the other codes affect the end screen codes but just in case, this is my entire code:
Code is removed for now. Will re-upload in 1 to 2 months
Add a gameover state to the program and set the state when the player collides.
Create a separate function for the game over screen. The gameover function has its own event loop:
def gameOverScreen():
global run, gameover
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
# do event handling which continues the game
# [...]
# if [...]
# gameover = False
# draw the game over screen
# [...]
pygame.display.flip()
clock.tick(100)
Call this function dependent on the state of gameover in the main loop.
Use the continue stement to contiunue the main loop immediately.
gameover = False
run = True
while run:
# [...]
if not gameover and time_difference >= 1500:
# [...]
win.fill(white)
win.blit(background.image, background.rect)
if not pygame.mixer.music.get_busy():
pygame.mixer.music.load('bgm.mp3')
pygame.mixer.music.play()
if gameover:
gameOverScreen()
continue # continue main loop
for e in enemy_list:
e.move(player)
collide = pygame.sprite.spritecollide(player, enemy_list, False)
if collide:
gameover = True
# [...]
I am trying to make a game in Pygame where he objective is to start the game but the start button keeps moving whenever you touch it but the window will not respond. I am not finished with the code yet because I tested it and it didn't work. Here is my code so far:
import pygame
import random
import time
pygame.init()
display = pygame.display.set_mode((800,600))
pygame.display.set_caption('BEST 3D PLATFORMER FPS GAME!')
clock = pygame.time.Clock()
pygame.display.update()
clock.tick(60)
display.fill((255,255,255))
def newposition()
randx = random.randrange(100, 700)
randy = random.randrange(100,500)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pass
if event.ty
button = pygame.image.load('start.png')
display.blit(button,(randx,randy))
pygame.quit()
quit()
All comments inside code
import pygame
import random
# --- constants --- (UPPER_CASE names)
WHITE = (255, 255, 255) # space after every `,`
FPS = 30
# --- classes --- (CamelCase names)
#empty
# --- functions --- (lower_case names)
def new_position():
x = random.randrange(100, 700) # space after every `,`
y = random.randrange(100, 500) # space after every `,`
return x, y # you have to return value
# --- main --- (lower_case names)
# - init -
pygame.init()
display = pygame.display.set_mode((800, 600)) # space after every `,`
pygame.display.set_caption('BEST 3D PLATFORMER FPS GAME!')
# - objects -
# load only once - don't waste time to load million times in loop
button = pygame.image.load('start.png').convert_alpha()
button_rect = button.get_rect() # button size and position
button_rect.topleft = new_position() # set start position
# - mainloop -
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
#pass # it does nothing so you can't exit
running = False # to exit `while running:`
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False # to exit `while running:`
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left button
button_rect.topleft = new_position() # set new position
# if event.ty # Syntax Error
# - updates (without draws) -
#empty
# - draws (without updates) -
# you have to use it inside loop
display.fill(WHITE) # clear screeen before you draw elements in new place
display.blit(button, button_rect)
# you have to use it inside loop
pygame.display.update() # you have to send buffer to monitor
# - FPS -
# you have to use it inside loop
clock.tick(FPS)
# - end -
pygame.quit()
BTW: simple template which you can use when you start new project.
PEP 8 -- Style Guide for Python Code
I had a similar issue, the fix is not straight forward. Here are my notes for python 3.6.1 and Pygame 1.9.3:
1) The event is unresponsive because there is no display generated for pygame, add a window display after pygame initialization:
pygame.init() # Initializes pygame
pygame.display.set_mode((500, 500)) # <- add this line. It generates a window of 500 width and 500 height
2) pygame.event.get() is a generates a list of event but not all event classes have .key method for example mouse motion. Thus, change all .key event handling codes such as
if event.key == pygame.K_q:
stop = True
To
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
stop = True
3) In some mac/python combinations even after the window is generated it doesn't focus / record keyboard events, this is a pygame issue and is fixed in a reimplementation of pygame using sdl2 (SDL is a cross-platform development library which provides low level access to keyboard, audio ,mouse etc). it can be installed by following the instructions here https://github.com/renpy/pygame_sdl2. One might need to install homebrew for it, which is another package manager for macOS. Instructions can be found here https://brew.sh/
4) after installing it using the instructions on github link you need to change all import pygame to import pygame_sdl2 as pygame
5) Voila! fixed ...
You've got to load button outside the loop (it only needs to be done once.)
button = pygame.image.load('start.png')
Also, you have defined newposition(), but have not called it. Also, randx and randy would not be accessible from outside of the function, because the would be local to it.
So, change your function to this :
def newposition()
randx = random.randrange(100, 700)
randy = random.randrange(100,500)
return randx, randy # Output the generated values
Then, before the loop :
rand_coords = newposition()
You simply forgot to update the pygame display with your modifications to it.
At the end of your loop, add pygame.display.update(), like this:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pass
# if event.ty why is that here?
display.blit(button,(rand_coords[0],rand_coords[1])) # Take our generated values
pygame.display.update()
Final code :
import pygame
import random
import time
pygame.init()
display = pygame.display.set_mode((800,600))
pygame.display.set_caption('BEST 3D PLATFORMER FPS GAME!') # Yeah, exactly :)
clock = pygame.time.Clock()
display.fill((255,255,255))
def newposition()
randx = random.randrange(100, 700)
randy = random.randrange(100,500)
return randx, randy # Output the generated values
rand_coords = newposition() # Get rand coords
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # Quit pygame if window in closed
# if event.ty why is that here?
clock.tick(60) # This needs to be in the loop
display.fill((255,255,255)) # You need to refill the screen with white every frame.
display.blit(button,(rand_coords[0],rand_coords[1])) # Take our generated values
pygame.display.update()
Hello I am trying to create towers for my Tower Defense game but every time i select a new tower the old one gets removed. I do not want this to be removed and I am sure there is a simple way to do this but I cannot find it. Here is my code. Thank you for any help.
def displayTower():
global bx, by
click = pygame.mouse.get_pressed()
Background.blit(redTower, (mx-bx,my-by))
Background.blit(redTower, (530,650))
while intro == 1:
mousePos = pygame.mouse.get_pos()
mousePressed = pygame.mouse.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if 530 < mousePos[0] < 590 and 650 < mousePos[1] < 710:
if mousePressed[0] == 1:
clicked = True
if clicked == True:
mx, my = pygame.mouse.get_pos()
bx = 30
by = 30
if mousePressed[0] == 0:
Background.blit(redTower, (mx-bx,my-by))
tx = mx - bx
ty = my - by
clicked = False
displayTower()
For one thing, you are calling displayTower() outside of a while loop, so it never gets executed. So you are blitting only one tower at a time, not two.
You each time have to blit all the screen or blit a portion of it and update only the rects affected by the change.
Yes, what you blitted should stay on, but you cannot count on it without proper updating when you wish.
To be secure, you should use internal surface, then blit it over the screen surface when you are done blitting and drawing. Anyway, what should the background variable contain? A screen or your surface?
So the second thing is that you never update the screen. You have to use either pygame.display.flip() or pygame.display.update().
And, do use events to get mouse position, it's more clever. Also add a sleep or pygame.time.clock() to regulate fps, this is almost a busy loop what you wrote.
I'm starting out in python and pygame. so I have been introduced to screen.blit for showing pictures on the screen. however when I use screen.blit nothing will happen in my program unless I am moving my mouse or clicking a button. I have no idea why this happens, I have simplified an example with only a cat moving across the screen. Nothing happens unless I am pressing a button or moving my mouse. I am using python 2.6.6
import pygame
pygame.init()
# Set the width and height of the screen [width, height]
size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
floor = pygame.image.load("floor.png").convert()
cat = pygame.image.load("cat.png").convert()
a=0
b=0
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# --- Game logic should go here
a+=1
b+=1
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.blit(floor, [0,0])
screen.blit(cat, [a,b])
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
pygame.display.update()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
That's because the screen.blip is inside the for event in pygame.event.get():
Correct the indentation and it will be fixed.
Try this:
while not done:
# --- Main event loop
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
# --- Game logic should go here
a+=1
b+=1
# --- Drawing code should go here
# First, clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
screen.blit(floor, [0,0])
screen.blit(cat, [a,b])
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
pygame.display.update()
# --- Limit to 60 frames per second
clock.tick(60)