Counting people inside the house game
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
14
down vote
favorite
This program animates people going inside and outside of a house, the user has to keep a running sum in their head and must give the answer at the end.
The speed of people, the number of maximum people inside the house and the number of rounds to be played can be adjusted, at the end the user will get a report saying how many he got right.
You can see the program in action here (Italian commentary, not important)
I took two random images from the internet for this, if you are concerned about copyright, you can just use rectangles of sizes:
- 396*324 for the house
- 197*255 for the person
Folder with code and images
I feel like the code contains too much repetition. It is easier for me to avoid repetition in logic/computational programming but making this animation led me to more repetition than I would have liked, especially in ingoing
vs outgoing
I am open to all kinds of suggestions:
import pygame
import random
import os
import time
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text = myfont.render('Correct! !'.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text = myfont.render('Wrong!, It was '.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
"""
def play_game(difficulty):
ingoing, outgoing = random.randint(0, 9), random.randint(0, 9)
animate_all_people(ingoing, outgoing, difficulty)
"""
def play_match(rounds, speed, max_people):
while True:
text = smallfont.render("Count the people inside the house.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 140 - text.get_height() // 2))
text = smallfont.render("When no more people are moving", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 240 - text.get_height() // 2))
text = smallfont.render("press the number on the keyboard.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 340 - text.get_height() // 2))
text = smallfont.render("Press any key to start playing.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 440 - text.get_height() // 2))
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
ingoing = random.randint(0, max_people) # Careful to avoid more outgoing than ingoing
points += animate_all_people(ingoing , random_if_condition( (0, max_people), lambda r: r <= ingoing), speed)
for _ in range(40 * 5): # 5 seconds
text = myfont.render("You got / right".format(points, rounds), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 140 - text.get_height() // 2))
pygame.display.flip()
#animate_all_people(random.randint(0, 9) , random.randint(0, 9), 30)
if __name__ == "__main__":
play_match(rounds = 3, speed = 15, max_people = 6)
python game animation pygame
add a comment |Â
up vote
14
down vote
favorite
This program animates people going inside and outside of a house, the user has to keep a running sum in their head and must give the answer at the end.
The speed of people, the number of maximum people inside the house and the number of rounds to be played can be adjusted, at the end the user will get a report saying how many he got right.
You can see the program in action here (Italian commentary, not important)
I took two random images from the internet for this, if you are concerned about copyright, you can just use rectangles of sizes:
- 396*324 for the house
- 197*255 for the person
Folder with code and images
I feel like the code contains too much repetition. It is easier for me to avoid repetition in logic/computational programming but making this animation led me to more repetition than I would have liked, especially in ingoing
vs outgoing
I am open to all kinds of suggestions:
import pygame
import random
import os
import time
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text = myfont.render('Correct! !'.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text = myfont.render('Wrong!, It was '.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
"""
def play_game(difficulty):
ingoing, outgoing = random.randint(0, 9), random.randint(0, 9)
animate_all_people(ingoing, outgoing, difficulty)
"""
def play_match(rounds, speed, max_people):
while True:
text = smallfont.render("Count the people inside the house.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 140 - text.get_height() // 2))
text = smallfont.render("When no more people are moving", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 240 - text.get_height() // 2))
text = smallfont.render("press the number on the keyboard.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 340 - text.get_height() // 2))
text = smallfont.render("Press any key to start playing.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 440 - text.get_height() // 2))
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
ingoing = random.randint(0, max_people) # Careful to avoid more outgoing than ingoing
points += animate_all_people(ingoing , random_if_condition( (0, max_people), lambda r: r <= ingoing), speed)
for _ in range(40 * 5): # 5 seconds
text = myfont.render("You got / right".format(points, rounds), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 140 - text.get_height() // 2))
pygame.display.flip()
#animate_all_people(random.randint(0, 9) , random.randint(0, 9), 30)
if __name__ == "__main__":
play_match(rounds = 3, speed = 15, max_people = 6)
python game animation pygame
Thegoogle drive
folder with code.. seems to be pointing to a image..Maybe you can upload it to github?
â alpha_989
Feb 24 at 21:38
@alpha_989 added correct link to git-hub
â Caridorc
Feb 25 at 19:28
add a comment |Â
up vote
14
down vote
favorite
up vote
14
down vote
favorite
This program animates people going inside and outside of a house, the user has to keep a running sum in their head and must give the answer at the end.
The speed of people, the number of maximum people inside the house and the number of rounds to be played can be adjusted, at the end the user will get a report saying how many he got right.
You can see the program in action here (Italian commentary, not important)
I took two random images from the internet for this, if you are concerned about copyright, you can just use rectangles of sizes:
- 396*324 for the house
- 197*255 for the person
Folder with code and images
I feel like the code contains too much repetition. It is easier for me to avoid repetition in logic/computational programming but making this animation led me to more repetition than I would have liked, especially in ingoing
vs outgoing
I am open to all kinds of suggestions:
import pygame
import random
import os
import time
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text = myfont.render('Correct! !'.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text = myfont.render('Wrong!, It was '.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
"""
def play_game(difficulty):
ingoing, outgoing = random.randint(0, 9), random.randint(0, 9)
animate_all_people(ingoing, outgoing, difficulty)
"""
def play_match(rounds, speed, max_people):
while True:
text = smallfont.render("Count the people inside the house.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 140 - text.get_height() // 2))
text = smallfont.render("When no more people are moving", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 240 - text.get_height() // 2))
text = smallfont.render("press the number on the keyboard.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 340 - text.get_height() // 2))
text = smallfont.render("Press any key to start playing.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 440 - text.get_height() // 2))
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
ingoing = random.randint(0, max_people) # Careful to avoid more outgoing than ingoing
points += animate_all_people(ingoing , random_if_condition( (0, max_people), lambda r: r <= ingoing), speed)
for _ in range(40 * 5): # 5 seconds
text = myfont.render("You got / right".format(points, rounds), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 140 - text.get_height() // 2))
pygame.display.flip()
#animate_all_people(random.randint(0, 9) , random.randint(0, 9), 30)
if __name__ == "__main__":
play_match(rounds = 3, speed = 15, max_people = 6)
python game animation pygame
This program animates people going inside and outside of a house, the user has to keep a running sum in their head and must give the answer at the end.
The speed of people, the number of maximum people inside the house and the number of rounds to be played can be adjusted, at the end the user will get a report saying how many he got right.
You can see the program in action here (Italian commentary, not important)
I took two random images from the internet for this, if you are concerned about copyright, you can just use rectangles of sizes:
- 396*324 for the house
- 197*255 for the person
Folder with code and images
I feel like the code contains too much repetition. It is easier for me to avoid repetition in logic/computational programming but making this animation led me to more repetition than I would have liked, especially in ingoing
vs outgoing
I am open to all kinds of suggestions:
import pygame
import random
import os
import time
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text = myfont.render('Correct! !'.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text = myfont.render('Wrong!, It was '.format(str(result)), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 240 - text.get_height() // 2))
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
"""
def play_game(difficulty):
ingoing, outgoing = random.randint(0, 9), random.randint(0, 9)
animate_all_people(ingoing, outgoing, difficulty)
"""
def play_match(rounds, speed, max_people):
while True:
text = smallfont.render("Count the people inside the house.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 140 - text.get_height() // 2))
text = smallfont.render("When no more people are moving", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 240 - text.get_height() // 2))
text = smallfont.render("press the number on the keyboard.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 340 - text.get_height() // 2))
text = smallfont.render("Press any key to start playing.", False, (255, 0, 0))
screen.blit(text,
(380 - text.get_width() // 2, 440 - text.get_height() // 2))
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
ingoing = random.randint(0, max_people) # Careful to avoid more outgoing than ingoing
points += animate_all_people(ingoing , random_if_condition( (0, max_people), lambda r: r <= ingoing), speed)
for _ in range(40 * 5): # 5 seconds
text = myfont.render("You got / right".format(points, rounds), False, (255, 0, 0))
screen.blit(text,
(320 - text.get_width() // 2, 140 - text.get_height() // 2))
pygame.display.flip()
#animate_all_people(random.randint(0, 9) , random.randint(0, 9), 30)
if __name__ == "__main__":
play_match(rounds = 3, speed = 15, max_people = 6)
python game animation pygame
edited Feb 25 at 19:27
asked Feb 24 at 20:18
Caridorc
22.6k432111
22.6k432111
Thegoogle drive
folder with code.. seems to be pointing to a image..Maybe you can upload it to github?
â alpha_989
Feb 24 at 21:38
@alpha_989 added correct link to git-hub
â Caridorc
Feb 25 at 19:28
add a comment |Â
Thegoogle drive
folder with code.. seems to be pointing to a image..Maybe you can upload it to github?
â alpha_989
Feb 24 at 21:38
@alpha_989 added correct link to git-hub
â Caridorc
Feb 25 at 19:28
The
google drive
folder with code.. seems to be pointing to a image..Maybe you can upload it to github?â alpha_989
Feb 24 at 21:38
The
google drive
folder with code.. seems to be pointing to a image..Maybe you can upload it to github?â alpha_989
Feb 24 at 21:38
@alpha_989 added correct link to git-hub
â Caridorc
Feb 25 at 19:28
@alpha_989 added correct link to git-hub
â Caridorc
Feb 25 at 19:28
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
12
down vote
You're right - there is a lot of duplication. Also, some organization is needed.
Organize!
Before you do anything else, get everything into a function of some kind. All those statements at module scope, move them into a setup function, write yourself a main
, and do the standard Python thing:
if __name__ == '__main__':
main()
You can call play_match
from inside main
after you call setup
. You might even put in a while:
loop to play multiple matches.
Animate
Let's have a look at your in/out functions:
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
The lines that are different are:
x = -200
x = 300
if x > 300:
if x > 900:
It seems fairly obvious that these could be parameters:
def animate_person(speed, start_x, target_x):
x = start_x
if x > target_x:
Then you can rewrite the two functions as:
def animate_person_going_inside_house(speed):
animate_person(speed, -200, 300)
def animate_person_going_outside_house(speed):
animate_person(speed, 300, 900)
Or, you could simply eliminate them and call the animate_person
directly.
Clarify
You have a lot of "magic" numbers, like -200, 900, 300, 260, 340, 200, and (255,255,255). I don't know what they mean. Replace them with named constants:
X_PERSON_OFF_LEFT_EDGE = -200
X_DOOR_OF_HOUSE = 300
Remember, you are writing code for the next maintainer, not for the compiler.
You have this while loop that is unclear:
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
When you see a break
, you have to ask, could I add this to the main loop test? In this case, yes, you can:
while ingoing + outgoing != 0:
direction = random.choice( ('in',) * ingoing + ('out',) * outgoing )
if direction == 'in':
ingoing -= 1
animate_person_going_inside_house(difficulty)
people_inside += 1
else:
outgoing -= 1
animate_person_going_outside_house(difficulty)
people_inside -= 1
Note that I have changed the behavior here, from 50/50 to proportional to the # remaining. You could certainly change it back. The point is to change the while
condition.
Note also that this is where you would replace calls to separate inside/outside functions with a single function. You could create a container with two sets of parameters, and index by a random number (0,1) or random string ('in', 'out') to select which parameter set to use.
Help Yourself
Don't be afraid to write helper functions. In fact, if you write a comment, ask yourself if that comment should be a function name instead. If you write a paragraph of code, and then break for another paragraph, ask yourself if that should be a new function. Even if you only call it once, it might be a structural function rather than a reusable function.
You have this code:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
That cries out to be a function. Or two functions.
if is_digit_key(event.key) and digit_val(event.key) == people_inside:
Advance!
One thing you don't do is support multiple people moving at the same time. I don't know how important that is to you, but your code isn't structured to handle it.
You would need a list of moving people, and their target locations. You could create a simple class for that:
class MovingPerson:
def __init__(start_x, target_x, speed):
Then your animate
function would loop over all the moving sprites, update them, then refresh the screen:
for p in moving_people:
p.update()
pygame.display.update()
1
I have doubts about yourrandom.choice
usage, on my 2.7 python it gives:>>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
1
You're right, @Caridorc. I was missing trailing commas - I've edited it. Tryrandom.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).
â Austin Hastings
Feb 25 at 23:37
add a comment |Â
up vote
6
down vote
I noticed that you are repeating some of the code under animate_person_going_inside
and `animate_person_going_outside functions. Also when rendering the text, some of the code is repeated.
If you take out that part of the code into a function, it will reduce repeatation.
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_moving(starting_position, final_position, speed):
running = True
x = starting_position
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > final_position:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice((0, 1)):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_moving(-200, 300, difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_moving(300, 900, difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text_render(
myfont, 'Correct! !'.format(
str(result)), 320, 240)
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text_render(
myfont, 'Wrong!, It was '.format(
str(result)), 320, 240)
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
def text_render(font_type, text_to_be_printed, max_width, max_height):
text = font_type.render(text_to_be_printed, False, (255, 0, 0))
screen.blit(text, (max_width - text.get_width() // 2, max_height -
text.get_height() // 2))
def play_match(rounds, speed, max_people):
while True:
text_render(smallfont, "Count the people inside the house.", 380, 140)
text_render(smallfont, "When no more people are moving", 380, 240)
text_render(smallfont, "press the number on the keyboard.", 380, 340)
text_render(smallfont, "Press any key to start playing.", 380, 440)
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
# Careful to avoid more outgoing than ingoing
ingoing = random.randint(0, max_people)
points += animate_all_people(ingoing,
random_if_condition(
(0, max_people),
lambda r: r <= ingoing),
speed)
for _ in range(40 * 5): # 5 seconds
text_render(myfont, "You got / right".format(points, rounds), 320,
140)
pygame.display.flip()
if __name__ == "__main__":
play_match(rounds=3, speed=15, max_people=6)
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
12
down vote
You're right - there is a lot of duplication. Also, some organization is needed.
Organize!
Before you do anything else, get everything into a function of some kind. All those statements at module scope, move them into a setup function, write yourself a main
, and do the standard Python thing:
if __name__ == '__main__':
main()
You can call play_match
from inside main
after you call setup
. You might even put in a while:
loop to play multiple matches.
Animate
Let's have a look at your in/out functions:
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
The lines that are different are:
x = -200
x = 300
if x > 300:
if x > 900:
It seems fairly obvious that these could be parameters:
def animate_person(speed, start_x, target_x):
x = start_x
if x > target_x:
Then you can rewrite the two functions as:
def animate_person_going_inside_house(speed):
animate_person(speed, -200, 300)
def animate_person_going_outside_house(speed):
animate_person(speed, 300, 900)
Or, you could simply eliminate them and call the animate_person
directly.
Clarify
You have a lot of "magic" numbers, like -200, 900, 300, 260, 340, 200, and (255,255,255). I don't know what they mean. Replace them with named constants:
X_PERSON_OFF_LEFT_EDGE = -200
X_DOOR_OF_HOUSE = 300
Remember, you are writing code for the next maintainer, not for the compiler.
You have this while loop that is unclear:
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
When you see a break
, you have to ask, could I add this to the main loop test? In this case, yes, you can:
while ingoing + outgoing != 0:
direction = random.choice( ('in',) * ingoing + ('out',) * outgoing )
if direction == 'in':
ingoing -= 1
animate_person_going_inside_house(difficulty)
people_inside += 1
else:
outgoing -= 1
animate_person_going_outside_house(difficulty)
people_inside -= 1
Note that I have changed the behavior here, from 50/50 to proportional to the # remaining. You could certainly change it back. The point is to change the while
condition.
Note also that this is where you would replace calls to separate inside/outside functions with a single function. You could create a container with two sets of parameters, and index by a random number (0,1) or random string ('in', 'out') to select which parameter set to use.
Help Yourself
Don't be afraid to write helper functions. In fact, if you write a comment, ask yourself if that comment should be a function name instead. If you write a paragraph of code, and then break for another paragraph, ask yourself if that should be a new function. Even if you only call it once, it might be a structural function rather than a reusable function.
You have this code:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
That cries out to be a function. Or two functions.
if is_digit_key(event.key) and digit_val(event.key) == people_inside:
Advance!
One thing you don't do is support multiple people moving at the same time. I don't know how important that is to you, but your code isn't structured to handle it.
You would need a list of moving people, and their target locations. You could create a simple class for that:
class MovingPerson:
def __init__(start_x, target_x, speed):
Then your animate
function would loop over all the moving sprites, update them, then refresh the screen:
for p in moving_people:
p.update()
pygame.display.update()
1
I have doubts about yourrandom.choice
usage, on my 2.7 python it gives:>>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
1
You're right, @Caridorc. I was missing trailing commas - I've edited it. Tryrandom.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).
â Austin Hastings
Feb 25 at 23:37
add a comment |Â
up vote
12
down vote
You're right - there is a lot of duplication. Also, some organization is needed.
Organize!
Before you do anything else, get everything into a function of some kind. All those statements at module scope, move them into a setup function, write yourself a main
, and do the standard Python thing:
if __name__ == '__main__':
main()
You can call play_match
from inside main
after you call setup
. You might even put in a while:
loop to play multiple matches.
Animate
Let's have a look at your in/out functions:
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
The lines that are different are:
x = -200
x = 300
if x > 300:
if x > 900:
It seems fairly obvious that these could be parameters:
def animate_person(speed, start_x, target_x):
x = start_x
if x > target_x:
Then you can rewrite the two functions as:
def animate_person_going_inside_house(speed):
animate_person(speed, -200, 300)
def animate_person_going_outside_house(speed):
animate_person(speed, 300, 900)
Or, you could simply eliminate them and call the animate_person
directly.
Clarify
You have a lot of "magic" numbers, like -200, 900, 300, 260, 340, 200, and (255,255,255). I don't know what they mean. Replace them with named constants:
X_PERSON_OFF_LEFT_EDGE = -200
X_DOOR_OF_HOUSE = 300
Remember, you are writing code for the next maintainer, not for the compiler.
You have this while loop that is unclear:
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
When you see a break
, you have to ask, could I add this to the main loop test? In this case, yes, you can:
while ingoing + outgoing != 0:
direction = random.choice( ('in',) * ingoing + ('out',) * outgoing )
if direction == 'in':
ingoing -= 1
animate_person_going_inside_house(difficulty)
people_inside += 1
else:
outgoing -= 1
animate_person_going_outside_house(difficulty)
people_inside -= 1
Note that I have changed the behavior here, from 50/50 to proportional to the # remaining. You could certainly change it back. The point is to change the while
condition.
Note also that this is where you would replace calls to separate inside/outside functions with a single function. You could create a container with two sets of parameters, and index by a random number (0,1) or random string ('in', 'out') to select which parameter set to use.
Help Yourself
Don't be afraid to write helper functions. In fact, if you write a comment, ask yourself if that comment should be a function name instead. If you write a paragraph of code, and then break for another paragraph, ask yourself if that should be a new function. Even if you only call it once, it might be a structural function rather than a reusable function.
You have this code:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
That cries out to be a function. Or two functions.
if is_digit_key(event.key) and digit_val(event.key) == people_inside:
Advance!
One thing you don't do is support multiple people moving at the same time. I don't know how important that is to you, but your code isn't structured to handle it.
You would need a list of moving people, and their target locations. You could create a simple class for that:
class MovingPerson:
def __init__(start_x, target_x, speed):
Then your animate
function would loop over all the moving sprites, update them, then refresh the screen:
for p in moving_people:
p.update()
pygame.display.update()
1
I have doubts about yourrandom.choice
usage, on my 2.7 python it gives:>>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
1
You're right, @Caridorc. I was missing trailing commas - I've edited it. Tryrandom.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).
â Austin Hastings
Feb 25 at 23:37
add a comment |Â
up vote
12
down vote
up vote
12
down vote
You're right - there is a lot of duplication. Also, some organization is needed.
Organize!
Before you do anything else, get everything into a function of some kind. All those statements at module scope, move them into a setup function, write yourself a main
, and do the standard Python thing:
if __name__ == '__main__':
main()
You can call play_match
from inside main
after you call setup
. You might even put in a while:
loop to play multiple matches.
Animate
Let's have a look at your in/out functions:
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
The lines that are different are:
x = -200
x = 300
if x > 300:
if x > 900:
It seems fairly obvious that these could be parameters:
def animate_person(speed, start_x, target_x):
x = start_x
if x > target_x:
Then you can rewrite the two functions as:
def animate_person_going_inside_house(speed):
animate_person(speed, -200, 300)
def animate_person_going_outside_house(speed):
animate_person(speed, 300, 900)
Or, you could simply eliminate them and call the animate_person
directly.
Clarify
You have a lot of "magic" numbers, like -200, 900, 300, 260, 340, 200, and (255,255,255). I don't know what they mean. Replace them with named constants:
X_PERSON_OFF_LEFT_EDGE = -200
X_DOOR_OF_HOUSE = 300
Remember, you are writing code for the next maintainer, not for the compiler.
You have this while loop that is unclear:
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
When you see a break
, you have to ask, could I add this to the main loop test? In this case, yes, you can:
while ingoing + outgoing != 0:
direction = random.choice( ('in',) * ingoing + ('out',) * outgoing )
if direction == 'in':
ingoing -= 1
animate_person_going_inside_house(difficulty)
people_inside += 1
else:
outgoing -= 1
animate_person_going_outside_house(difficulty)
people_inside -= 1
Note that I have changed the behavior here, from 50/50 to proportional to the # remaining. You could certainly change it back. The point is to change the while
condition.
Note also that this is where you would replace calls to separate inside/outside functions with a single function. You could create a container with two sets of parameters, and index by a random number (0,1) or random string ('in', 'out') to select which parameter set to use.
Help Yourself
Don't be afraid to write helper functions. In fact, if you write a comment, ask yourself if that comment should be a function name instead. If you write a paragraph of code, and then break for another paragraph, ask yourself if that should be a new function. Even if you only call it once, it might be a structural function rather than a reusable function.
You have this code:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
That cries out to be a function. Or two functions.
if is_digit_key(event.key) and digit_val(event.key) == people_inside:
Advance!
One thing you don't do is support multiple people moving at the same time. I don't know how important that is to you, but your code isn't structured to handle it.
You would need a list of moving people, and their target locations. You could create a simple class for that:
class MovingPerson:
def __init__(start_x, target_x, speed):
Then your animate
function would loop over all the moving sprites, update them, then refresh the screen:
for p in moving_people:
p.update()
pygame.display.update()
You're right - there is a lot of duplication. Also, some organization is needed.
Organize!
Before you do anything else, get everything into a function of some kind. All those statements at module scope, move them into a setup function, write yourself a main
, and do the standard Python thing:
if __name__ == '__main__':
main()
You can call play_match
from inside main
after you call setup
. You might even put in a while:
loop to play multiple matches.
Animate
Let's have a look at your in/out functions:
def animate_person_going_inside_house(speed):
running = True
x = -200
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 300:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_person_going_outside_house(speed):
running = True
x = 300
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > 900:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
The lines that are different are:
x = -200
x = 300
if x > 300:
if x > 900:
It seems fairly obvious that these could be parameters:
def animate_person(speed, start_x, target_x):
x = start_x
if x > target_x:
Then you can rewrite the two functions as:
def animate_person_going_inside_house(speed):
animate_person(speed, -200, 300)
def animate_person_going_outside_house(speed):
animate_person(speed, 300, 900)
Or, you could simply eliminate them and call the animate_person
directly.
Clarify
You have a lot of "magic" numbers, like -200, 900, 300, 260, 340, 200, and (255,255,255). I don't know what they mean. Replace them with named constants:
X_PERSON_OFF_LEFT_EDGE = -200
X_DOOR_OF_HOUSE = 300
Remember, you are writing code for the next maintainer, not for the compiler.
You have this while loop that is unclear:
while True:
if random.choice( (0, 1) ):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_going_inside_house(difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_going_outside_house(difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
When you see a break
, you have to ask, could I add this to the main loop test? In this case, yes, you can:
while ingoing + outgoing != 0:
direction = random.choice( ('in',) * ingoing + ('out',) * outgoing )
if direction == 'in':
ingoing -= 1
animate_person_going_inside_house(difficulty)
people_inside += 1
else:
outgoing -= 1
animate_person_going_outside_house(difficulty)
people_inside -= 1
Note that I have changed the behavior here, from 50/50 to proportional to the # remaining. You could certainly change it back. The point is to change the while
condition.
Note also that this is where you would replace calls to separate inside/outside functions with a single function. You could create a container with two sets of parameters, and index by a random number (0,1) or random string ('in', 'out') to select which parameter set to use.
Help Yourself
Don't be afraid to write helper functions. In fact, if you write a comment, ask yourself if that comment should be a function name instead. If you write a paragraph of code, and then break for another paragraph, ask yourself if that should be a new function. Even if you only call it once, it might be a structural function rather than a reusable function.
You have this code:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
That cries out to be a function. Or two functions.
if is_digit_key(event.key) and digit_val(event.key) == people_inside:
Advance!
One thing you don't do is support multiple people moving at the same time. I don't know how important that is to you, but your code isn't structured to handle it.
You would need a list of moving people, and their target locations. You could create a simple class for that:
class MovingPerson:
def __init__(start_x, target_x, speed):
Then your animate
function would loop over all the moving sprites, update them, then refresh the screen:
for p in moving_people:
p.update()
pygame.display.update()
edited Feb 25 at 23:36
answered Feb 24 at 22:05
Austin Hastings
6,1591130
6,1591130
1
I have doubts about yourrandom.choice
usage, on my 2.7 python it gives:>>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
1
You're right, @Caridorc. I was missing trailing commas - I've edited it. Tryrandom.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).
â Austin Hastings
Feb 25 at 23:37
add a comment |Â
1
I have doubts about yourrandom.choice
usage, on my 2.7 python it gives:>>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
1
You're right, @Caridorc. I was missing trailing commas - I've edited it. Tryrandom.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).
â Austin Hastings
Feb 25 at 23:37
1
1
I have doubts about your
random.choice
usage, on my 2.7 python it gives: >>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
I have doubts about your
random.choice
usage, on my 2.7 python it gives: >>> import random >>> random.choice( ('in') * 3 + ('out') * 4 ) 'u'
â Caridorc
Feb 25 at 19:32
1
1
You're right, @Caridorc. I was missing trailing commas - I've edited it. Try
random.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).â Austin Hastings
Feb 25 at 23:37
You're right, @Caridorc. I was missing trailing commas - I've edited it. Try
random.choice( ('in' , ) * 3 + ('out' , ) * 4 )
instead (note the commas).â Austin Hastings
Feb 25 at 23:37
add a comment |Â
up vote
6
down vote
I noticed that you are repeating some of the code under animate_person_going_inside
and `animate_person_going_outside functions. Also when rendering the text, some of the code is repeated.
If you take out that part of the code into a function, it will reduce repeatation.
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_moving(starting_position, final_position, speed):
running = True
x = starting_position
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > final_position:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice((0, 1)):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_moving(-200, 300, difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_moving(300, 900, difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text_render(
myfont, 'Correct! !'.format(
str(result)), 320, 240)
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text_render(
myfont, 'Wrong!, It was '.format(
str(result)), 320, 240)
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
def text_render(font_type, text_to_be_printed, max_width, max_height):
text = font_type.render(text_to_be_printed, False, (255, 0, 0))
screen.blit(text, (max_width - text.get_width() // 2, max_height -
text.get_height() // 2))
def play_match(rounds, speed, max_people):
while True:
text_render(smallfont, "Count the people inside the house.", 380, 140)
text_render(smallfont, "When no more people are moving", 380, 240)
text_render(smallfont, "press the number on the keyboard.", 380, 340)
text_render(smallfont, "Press any key to start playing.", 380, 440)
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
# Careful to avoid more outgoing than ingoing
ingoing = random.randint(0, max_people)
points += animate_all_people(ingoing,
random_if_condition(
(0, max_people),
lambda r: r <= ingoing),
speed)
for _ in range(40 * 5): # 5 seconds
text_render(myfont, "You got / right".format(points, rounds), 320,
140)
pygame.display.flip()
if __name__ == "__main__":
play_match(rounds=3, speed=15, max_people=6)
add a comment |Â
up vote
6
down vote
I noticed that you are repeating some of the code under animate_person_going_inside
and `animate_person_going_outside functions. Also when rendering the text, some of the code is repeated.
If you take out that part of the code into a function, it will reduce repeatation.
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_moving(starting_position, final_position, speed):
running = True
x = starting_position
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > final_position:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice((0, 1)):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_moving(-200, 300, difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_moving(300, 900, difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text_render(
myfont, 'Correct! !'.format(
str(result)), 320, 240)
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text_render(
myfont, 'Wrong!, It was '.format(
str(result)), 320, 240)
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
def text_render(font_type, text_to_be_printed, max_width, max_height):
text = font_type.render(text_to_be_printed, False, (255, 0, 0))
screen.blit(text, (max_width - text.get_width() // 2, max_height -
text.get_height() // 2))
def play_match(rounds, speed, max_people):
while True:
text_render(smallfont, "Count the people inside the house.", 380, 140)
text_render(smallfont, "When no more people are moving", 380, 240)
text_render(smallfont, "press the number on the keyboard.", 380, 340)
text_render(smallfont, "Press any key to start playing.", 380, 440)
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
# Careful to avoid more outgoing than ingoing
ingoing = random.randint(0, max_people)
points += animate_all_people(ingoing,
random_if_condition(
(0, max_people),
lambda r: r <= ingoing),
speed)
for _ in range(40 * 5): # 5 seconds
text_render(myfont, "You got / right".format(points, rounds), 320,
140)
pygame.display.flip()
if __name__ == "__main__":
play_match(rounds=3, speed=15, max_people=6)
add a comment |Â
up vote
6
down vote
up vote
6
down vote
I noticed that you are repeating some of the code under animate_person_going_inside
and `animate_person_going_outside functions. Also when rendering the text, some of the code is repeated.
If you take out that part of the code into a function, it will reduce repeatation.
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_moving(starting_position, final_position, speed):
running = True
x = starting_position
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > final_position:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice((0, 1)):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_moving(-200, 300, difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_moving(300, 900, difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text_render(
myfont, 'Correct! !'.format(
str(result)), 320, 240)
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text_render(
myfont, 'Wrong!, It was '.format(
str(result)), 320, 240)
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
def text_render(font_type, text_to_be_printed, max_width, max_height):
text = font_type.render(text_to_be_printed, False, (255, 0, 0))
screen.blit(text, (max_width - text.get_width() // 2, max_height -
text.get_height() // 2))
def play_match(rounds, speed, max_people):
while True:
text_render(smallfont, "Count the people inside the house.", 380, 140)
text_render(smallfont, "When no more people are moving", 380, 240)
text_render(smallfont, "press the number on the keyboard.", 380, 340)
text_render(smallfont, "Press any key to start playing.", 380, 440)
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
# Careful to avoid more outgoing than ingoing
ingoing = random.randint(0, max_people)
points += animate_all_people(ingoing,
random_if_condition(
(0, max_people),
lambda r: r <= ingoing),
speed)
for _ in range(40 * 5): # 5 seconds
text_render(myfont, "You got / right".format(points, rounds), 320,
140)
pygame.display.flip()
if __name__ == "__main__":
play_match(rounds=3, speed=15, max_people=6)
I noticed that you are repeating some of the code under animate_person_going_inside
and `animate_person_going_outside functions. Also when rendering the text, some of the code is repeated.
If you take out that part of the code into a function, it will reduce repeatation.
import pygame
import random
pygame.init()
screen = pygame.display.set_mode((800, 640))
person = pygame.image.load('person.png')
house = pygame.image.load('house.png')
clock = pygame.time.Clock()
pygame.display.set_caption('People counting game')
myfont = pygame.font.SysFont('comicsansms', 80)
smallfont = pygame.font.SysFont('comicsansms', 30)
ingoing_persons = 5
outgoing_persons = 3
def animate_person_moving(starting_position, final_position, speed):
running = True
x = starting_position
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
x += speed
screen.fill((255, 255, 255)) # fill the screen
screen.blit(person, (int(x), 340))
screen.blit(house, (200, 260))
if x > final_position:
return
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
def animate_all_people(ingoing, outgoing, difficulty):
result = ingoing - outgoing
ingoing_so_far = 0
outgoing_so_far = 0
people_inside = 0
while True:
if random.choice((0, 1)):
if ingoing_so_far < ingoing:
people_inside += 1
animate_person_moving(-200, 300, difficulty)
ingoing_so_far += 1
else:
if outgoing_so_far < outgoing and people_inside > 0: # People can only exit if people are inside!
people_inside -= 1
animate_person_moving(300, 900, difficulty)
outgoing_so_far += 1
if ingoing_so_far == ingoing and outgoing_so_far == outgoing:
break
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_0 and people_inside == 0) or
(event.key == pygame.K_1 and people_inside == 1) or
(event.key == pygame.K_2 and people_inside == 2) or
(event.key == pygame.K_3 and people_inside == 3) or
(event.key == pygame.K_4 and people_inside == 4) or
(event.key == pygame.K_5 and people_inside == 5) or
(event.key == pygame.K_6 and people_inside == 6) or
(event.key == pygame.K_7 and people_inside == 7) or
(event.key == pygame.K_8 and people_inside == 8) or
(event.key == pygame.K_9 and people_inside == 9):
for _ in range(40 * 2):
text_render(
myfont, 'Correct! !'.format(
str(result)), 320, 240)
pygame.display.flip()
return 1
else:
for _ in range(40 * 2):
text_render(
myfont, 'Wrong!, It was '.format(
str(result)), 320, 240)
pygame.display.flip()
return 0
def random_if_condition(minmax, condition):
while True:
r = random.randint(*minmax)
if condition(r):
return r
def text_render(font_type, text_to_be_printed, max_width, max_height):
text = font_type.render(text_to_be_printed, False, (255, 0, 0))
screen.blit(text, (max_width - text.get_width() // 2, max_height -
text.get_height() // 2))
def play_match(rounds, speed, max_people):
while True:
text_render(smallfont, "Count the people inside the house.", 380, 140)
text_render(smallfont, "When no more people are moving", 380, 240)
text_render(smallfont, "press the number on the keyboard.", 380, 340)
text_render(smallfont, "Press any key to start playing.", 380, 440)
event = pygame.event.poll()
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYUP or event.type == pygame.KEYDOWN:
break
pygame.display.flip()
points = 0
for _ in range(rounds):
# Careful to avoid more outgoing than ingoing
ingoing = random.randint(0, max_people)
points += animate_all_people(ingoing,
random_if_condition(
(0, max_people),
lambda r: r <= ingoing),
speed)
for _ in range(40 * 5): # 5 seconds
text_render(myfont, "You got / right".format(points, rounds), 320,
140)
pygame.display.flip()
if __name__ == "__main__":
play_match(rounds=3, speed=15, max_people=6)
answered Feb 24 at 22:43
alpha_989
1956
1956
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188288%2fcounting-people-inside-the-house-game%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
The
google drive
folder with code.. seems to be pointing to a image..Maybe you can upload it to github?â alpha_989
Feb 24 at 21:38
@alpha_989 added correct link to git-hub
â Caridorc
Feb 25 at 19:28