When I try multiprocessing, multiple windows show up - python

I'm trying to create a pong game for my first Pygame game. I'm very new to Pygame and relatively new to Python. So far I only have the two bumpers on either side. Here is the code I have so far:
import pygame, sys, os
from pygame.locals import *
from multiprocessing import Process
window = pygame.display.set_mode((600,400))
pygame.display.set_caption("Pong")
screen = pygame.display.get_surface()
pongBackground = pygame.image.load("C:/Users/LN/Desktop/PongBackground.png")
pongHitter = pygame.image.load("C:/Users/LN/Desktop/PongHitter.png")
pongHitter = pygame.image.load("C:/Users/LN/Desktop/PongHitter.png")
pongBall = pygame.image.load("C:/Users/LN/Desktop/PongBall.png")
pygame.init()
class hitter():
"""moves the pong hitter with arrow keys"""
def _init_(self):
screen.blit(pongBackground, (0,0))
self.position = pongHitter.get_rect()
pygame.display.update()
def goTo(self, coord):
screen.blit(pongHitter,coord)
self.position = self.position.move(coord)
pygame.display.update()
def moveUp(self):
for i in range(1):
screen.blit(pongBackground, self.position, self.position)
self.position = self.position.move(0, -1)
screen.blit(pongHitter, self.position)
pygame.display.update()
pygame.time.delay(10)
def moveDown(self):
for i in range(1):
screen.blit(pongBackground, self.position, self.position)
self.position = self.position.move(0, 1)
screen.blit(pongHitter, self.position)
pygame.display.update()
pygame.time.delay(10)
hitterA=hitter()
hitterB=hitter()
hitterA._init_()
hitterB._init_()
hitterA.goTo((5,200))
hitterB.goTo((590,200))
pygame.key.set_repeat(1,1)
contin=True
def inputLeft():
while True:
for event in pygame.event.get():
if pygame.key.get_pressed()[K_UP]:
hitterA.moveUp()
elif pygame.key.get_pressed()[K_DOWN]:
hitterA.moveDown()
elif pygame.key.get_pressed()[K_ESCAPE]:
sys.exit(0)
def inputRight():
while True:
for event in pygame.event.get():
if pygame.key.get_pressed()[K_w]:
hitterB.moveUp()
elif pygame.key.get_pressed()[K_s]:
hitterB.moveDown()
elif pygame.key.get_pressed()[K_ESCAPE]:
sys.exit(0)
if __name__=='__main__':
p = Process(target=inputLeft)
p.start()
p.join()
p2 = Process(target=inputRight)
p2.start()
p2.join()
Now I'm trying to get it so that both bumpers can move simultaneously. I've tried multiprocessing as you can see above, but it creates different window with each process. How can I get everything to display on one window? Thanks! By the way, this python 3.3.

multi processing is the wrong approach
give wasd to one hitter and the arrows keys to another then for youre keypress statments make it so that wasd moves one paddle and the arrows move the other
here is what your mainloop should look like instead of having two:
while True:
for event in pygame.event.get():
if pygame.key.get_pressed()[K_UP]:
hitterA.moveUp()
if pygame.key.get_pressed()[K_DOWN]:
hitterA.moveDown()
if pygame.key.get_pressed()[K_w]:
hitterB.moveUp()
if pygame.key.get_pressed()[K_s]:
hitterB.moveDown()
if pygame.key.get_pressed()[K_ESCAPE]:
sys.exit(0)
there is no need for multiprocessing it will work just fine without it
your code looks great but just get rid of the multiprocessing
here is a pretty good example of a pong game with pygame you can use it to help you out
Pygame Pong Example

Related

Problem with making Circle properly appear on screen in Pygame

I think my understanding of Pygame is a little bit weak. I would appreciate any help in general about the intricacies of the code (since this was given by the teacher) or simply how I can at least make the obstacle visible.
def draw(screen, background, boids, obstaclearray):
#redrawing the whole window
boids.clear(screen, background)
dirty = boids.draw(screen)
for element in obstaclearray:
pygame.draw.circle(screen, (255,255,255), (element.x, element.y), element.radius)
pygame.display.update(dirty)
Above is where I actually do the drawing and attempt to draw the circle.
The CircularObstacle class is a very simple class that looks like this:
import pygame
class CircularObstacle():
def __init__(self, x, y, radius): #MAYBE ADD A SIZE
self.x = x
self.y = y
self.radius = radius
The problem is that the circle only draws itself when the boids have went over it, which is really weird. I think it has to do with the way the pygame has been setup with and the Surfaces and everything, so below is all the code in main. Of course the obstacle does not work as intended, but I plan to fix that later, first I want to at least get a circle to show.
Below is my full code because I believe it is crucial to solving the issue:
import pygame
from pygame.locals import *
import argparse
import sys
from boid import Boid
from Obstacle import CircularObstacle
def add_boids(boids,num_boids):
for boid in range (num_boids):
boids.add(Boid())
def update(dt, boids):
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit(0)
elif event.type == KEYDOWN:
mods = pygame.key.get_mods()
if event.key == pygame.K_q:
# quit
pygame.quit()
sys.exit(0)
elif event.key == pygame.K_UP:
# add boids
if mods & pygame.KMOD_SHIFT:
add_boids(boids, 100)
else:
add_boids(boids, 10)
elif event.key == pygame.K_DOWN:
# remove boids
if mods & pygame.KMOD_SHIFT:
boids.remove(boids.sprites()[:100])
else:
boids.remove(boids.sprites()[:10])
#ADD STUFF LIKE THE SLIDER AND STUFF
for b in boids:
b.update(dt, boids)
def draw(screen, background, boids, obstaclearray):
#redrawing the whole window
boids.clear(screen, background)
dirty = boids.draw(screen)
for element in obstaclearray:
pygame.draw.circle(screen, (255,255,255), (element.x, element.y), element.radius)
pygame.display.update(dirty)
default_boids = 0
default_geometry = "1000x1000"
# Initialise pygame.
pygame.init()
pygame.event.set_allowed([pygame.QUIT, pygame.KEYDOWN, pygame.KEYUP])
# keep a good framerate so the graphics are better
fps = 60.0
fpsClock = pygame.time.Clock()
# Set up pygamme window
window_width, window_height = 800,600
flags = DOUBLEBUF
screen = pygame.display.set_mode((window_width, window_height), flags)
screen.set_alpha(None)
background = pygame.Surface(screen.get_size()).convert()
background.fill(pygame.Color('black'))
boids = pygame.sprite.RenderUpdates()
add_boids(boids, default_boids)
obstaclearray = []
defaultcircleobstacle = CircularObstacle(200,200,13)
obstaclearray.append(defaultcircleobstacle)
#The "game loop"
dt = 1/fps # here dt means the amount of time elapsed since the last frame
#it seems like thie is a forever loop but in reality this is not since in the update method we provide functinality to quit the program
while True:
update(dt, boids)
draw(screen, background, boids, obstaclearray)
dt = fpsClock.tick(fps)
When you call pygame.display.update() you have 2 options. You can call it without any parameter. In this case the complete screen is updated.
pygame.display.update()
Or call it with a list of rectangular regions that need to be updated. In this case, only the rectangular areas will be updated.
pygame.display.update(rect_list)
You do the 2nd option, but the areas where the circles are drawn are not in the dirty list, therefore this regions are not updated.
pygame.display.update(dirty)
Either update the whole screen with pygame.display.update() or add the regions of the circles to the dirty list:
def draw(screen, background, boids, obstaclearray):
boids.clear(screen, background)
dirty = boids.draw(screen)
for element in obstaclearray:
dirty_rect = pygame.draw.circle(screen, (255,255,255), (element.x, element.y), element.radius)
dirty.append(dirty_rect)
pygame.display.update(dirty)

How to integrate 'MENU' code for my game with the actual gaming code?

I have created a basic game. Now I want to expand on the basic game and add a video game menu to it. I have two programs:
Basic game code
MENU code
I want to integrate both codes into one so that my game becomes more functional. I am just a beginner and need directions on how to do that. Thanks for helping.
BASIC GAME CODE:
import pygame
import random
import sys
pygame.init()
w=800
h=600
red=(251,63,75)
blue=(104,41,171)
yellow=(255,255,0)
player_size=25
player_pos=[w/2,h-(2*player_size)]
enemy_size=25
enemy_pos=[random.randint(0,w-enemy_size),0]
enemy_list=[ ]
bg_color=(0,0,0)
screen=pygame.display.set_mode((w,h))
game_over=False
speed=10
score=0
clock=pygame.time.Clock()
myFont=pygame.font.SysFont("monospace",35)
def set_level(score,speed):
if score<10:
speed=5
elif score<20:
speed=6
elif score<30:
speed=8
elif score<40:
speed=10
elif score<50:
speed=13
elif score<200:
speed=15
else:
speed=20
return speed
def drop_enemies(enemy_list):
delay=random.random()
if len(enemy_list)<6 and delay<0.1:
x_pos=random.randint(0,w-enemy_size)
y_pos=0
enemy_list.append([x_pos,y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,blue,
(enemy_pos[0],enemy_pos[1],enemy_size,enemy_size))
def update_enemy_pos(enemy_list,score):
for idx,enemy_pos in enumerate(enemy_list):
if enemy_pos[1]>=0 and enemy_pos[1]<h:
enemy_pos[1]+=speed
else:
enemy_list.pop(idx)
score+=1
return score
def detect_collision(player_pos,enemy_pos):
p_x=player_pos[0]
p_y=player_pos[1]
e_x=enemy_pos[0]
e_y=enemy_pos[1]
if (e_x>=p_x and e_x<(p_x+player_size)) or (p_x>=e_x and p_x<(e_x+enemy_size)):
if (e_y>=p_y and e_y<(p_y+player_size)) or (p_y>=e_y and p_y<(e_y+enemy_size)):
return True
return False
def collision_check(enemy_list,player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos,player_pos):
return True
return False
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
if event.type==pygame.KEYDOWN:
x=player_pos[0]
y=player_pos[1]
if event.key==pygame.K_LEFT:
x-=player_size
elif event.key==pygame.K_UP:
y-=player_size
elif event.key==pygame.K_RIGHT:
x+=player_size
elif event.key==pygame.K_DOWN:
y+=player_size
player_pos=[x,y]
screen.fill(bg_color)
drop_enemies(enemy_list)
score=update_enemy_pos(enemy_list,score)
speed=set_level(score,speed)
text='Your Score is:' + str(score)
label=myFont.render(text,1,yellow)
screen.blit(label,(w/2,h-40))
if collision_check(enemy_list,player_pos):
game_over=True
break
draw_enemies(enemy_list)
pygame.draw.rect(screen,red,
(player_pos[0],player_pos[1],player_size,player_size))
clock.tick(30)
pygame.display.update()
pygame.display.flip()
GAME MENU CODE:
import pygame
import random
import sys
pygame.init()
w=800
h=600
bg_color=(34,139,34)
red=(255,0,0)
blue=(0,0,125)
bright_blue=(0,0,255)
font_size=35
b1_pos=[w/2-50,h/2]
b1_size=[105,50]
screen=pygame.display.set_mode((w,h))
myFont=pygame.font.SysFont("freesansbold.tff",font_size)
def button(b1_pos,b1_size):
mouse_pos=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
if (b1_pos[0]<mouse_pos[0]<(b1_pos[0]+b1_size[0])) and (b1_pos[1]<mouse_pos[1]<(b1_pos[1]+b1_size[1])):
pygame.draw.rect(screen,bright_blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
if click[0]==1:
print("Left click")
else:
pygame.draw.rect(screen,blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
text='START'
label=myFont.render(text,1,red)
screen.blit(label,(w/2-38,h/2+5))
game_over=False
while not game_over:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
screen.fill(bg_color)
button(b1_pos,b1_size)
pygame.display.update()
When creating a game you need something called The MainLoop. All the code that needs to be updated in every frame goes inside this loop. This loop runs forever until the game is terminated. Check these video tutorials and this
Let me give you an example:
import pygame
#Import literals such as QUIT
from pygame.locals import *
pygame.init()
w = 800
h = 600
screen = pygame.display.set_mode((w,h))
running = True
def MenuCode():
pass
def GameCode():
pass
#This is the Game Loop.
while running:
#Events are used to check if a key has
#been pressed or a mouse button or a mouse movement.
for event in pygame.event.get():
#If the user pressed the x button.
#terminate the while loop.
if event.type == QUIT:
running = False
break;
#In every frame you must clean the window with a color
#in order to draw anythin else above it.
screen.fill((0,0,0))
#Here draw anything you like
#Also somewhere here call all the code that needs to be
#called every frame (Menu code, Game code, etc)
MenuCode()
GameCode()
#Lastly you must update the display.
#The most important thing that this does
#is called buffer swapping, check it out.
pygame.display.update()
#When the loop terminates, terminate pygame.
pygame.quit()
If you want to learn what the update() method does check about double buffering

How to stop drawing a specific rectangle pygame

My program is a 'Piano Hero' game in pygame which works in the same way as guitar hero except that it is for a computer keyboard and its based on playing the piano rather than the guitar. I am using a design similar to Synthesia for my interface where rectangles come down to a 'hitline' and you have to press the key at the right time.
My problem is that although the rectangles are drawing and working as intended at first, they do not seem to update so that the top ever stops. In other words, every note in the song is infinitely long.
I feel like this is probably where the error is although I am not 100% sure.
def Draw(self,hitLine):
if self.coords[2][1]<hitLine:
self.coords[0][1]+=2
self.coords[1][1]+=2
self.coords[2][1]+=2
self.coords[3][1]+=2
elif self.coords[2][1]>=hitLine and self.coords[0][1]<hitLine:
self.coords[0][1]+=2
self.coords[1][1]+=2
else:
self.drawing = False
pygame.draw.polygon(screen,BLUE,self.coords,0)
pygame.display.update()
This line is inside a while loop which just updates all of the rectangles in the song one at a time.
for z in notes:
if z.drawing:
z.Draw(hitLine)
I found you're question quite fun to work on and is very interesting!
Some items to consider.
It doesn't seem that there is any reason to use a "pygame polygon" for your Note objects which are clearly rectangles. In my code below I used "pygame Rect" objects.
You're main loop doesn't clear the screen every frame.
In your main loop you need to clear the screen every frame. In my code I used Rect objects. The Note stops drawing itself when it's top hits the hitLine.
import pygame
pygame.init()
gameScreen = pygame.display.set_mode((1100, 692))
hitLine = 500
class Note:
def __init__(self, rect):
self.rect = rect
self.drawing = True
def draw(self):
if self.rect.y < hitLine:
self.rect.y += 2
else:
self.drawing = False;
pygame.draw.rect(gameScreen, (0, 0, 255), self.rect, 0)
fNote = Note(pygame.Rect(500, -550, 80, 550))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameScreen.fill((0, 0, 0))
if fNote.drawing:
fNote.draw()
pygame.display.update()

Pygame key holding not working

import pygame, sys, math
class Cam:
def __init__(self, pos=(0,0,0), rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
def update(self, dt, key):
s = dt*10
if key[pygame.K_r]: self.pos[1]-=s
if key[pygame.K_f]: self.pos[1]+=s
if key[pygame.K_w]: self.pos[2]+=s
if key[pygame.K_s]: self.pos[2]-=s
if key[pygame.K_a]: self.pos[0]-=s
if key[pygame.K_d]: self.pos[0]+=s
pygame.init()
w,h = 400,400; cx,cy=w//2, h//2
screen = pygame.display.set_mode((w,h))
clock = pygame.time.Clock()
verts=(-1,-1,-1),(1,-1,-1),(1,1,-1),(-1,1,-1),(-1,-1,1),(1,-1,1),(1,1,1),(-1,1,1)
edges = (0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)
cam = Cam((0,0,-5))
while True:
dt = 0.1
print dt
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill((255,255,255))
for edge in edges:
points = []
for x,y,z in (verts[edge[0]],verts[edge[1]]):
x-=cam.pos[0]
y-=cam.pos[1]
z-=cam.pos[2]
f=200/z
x,y = x*f, y*f
points = points + [(cx+int(x), cy+int(y))]
pygame.draw.line(screen, (0,0,0), points[0], points[1], 1)
pygame.display.flip()
key = pygame.key.get_pressed()
cam.update(dt, key)
This is my code. Pressing WASDRF should move the camera around constantly while holding the key, but no. It doesn't. I have to press the key each time I want to move one pixel. Can someone explain why holding the key doesn't work? Judging by all the other questions I've found, this should work.
Just realized my mistake so I thought i would post the answer myself. I put the entire rest of the code after the even for loop IN the event for loop meaning it would only update one every time an event like a key press happened. I needed to unindent everything past sys.exit()

Python Basic control flow errors

When I run this code, it enters a while loop and checks every turn whether or not on_title_screen==True. If it is true, the program will continue to check for input, but if it is false, the loop will refresh the screen and begin the game. However, when start is clicked, and on_title_screen=False, the game still captures mouse input, and does not display the bird that it should.
import random
import pygame
from pygame import *
import math
import sys
#Presets for window
size=width,height=500,500
Ag=-9.80665
clock = pygame.time.Clock()
white=(255,255,255)
blue=(0,0,255)
red=(255,0,0)
gray_bgColor=(190,193,212)
#Initialise pygame Surface as screen
pygame.init()
pygame.font.init()
screen=pygame.display.set_mode(size)
pygame.display.set_caption("Flappy Kid")
#Game Presets
vY=0
xPos,yPos=200,100
score=0
on_title_screen=True
def falling_loop():
for event in pygame.event.get():
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_UP:
vY=-10
if yPos>height-50:
yPos=100
vY+=1
yPos+=vY
class graphics():
#Holds the methods for loading/displaying graphics
def load_images(self):
#Loads the background and sprite images
self.background_image=pygame.image.load("flappy_background.png").convert()
self.bird_image=pygame.image.load("flappy_sprite.jpg").convert()
screen.set_colorkey(white)
self.birdHitBox=self.bird_image.get_rect()
def show_background(self):
#blits the background
screen.blit(self.background_image,[0,0])
def refresh_display(self):
#updates the display
screen.blit(self.background_image,[xPos,yPos],self.birdHitBox)
falling_loop()
screen.blit(self.bird_image,[xPos,yPos])
class titleScreen():
#Holds the methods for the title screen/menu
def title(self):
#Sets up the title
titleText="Flappy Game"
titlePos=(0,0)
currentFont=pygame.font.SysFont("arialms",30,bold=True,italic=True)
renderTitle=currentFont.render(titleText,1,blue,gray_bgColor)
self.titlex,self.titley=currentFont.size(titleText)
screen.blit(renderTitle,titlePos)
def start(self):
#Sets up the start Button
startText="Start Game"
self.startPos=(0,self.titley)
currentFont=pygame.font.SysFont("arialms",25,bold=False,italic=False)
renderStart=currentFont.render(startText,1,blue,gray_bgColor)
self.startx,self.starty=currentFont.size(startText)
self.start_rect = pygame.Rect(self.startPos[0],self.titley,self.startx,self.starty)
screen.blit(renderStart,self.startPos)
def quit(self):
#Sets up the quit button
quitText="Quit"
self.quitPos=(0,self.starty+self.titley)
currentFont=pygame.font.SysFont("arialms",25,bold=False,italic=False)
renderQuit=currentFont.render(quitText,1,red,gray_bgColor)
self.quitx,self.quity=currentFont.size(quitText)
self.quit_rect = pygame.Rect(self.quitPos[0],self.titley+self.starty,self.quitx,self.quity)
screen.blit(renderQuit,self.quitPos)
def get_click(self):
#Gets mouse click and processes outcomes
for event in pygame.event.get():
if event.type==pygame.MOUSEBUTTONDOWN:
x,y=pygame.mouse.get_pos()
#Tests for start:
if self.start_rect.collidepoint(x,y):
print("start")
on_title_screen=False
elif self.quit_rect.collidepoint(x,y):
print("quit")
sys.exit()
titleC=titleScreen()
graphicsC=graphics()
def setupTitle():
#bundles all title_screen functions
titleC.title()
titleC.start()
titleC.quit()
def main():
graphicsC.load_images()
graphicsC.show_background()
setupTitle()
while True:
clock.tick(30)
if on_title_screen==False:
graphicsC.refresh_display()
elif on_title_screen==True:
titleC.get_click()
pygame.display.flip()
main()
I think #TessellatingHeckler is right, on_title_screen is a shadow variable, not the same.
In this code, there is nowhere that on_title_screen (global) could ever be set to False.
A more powerful answer though is to explain how to find the problem. I strongly recommend using pdb or ipdb. In this case, I would put one just inside of the while loop and make sure that the variables are what I think they should be.

Categories