So I am new to pygame and I made a program that will make a ball bounce according to gravity, and it works perfectly but now I want to be able to make infinite of them by creating one wherever I click. I know how to get the coordinates of the click, but I don't know how to create multiple circles. Would I somehow use a function or a class? Here's my code, sorry if it's a little messy.
import pygame,random,time
pygame.init()
infoObject = pygame.display.Info()
side = pygame.display.Info().current_h
side = side - ((1.0/12)*(pygame.display.Info().current_h))
side = int(side)
screen = pygame.display.set_mode([side, side])
pygame.display.set_caption("")
clock = pygame.time.Clock()
done = False
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (250,30,25)
GREEN = (25, 240, 25)
YELLOW = (250,240,25)
FPS = 60
x=100
y=100
t=0
r=10
direction=0
count = 0
def faller(x,y,color,size):
pygame.draw.circle(screen,color,(x,y),size,0)
def reverse():
global t,direction
if direction == 0:
direction = 1
t=t*4/5
elif direction == 1:
direction = 0
t=1
while not done:
clock.tick(FPS)
events = pygame.event.get()
screen.fill(BLACK)
for event in events:
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
done = True
if direction==0:
t+=1
y+=int((9.8/FPS)*t)
elif direction==1:
t-=1
y-=int((9.8/FPS)*t)
if t==0:
reverse()
if y+r>side:
y=side-r
faller(x,y,RED,r)
reverse()
else:
faller(x,y,RED,r)
if y==side-r:
count+=1
else:
count=0
if count>=3:
done = True
pygame.display.flip()
pygame.quit()
I would encourage you to experiment with classes and methods. Once you have a class Ball, you can make a list of the Ball objects and process them all at once. You could then use the .append() list method to add a new Ball on mouse click.
I would suggest you use variables such as:
pos_x,
pos_y,
vel_x,
vel_y,
This will make things much easier to understand if you wanted to implement collisions. Dont forget to comment your code :)
Related
I am trying to create a flappy bird game with python but i cant get multiple walls to appear on the page and move across.
I was wondering if there was a way to make multiple walls (rectangles) and move them without defining them individually. Im using Pygame.
import pygame
pygame.init()
white = (255,255,255)
yellow = (255,200,0)
green = (0,255,0)
displayHeight = 600
displayWidth = 500
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
clock = pygame.time.Clock()
crash = False
def bird(b_X, b_Y, b_R, b_Colour):
pygame.draw.circle(gameDisplay, b_Colour, (b_X, b_Y), b_R)
def game_loop():
bX = 50
bY = 300
bR = 20
bColour = yellow
velocity = 0
gravity = 0.6
lift = -15
while crash == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.QUIT
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
velocity += lift
gameDisplay.fill(white)
bird(bX, bY, bR, bColour)
velocity = velocity + gravity
bY += velocity
bY = round(bY)
if bY > displayHeight:
bY = displayHeight
velocity = 0
if bY < 0:
bY = 0
velocity = 0
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
Is there a way to make a big population of blocks and move them individually without defining them one by one.
I do not know how the code exactly works out, but you can store multiple wall 'objects' in a list, and looping over that list every time you update the screen. In pseudocode, it works like this
wall-list = []
for wanted_wall_amount in range():
wall = create_a_wall
wall-list.append(wall)
game loop:
for wall in wall-list:
wall.x_coordinate += movespeed
because of the for loop within the game loop, every wall object you stored will update it's position, or whatever you want to move simultanously. I hope you understand the weird pseudocode
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
...
I've basically just started developing with PyGame and I am having trouble with the whole Sprite concept. I have been looking every where for guides on how to use it, I just can't seem to find any. I would like to know the basic concept of how it all works. This is the code I have been working on:
#!/usr/bin/python
import pygame, sys
from pygame.locals import *
size = width, height = 320, 320
clock = pygame.time.Clock()
xDirection = 0
yDirection = 0
xPosition = 32
yPosition = 256
blockAmount = width/32
pygame.init()
screen = pygame.display.set_mode(size)
screen.fill([0, 155, 255])
pygame.display.set_caption("Mario Test")
background = pygame.Surface(screen.get_size())
mainCharacter = pygame.sprite.Sprite()
mainCharacter.image = pygame.image.load("data/character.png").convert()
mainCharacter.rect = mainCharacter.image.get_rect()
mainCharacter.rect.topleft = [xPosition, yPosition]
screen.blit(mainCharacter.image, mainCharacter.rect)
grass = pygame.sprite.Sprite()
grass.image = pygame.image.load("data/grass.png").convert()
grass.rect = grass.image.get_rect()
for i in range(blockAmount):
blockX = i * 32
blockY = 288
grass.rect.topleft = [blockX, blockY]
screen.blit(grass.image, grass.rect)
grass.rect.topleft = [64, 256]
screen.blit(grass.image, grass.rect.topleft )
running = False
jumping = False
falling = False
standing = True
jumpvel = 22
gravity = -1
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
running = True
xRun = -5
elif event.key == K_RIGHT:
running = True
xRun = 5
elif event.key == K_UP or event.key == K_SPACE:
jumping = True
elif event.type == KEYUP:
if event.key == K_LEFT or event.key == K_RIGHT:
running = False
if running == True:
xPosition += xRun
if mainCharacter.rect.right >= width:
xPosition = xPosition - 10
print "hit"
running = False
elif mainCharacter.rect.left <= 0:
xPosition = xPosition + 10
print "hit"
running = False
screen.fill([0, 155, 255])
for i in range(blockAmount):
blockX = i * 32
blockY = 288
grass.rect.topleft = [blockX, blockY]
screen.blit(grass.image, grass.rect)
grass.rect.topleft = [64, 64]
screen.blit(grass.image, grass.rect.topleft )
if jumping:
yPosition -= jumpvel
print jumpvel
jumpvel += gravity
if jumpvel < -22:
jumping = False
if mainCharacter.rect.bottom == grass.rect.top:
jumping = False
if not jumping:
jumpvel = 22
mainCharacter.rect.topleft = [xPosition, yPosition]
screen.blit(mainCharacter.image,mainCharacter.rect)
clock.tick(60)
pygame.display.update()
basically I just want to know how to make these grass blocks into sprites in a group, so that when I add my player (also a sprite) I can determine whether or not he is in the air or not through the collision system. Can someone please explain to me how I would do this. All I am looking for is basically a kick starter because some of the documentation is quite bad in my opinion as it doesn't completely tell you how to use it. Any help is greatly appreciated :)
In Pygame, sprites are very minimal. They consist of two main parts: an image and a rect. The image is what is displayed on the screen and the rect is used for positioning and collision detection. Here's an example of how your grass image could be made into a Sprite:
grass = pygame.image.load("grass.png")
grass = grass.convert_alpha()
grassSprite = new pygame.sprite.Sprite()
grassSprite.image = grass
#This automatically sets the rect to be the same size as your image.
grassSprite.rect = grass.get_rect()
Sprites are pretty pointless on their own, since you can always keep track of images and positions yourself. The advantage is in using groups. Here's an example of how a group might be used:
myGroup = pygame.sprite.Group()
myGroup.add([sprite1,sprite2,sprite3])
myGroup.update()
myGroup.draw()
if myGroup.has(sprite2):
myGroup.remove(sprite2)
This code creates a group, adds three sprites to the group, updates the sprites, draws them, checks to see if sprite2 is in the group, then removes the sprite. It is mostly straight forward, but there are some things to note:
1) Group.add() can take either a single sprite or any iterable collection of sprites, such as a list or a tuple.
2) Group.update() calls the update methods of all the Sprites it contains. Pygame's Sprite doesn't do anything when its update method is called; however, if you make a subclass of Sprite, you can override the update method to make it do something.
3) Group.draw() blits the images of all the Group's Sprites to the screen at the x and y positions of their rects. If you want to move a sprite, you change its rect's x and y positions like so: mySprite.rect.x = 4 or mySprite.rect.y -= 7
One way to use Groups is to create a different group for each level. Then call the update and draw method of whichever group represents the current level. Since nothing will happen or be displayed unless those methods are called, all other levels will remain "paused" until you switch back to them. Here's an example:
levels = [pygame.sprite.Group(),pygame.sprite.Group(),pygame.sprite.Group()]
levels[0].add(listOfLevel0Sprites)
levels[1].add(listOfLevel1Sprites)
levels[2].add(listOfLevel2Sprites)
currentLevel = 0
while(True):
levels[currentLevel].update()
levels[currentLevel].draw()
I know this question is somewhat old, but I hope you still find it helpful!
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.
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed last month.
My goal is for my program to be able to detect collision when the ball sprite hits any one of the 'g_ball' sprites. The code apperently detects collision, and i have the "print" statement to test it...but it's CONSTANTLY printing "progress" even though none of the sprites are touching. Here is the code:
while 1:
screen.blit(background, (0,0))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_a:
m_x = -4
s+=1
elif event.key == K_d:
m_x = +4
s2+=1
if event.type == KEYUP:
if event.key == K_a:
m_x = 0
elif event.key == K_d:
m_x = 0
x+= m_x
y+= m_y
ball = pygame.sprite.Sprite()
ball.image = pygame.image.load('red_ball.png').convert()
ball.rect = ball.image.get_rect()
ball.image.set_colorkey((white))
screen.blit(ball.image,(x,y))
if x > 640:
x = 0
if x < 0:
x = 640
g_ball = pygame.sprite.Sprite()
g_ball.image = pygame.image.load('green_ball.png').convert()
g_ball.rect = g_ball.image.get_rect()
g_ball.image.set_colorkey(white)
screen.blit(g_ball.image,(50,t))
t+=5
if t > 521:
t = 0
collision = pygame.sprite.collide_rect(ball, g_ball)
if collision == True:
print ('PROGRESS!!!')
It's because you have no offset set for the collision, you have only passed the offset to screen.blit.
Your fixed code would be this:
...
ball.rect = ball.image.get_rect()
ball.rect.topleft = (x, y)
...
g_ball.rect = g_ball.image.get_rect()
g_ball.rect.topleft = (50, t)
...
nightcracker is right. Do you realize what you are doing in this loop (which is supposed to run as fast as possible)? you are creating 2 new balls, you load the image from hd, you place them to (0,0), and then you print them manually on screen at a given position. This last part means you display them somewhere, but not where they really are (you did set their real position with ball.rect=ball.image.get_rect()). They really are at (0,0), and are colliding all the time.
The way you blit them to screen isn't good, you should use a renderer. Anyway you should probably try some tutorials first, learn what is a Surface and what is a Sprite. Be careful of what you put inside the main loop (why do you create new balls all the time ? they could be created once at startup), your code will be prettier, and your FPS will increase