The goal of this program is to make a green circle bounce up and down on the screen in a loop. I have made it go down and back up again, but not to make it go down again.
import pygame, sys, time, random
from pygame.locals import *
from time import *
pygame.init()
windowSurface = pygame.display.set_mode((500, 400), 0, 32)
pygame.display.set_caption("Bounce")
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
info = pygame.display.Info()
sw = info.current_w
sh = info.current_h
y= 0
yy= sh
while True:
windowSurface.fill(BLACK)
pygame.draw.circle(windowSurface, GREEN , (250,y), 13, 0)
sleep(.006)
y+= 1
if y>sh:
pygame.draw.circle(windowSurface, GREEN , (250,yy), 13, 0)
sleep(.0001)
yy +=-1
if yy<-.00001:
y=0
y+= 1
pygame.draw.circle(windowSurface, GREEN , (250,y), 13, 0)
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
In your if yy < -.00001: block, I think you're trying to reset the state back to how it was at the beginning of the program. If that's the case, you forgot to set yy = sh.
In other words:
if yy<-.00001:
y=0
yy=sh # <- add this line
y+= 1
pygame.draw.circle(windowSurface, GREEN , (250,y), 13, 0)
In general though, I agree with halflings. This code is way too complicated. I'd suggest using a state variable to record whether the ball is moving up or down, then in the loop check that variable and either increment or decrement the position. When you get to the other end of the screen, swap the state variable to change the direction of the ball.
EDIT: Try this:
import pygame, sys, time, random
from pygame.locals import *
from time import *
pygame.init()
windowSurface = pygame.display.set_mode((500, 400), 0, 32)
pygame.display.set_caption("Bounce")
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
info = pygame.display.Info()
sw = info.current_w
sh = info.current_h
y = 0
# Initial direction is down
direction = 1
while True:
windowSurface.fill(BLACK)
pygame.draw.circle(windowSurface, GREEN , (250,y), 13, 0)
#print "Drawing at 250,", y
sleep(.006)
y += direction
if y >= sh:
# Changes the direction from down to up
direction = -1
elif y <= 0:
# Changes the direction from up to down
direction = 1
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Note: Hopefully this runs for you. I don't have pygame installed so I've only run it with the pygame stuff commented out and print calls substituted instead of draw commands. It works for me, anyway.
Your code seem way too complicated for the animation you're trying to do.
What you're looking for to simulate a "bouncing effect" may be the sin function (as it ossilates between -1 and 1) :
t = 0
speed = 0.01
maxHeight = 200
while True:
windowSurface.fill(BLACK)
pygame.draw.circle(windowSurface, GREEN , (250,y), 13, 0)
sleep(.006)
t += 1
y = int( ( sin(t*speed) + 1) * maxHeight / 2 )
pygame.draw.circle(windowSurface, GREEN , (250, y , 13, 0)
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Do not forget to put from math import sin at the top of your code.
If you're trying to achieve something realistic, you should probably use the speed and acceleration of the ball instead of using the 'sin' function to simulate a bouncing effect.
Use a while loop for your ball to bounce.
It should loop the code over and over again. What happens when it doesn't go down a second time? Does it throw an error? Does it just freeze?
A easy fix you can add is a counter variable so every time you ball changes directions the variable +=1 so after a set number of changes the program stops. Assuming thats what you want it to do.
Related
I'm following the programarcadegames website to try and move an object along with mouse movement. When I run the program, the coordinates of the moving mouse print out as it goes which is good, but the issue is that the item itself is constantly stuck in its starting position. I've tried making changes and running them to see what went wrong but the same thing keeps happening. Here is my code so far:
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GRAY = (128, 128, 128)
pygame.init()
star_list = []
for i in range(50):
x = random.randrange(0, 700)
y = random.randrange(0, 700)
star_list.append([x, y])
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Space Game")
# Loop until the user clicks the close button.
done = False
# Draw spaceship
def draw_spaceship(screen, x ,y):
#body
pygame.draw.rect(screen, GRAY, [350,375,20,40], 0)
#wing1 pygame.draw.polygon(screen, BLUE, [[350,375], [330,375], [350,400]], 0)
pygame.draw.polygon(screen, GRAY, [[390,375], [365,375], [365,400]], 0)
#wing2
pygame.draw.polygon(screen, GRAY, [[350,375], [330,375], [350,400]], 0)
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Game logic
# Mouse movement
pos = pygame.mouse.get_pos()
print (pos)
x=pos[0]
y=pos[1]
# Background
screen.fill(BLACK)
# Process each star in the list
for i in range(len(star_list)):
pygame.draw.circle(screen, WHITE, star_list[i], 2)
star_list[i][1] += 1
if star_list[i][1] > 700:
y = random.randrange(-50, -10)
star_list[i][1] = y
x = random.randrange(0, 700)
star_list[i][0] = x
#call draw_spaceship
draw_spaceship(screen, 0, 0)
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
Your draw_spaceship function draws the ship at a constant position. Draw the ship relative to the x and y coordiante:
def draw_spaceship(screen, x, y):
#body
pygame.draw.rect(screen, GRAY, [x-10, y-20, 20, 40], 0)
#wing1
pygame.draw.polygon(screen, GRAY, [[x+30,y-20], [x+10,y-20], [x+10,y+5]], 0)
#wing2
pygame.draw.polygon(screen, GRAY, [[x-10,y-20], [x-30,y-20], [x-10,y+5]], 0)
Call draw_spaceship with the current mouse position, instead of (0, 0):
while not done:
# [...]
#draw_spaceship(screen, 0, 0)
draw_spaceship(screen, pos[0], pos[1])
draw_spaceship is drawing your ship at a constant position, (0,0). You should change the call for that to something more like
draw_spaceship(screen, pos[0], pos[1])
Edit: It looks like your draw_spaceship() function has hardcoded values for where to draw the spaceship, without even using the x and y arguments given.
When I left click, a line should show from the origin, and if left clicked with two seconds, white circles should appear. After two seconds, another line is drawn and then after two seconds the previous line should disappear. Right now, when I click, a line shows from the origin and then when I click again, two lines show.
from pygame import *
import random
init()
size = width, height = 700, 700
screen = display.set_mode(size)
button = 0
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
color = RED
mx = 0
my = 0
cx = 0
cy = 0
def drawScene(screen, button):
if button == 1:
draw.circle(screen, RED, (mx,my), 5)
draw.line(screen, color, (mx,my),(lx,ly), 2)
cx = lx
cy = ly
draw.circle(screen, RED, (mx,my), 5)
display.flip()
if button == 3:
draw.line(screen, color, (mx,my),(lx,ly), 2)
draw.circle(screen, color, (lx,ly), 5)
display.flip()
running = True
myClock = time.Clock()
# Game Loop
while running:
lx = mx
ly = my
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT:
running = False
if evnt.type == MOUSEBUTTONDOWN:
mx,my = evnt.pos
button = evnt.button
if time.get_ticks() <= 2000 and time.get_ticks() > 0 :
draw.circle(screen, WHITE, (mx,my), 5)
else:
draw.line(screen, WHITE, (cx,cy),(lx,ly), 2)
if button == 3:
if color == RED:
color = BLUE
elif color == BLUE:
color = GREEN
elif color == GREEN:
color = RED
drawScene(screen, button)
myClock.tick(60)
quit()
Lets start with setting up a basic window first
from pygame import *
import random
init()
size = width, height = 700, 700
screen = display.set_mode(size)
button = 0
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
color = RED
running = True
myClock = time.Clock()
def drawScene():
screen.fill(BLACK)
display.update() #update is the same as flip()
# Game Loop
while running:
myClock.tick(60)
drawScene()
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT:
running = False
After helping someone else with this problem (the question i linked), i found that using lists would be the best idea
So lets create a list for the points where the circles go and lines connect to
points = [] #put this before the drawScene function so it can reference it
Now, when the user clicks, we want to add the point to the list and draw it on the screen
def drawScene():
screen.fill(BLACK)
for point in points:
draw.circle(screen,color,point,5)
display.update() #update is the same as flip()
if evnt.type == MOUSEBUTTONDOWN:
points.append(evnt.pos)
now we can create points on the screen by clicking. Lets create the lines
We want to start at the origin so add the origin to the list at the start
points = [(0,0)]
Now we want to loop through every point and draw a circle and a line in between. so change the loop to
for i in range(1,len(points)): #loop through all but the first point as you dont want circle at origin
draw.circle(screen,WHITE,points[i],5)
draw.line(screen,color,points[i - 1],points[i])
Now we can draw lines and circles. But we only want to draw the circles if we clicked within 2 seconds, so lets create a timer, we will make one for each line so lets make a list as each line disappears after 2 seconds aswell
timers = []
Once we click, we want to start the timer, we can do that with
if evnt.type == MOUSEBUTTONDOWN:
points.append(evnt.pos)
timers.append(time.get_ticks())
this gets the current time in milliseconds we want to know once its been 2 seconds so if we get the current time and minus the start time, we get the difference so
for i in range(len(timers)-1,-1,-1):
if time.get_ticks() - timers[i] > 2000: #if been 2 seconds
del timers[i] #delete the timer
del points[i + 1] #delete the point for the line
this gets pretty close after 2 seconds the new line moves to the origin, to fix this, we need to delete the origin point
del points[i]
but now after the lines disappear, it starts at the last place clicked instead of the origin. so lets check if there is no lines, make sure the origin is the first point
if len(points) == 1:
points[0] = (0,0)
Awesome, the last thing is the circles appearing within the 2 seconds, which also means more than 1 line so
if points[0] != (0,0) or len(points) > 2:
draw.circle(screen,WHITE,points[i],5)
Here is the full code:
from pygame import *
import random
init()
size = width, height = 700, 700
screen = display.set_mode(size)
button = 0
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
color = RED
running = True
myClock = time.Clock()
points = [(0,0)]
timers = []
def drawScene():
screen.fill(BLACK)
for i in range(1,len(points)): #loop through all but the first point as you dont want circle at origin
if points[0] != (0,0) or len(points) > 2:
draw.circle(screen,WHITE,points[i],5)
draw.line(screen,color,points[i - 1],points[i])
for i in range(len(timers)-1,-1,-1):
if time.get_ticks() - timers[i] > 2000: #if been 2 seconds
del timers[i] #delete the timer
del points[i] #delete the point for the line
if len(points) == 1:
points[0] = (0,0)
display.update() #update is the same as flip()
# Game Loop
while running:
myClock.tick(60)
drawScene()
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT:
running = False
if evnt.type == MOUSEBUTTONDOWN:
points.append(evnt.pos)
timers.append(time.get_ticks())
I am a beginner for learning Python and I just ran into a problem when I debug a series of codes I copied from a book, and I get a white screen window instead of one with pattern, here is the code:
import pygame, sys, random
import pygame.locals as GAME_GLOBALS
import pygame.event as GAME_EVENTS
pygame.init()
windowWidth = 640
windowHeight = 480
surface = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption('Pygame Shapes!')
while True:
surface.fill((200, 0, 0))
pygame.draw.rect(surface, (255, 0, 0), (random.randint(0, windowWidth), random.randint(0, windowHeight), 10, 10))
greenSquareX = windowWidth / 2
greenSquareY = windowHeight / 2
while True:
surface.fill((0, 0, 0))
pygame.draw.rect(surface, (0, 255, 0),
(greenSquareX, greenSquareY, 10, 10))
greenSquareX += 1
# greenSquareY += 1
pygame.draw.rect(surface, (0, 0, 255),
(blueSquareX, blueSquareY, 10, 10))
blueSquareX = 0.0
blueSquareY = 0.0
blueSquareVX = 1
blueSquareVy = 1
while True:
surface.fill((0, 0, 0))
pygame.draw.rect(surface, (0, 0, 255),
(blueSquareX, blueSquareY, 10, 10))
blueSquareX += blueSquareVX
blueSquareY += blueSquareVY
blueSquareVX += 0.1
blueSquareVY += 0.1
for event in GAME_EVENTS.GET():
if event.type == GAME_GLOBALS.QUIT:
pygame.quit()
sys.exit()
pygame.dispaly.update()
And the first error I got was: E1101:Module 'pygame' has no 'init' member'(4 ,1). I have ran other Python code with pygame.init() before, and the result turned out well; but this time I get a white screen window. What is wrong with my code? Thanks for help!!
This took me a great deal of debugging to fix, haha.
First of all, you are not escaping or updating in any of your while loops. Once the code enters your first while loop, nothing (the pygame.display) ever updates after that – resulting in your white-screen syndrome.
In addition, please name your variables consistently and check for typos in your code. You created a blueSquareVy variable only to try to refer to it as blueSquareVY later, and you misspelled pygame.display.update() at the end of the code. Capitalization matters – and that's just a few of the typos!
There are also logical errors within the code. You should not fill your window surface after your graphics have been drawn onto the screen. Looking at your variables, it seems that you would like the little squares to move. You would create the position variables outside of the while loop, as if you create them within the loop, they get recreated at their initial value every iteration of the loop.
The annotated and bugfixed code:
import pygame, sys, random
import pygame.locals as GAME_GLOBALS
import pygame.event as GAME_EVENTS
pygame.init()
windowWidth = 640
windowHeight = 480
surface = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption('Pygame Shapes!')
# Renamed variables to be consistent
# Moved variables out of the while loop
greenSquareX = windowWidth / 2
greenSquareY = windowHeight / 2
blueSquareX = 0.0
blueSquareY = 0.0
blueSquareVX = 1
blueSquareVY = 1
# Joined the two while loops into one
while True:
surface.fill((200, 0, 0))
pygame.draw.rect(surface, (255, 0, 0), (random.randint(0, windowWidth), random.randint(0, windowHeight), 10, 10))
surface.fill((0, 0, 0))
pygame.draw.rect(surface, (0, 255, 0),
(greenSquareX, greenSquareY, 10, 10))
greenSquareX += 1
greenSquareY += 1
pygame.draw.rect(surface, (0, 0, 255),
(blueSquareX, blueSquareY, 10, 10))
blueSquareX += blueSquareVX
blueSquareY += blueSquareVY
blueSquareVX += 0.1
blueSquareVY += 0.1
# Do not capitalize the .get() method for pygame.event class
for event in GAME_EVENTS.get():
if event.type == GAME_GLOBALS.QUIT:
pygame.quit()
sys.exit()
# Misspelled pygame.display
pygame.display.update()
Hope this helped!
I am having a problem where i am trying to get a circle to go to the same spot every time i execute the program. But each time I run the code, the dot doesn't always line up. I have a test circle in the same place to compare run to run. The Red circle should cover the white circle perfectly but it changes every time i run the program. I am reseting the kernal as i am using pygame.time.get_ticks() to time everything.
import sys, pygame, math
from pygame.locals import *
# set up a bunch of constants
BLUE = ( 0, 0, 255)
WHITE = (255, 255, 255)
ORANGE = (255, 165, 0)
PINK = (255, 20, 147)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
LIMEGREEN = ( 50, 205, 50)
YELLOW = (255, 255, 0)
PURPLE = (160, 32, 240)
BLACK = ( 0, 0, 0)
#Background Colour
BGCOLOR = BLACK
#Setting Window Size and finding window x and y centre
WINDOWWIDTH = 1918# width of the program's window, in pixels 960x540
WINDOWHEIGHT = 1078# height in pixels
WIN_CENTERX = int(WINDOWWIDTH / 2) # the midpoint for the width of the window
WIN_CENTERY = int(WINDOWHEIGHT / 2) # the midpoint for the height of the window
# frames per second to run at
FPS = 60
#intializing Variables
AMPLITUDE = 450
colourArray=[BLUE,WHITE,YELLOW,GREEN,RED,PINK,PURPLE,LIMEGREEN,ORANGE]
i=0
xPos = 0
step = 0
small_step =0
stop_step=step=0
xPos=0
yPos=0
c=RED
timestep=0
# standard pygame setup code
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT),pygame.FULLSCREEN)
pygame.display.set_caption('Task1')
fontObj = pygame.font.Font('freesansbold.ttf', 16)
# main application loop
while True:
# event handling loop for quit events
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
#setup for label and time
tempTime=pygame.time.get_ticks()/1000
time_string=str(tempTime)
instructionsSurf = fontObj.render(time_string, True, WHITE, BGCOLOR)
instructionsRect = instructionsSurf.get_rect()
instructionsRect.left = 10
instructionsRect.bottom = WINDOWHEIGHT - 10
# fill the screen to draw from a blank state
DISPLAYSURF.fill(BGCOLOR)
DISPLAYSURF.blit(instructionsSurf, instructionsRect)
tempTime=pygame.time.get_ticks()/1000
#Color change loop
c=RED
if (0<=(tempTime)<3):
c=RED
if (3<=(tempTime)<5):
c=BLUE
if (5<=(tempTime)<7):
c=GREEN
if (7<=(tempTime)<9):
c=YELLOW
if (9<=(tempTime)<11):
c=WHITE
if (11<=(tempTime)<17):
c=RED
if (17<=(tempTime)<42):
c=RED
if (42<=(tempTime)<46):
c=RED
if (46<=(tempTime)<120):
c=colourArray[i]
#Setting position of x and y coordinates
if (0<=(tempTime)<14):
xPos = 0
yPos = 0
if (14<(tempTime)<17):
small_step += 5.111
xPos = small_step
yPos = 0
if (17<(tempTime)<43):
step += 0.05001
step %= 2 * math.pi
xPos = math.cos(step) * AMPLITUDE
yPos = math.sin(step) * AMPLITUDE
if (43<(tempTime)<46):
stop_step=step
xPos = math.cos(stop_step) * AMPLITUDE
yPos = math.sin(stop_step) * AMPLITUDE
if (46<(tempTime)<120):
step += 0.05001
step %= 2 * math.pi
xPos = math.cos(step) * AMPLITUDE
yPos = math.sin(step) * AMPLITUDE
#test dot
pygame.draw.circle(DISPLAYSURF, WHITE, (WIN_CENTERX+AMPLITUDE, 0+WIN_CENTERY),12,0)
# draw dot1
dot1=pygame.draw.circle(DISPLAYSURF, c, (int(xPos)+ WIN_CENTERX, int(yPos) + WIN_CENTERY), 12,0)
# draw dot2
dot2=pygame.draw.circle(DISPLAYSURF, BLACK, (int(xPos) + WIN_CENTERX, int(yPos) + WIN_CENTERY), 6,0)
#refresh
pygame.draw.rect(DISPLAYSURF, BLACK, (0, 0, WINDOWWIDTH, WINDOWHEIGHT), 1)
pygame.display.update()
FPSCLOCK.tick(FPS)
I've only scanned your code but I would guess your inconsistency is due to a high frame rate (60). FPSCLOCK.tick(FPS) will make sure you go up to 60, but does not mean you will go 60 fps. So if your computer can not handle 60 frames per second, it will go below 60 frames.
Cristph Terasa's recommendation of using busy_loop should do the job for ya, but I personally have no experience for it and want to share a method of normalizing game speed across different FPSs.
Rather than reinventing a wheel, here's a link to a question that explains it. I recommend the second answer, written by pmoleri.
In Pygame, normalizing game-speed across different fps values
This solution should help your game run at the same speed no matter the frame rate.
So I am trying to move this random jumble of two polygons, a circle, and a line across the screen, any direction, and when it reaches the end of the screen is is placed back on the screen and moves again. Simply put, I want to move those shapes across the screen. I cannot really figure out how, I am new to pygame so all this is a bit confusing but this is what I have so far.
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
windowSurface = pygame.display.set_mode((500, 400), 0, 32)
pygame.display.set_caption("Paint")
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
windowSurface.fill(WHITE)
info = pygame.display.Info()
sw = info.current_w
sh = info.current_h
x = y = 0
dx = 5
dy = 2
while True:
pygame.draw.polygon(windowSurface,BLUE,((0+x,250+y),(120+x,120+y),(55+x,55+y)))
pygame.draw.polygon(windowSurface,RED,((0+x,150+y),(85+x,85+y),(100+x,175+y),(0+x,150+y)))
pygame.draw.line(windowSurface,BLACK,(60+x,85+y), (120+x, 110+x), 6)
pygame.draw.circle(windowSurface, GREEN , (75+x,100+y), 13, 0)
x += dx
y += dy
if x - dx < 0 or x + dx > sw:
dx = -dx
if y - dy < 0 or y + dy > sh:
dy = -dy
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
You probably want to clear the screen each time you redraw.
while True:
windowSurface.fill(WHITE) #This clears the screen on each redraw
pygame.draw.polygon(windowSurface,BLUE,((0+x,250+y),(120+x,120+y),(55+x,55+y)))
pygame.draw.polygon(windowSurface,RED,((0+x,150+y),(85+x,85+y),(100+x,175+y),(0+x,150+y)))
pygame.draw.line(windowSurface,BLACK,(60+x,85+y), (120+x, 110+y), 6)
pygame.draw.circle(windowSurface, GREEN , (75+x,100+y), 13, 0)
Also, look at the coordinates for the line. I have changed the endpoint to
(120+x, 110+y)
And if you change your edge detection to this your shapes will mostly stay in the window
if x < 0 or x > sw-120:
dx = -dx
x += dx
if y < -85 or y > sh-175:
dy = -dy
y += dy