Our project is a new version of Flappy Bird Game. It is a pygame program written in python. Users can play this game either on PiTFT screen or play it in their computer. It contains two play modes, single player and dual player modes. In single player mode, each player have 3 lives and their NetIDs and final scores will be writen to a score board, which keeps track of top 10 scores. The dual player mode gives users the opportunity to compete with their friends. We also implemented two background settings, daytime and night modes. The users could also choose either one background mode before playing the game. One difficulty for users is that the horizontal shifting speed will increasing as time goes on. We also implemented a hidden trick in the single player mode. When user achieves 10 scores, the flappy bird will evolve into flappy Joe.
Following is the instruction of how to play the game.
Our objective for this project is to implement the game on PiTFT screen. We try to create user-friendly interfaces to allow user better understand the game instructions and workflows. The game allows users to choose playing modes and background settings, and to control bird using touchscreen or keyboard buttons. It also contains a score board function to track previous history.
Following is the front page of the game. Every interface is based on traditional Flappy Bird game. We modified some details to include our own functionalities.
Our design process is to first create all static interfaces and buttons associated with each interface. Then we started to create single player mode, including pipe and background shifting, bird falling or jumping, score and life tracking, sound effect. Then we created a backend json file and read/write to it when store new record. Finally, we created the dual player mode based on the single player mode.
Following is our project schedule.
We tested our program in the same way as the developing steps. We tested the overall structure of the game by traversing each interface, and test the single player mode by checking the update of the score and life when bird moves. One difficulty is that we need the user to input NetID to store their score. However, pygame does not contain type-in box to get the keyboard input. Therefore, we added a new interface and transfer the keyboard input to string and draw the string on the screen. Finally, we finished the dual player implementation in a very short period of time because all the fucntionalities are the same as in single player mode.
Following is the NetID page, which allows user to type in their NetID on screen.
Followings are the screenshots of our project interfaces.
This is the front page
This is the instruction page
This is the score board page
This is the mode selection page
This is the user NetID page
This is the background selection page
This is in the single daytime playing mode
This is flappy joe when score is greater than 10
This is pause page when users have to pause the game because of emergency
This is in the single night playing mode
This is in the dual player daytime mode
This is the result of dual player game
Everything in our project performed as planned and our team meets the goals outlined in the description. We designed a new flappy bird game. In the demo, we encouraged professor Skovira and TAs to play the game, which gave everyone a lot of fun. Finally, the project got the highly praise from professor Skovira and TAs.
Our final project was planned, developed and demonstrated as expected. We designed a new version of Flappy Bird Game written in Python, which could be played either on PiTFT screen or personal computer. Firstly, a user-friendly interface was implemented. Secondly, single player mode was realized. In single player mode, each player have 3 lives and their NetIDs and final scores will be writen to a score board, which keeps track of top 10 scores. Then the code of dual player mode was written. It gives users the opportunity to compete with their friends, which will bring a lot of fun. We also implemented two background settings, daytime and night modes. The users could also choose either one background mode before playing the game. One difficulty for users is that the horizontal shifting speed will increasing as time goes on. We also implemented a hidden trick in the single player mode. When user achieves 10 scores, the flappy bird will evolve into flappy Joe.
We want to create the bird rotating effect when jumping or falling.
Also, we can increase the game difficulity by decreasing the gap between pipes as time goes on.
Finally, we can increase the game difficulity by making pipes move up and down as time goes on.
PiTFT Screen
Raspberry Pi 3
Loudspeaker box
Interfaces Creation: Yuanxin Wang, Zhizhong Peng
Bird Control: Yuanxin Wang, Zhizhong Peng
Single Player mode: Yuanxin Wang, Zhizhong Peng
Screen Shifting: Zhizhong Peng
Random Pipe: Yuanxin Wang, Zhizhong Peng
Score Board function: Yuanxin Wang
Dual Player mode: Yuanxin Wang
Sound Effect: Zhizhong Peng
# Yuanxin Wang & Zhizhong Peng
# yw2243 & zp83
# 12/05/2018
# ECE 5725 Final Project
# Flappy Bird Game
# This program is a new version of Flappy Bird Game.
import pygame,sys,random
from pygame.locals import *
import os
import sys
import time
import json
import string
#set up environment variables so it can be displayed on PiTFT
#os.putenv('SDL_VIDEODRIVER', 'fbcon')
#os.putenv('SDL_FBDEV', '/dev/fb1')
#set up to enable touchscreen function
#os.putenv('SDL_MOUSEDRV', 'TSLIB')
#os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
def main():
#start pygame
pygame.init()
# initialize global variables
global win,score2, location2,usernamemode,username,score_list,json_file,speedLimit,
movingLeftSpeed,screenSize,screen,height,width,FPS,life,score, count, press, startAgain,
flags, countdown,BLACK,WHITE,bg1,bg2,bg3,bg4,location,mode1,mode2,instruction,history,
playmode,singlePlayer,duelPlayer,daytime,nighttime,clock,SCREENWIDTH,SCREENHEIGHT,BASEY,
IMAGES, SOUNDS
#initialze each global varialbes
win = 0 # which player win the game
SCREENWIDTH = 320
SCREENHEIGHT = 240
BASEY = SCREENHEIGHT * 0.79
IMAGES, SOUNDS = {}, {}
username = ""
clock = pygame.time.Clock()
speedLimit = 4 # highest speed lime of shifting left
movingLeftSpeed = 2 # initial shifting left speed
screenSize = (320, 240)
height = 32
width = 28
FPS = 64
speed = 5 # bird falling speed
location = (77, 120) # first bird location
location2 = (77, 100) # second bird location
score = 0 # score of the first player
score2 = 0 # score of the second player
life = 3 # how many lives the player have
count = 15
startPage = True
mode1 = False
mode2 = False
history = False
instruction = False
playmode = False
usernamemode = False
singlePlayer = False
duelPlayer = False
daytime = False
nighttime = False
countdown = False
press = True
startAgain = False
flags = False
score_list = []
#make the mouse invisible
pygame.mouse.set_visible(True)
#colors code for white and black
WHITE = 255, 255, 255
BLACK = 0, 0, 0
#set the size for the screen
screen = pygame.display.set_mode(screenSize)
# set the caption of the pygame
pygame.display.set_caption('Flappy Bird')
# load the images
bg1 = pygame.image.load("front_page.jpg")
bg2 = pygame.image.load("front_page2.jpg")
bg3 = pygame.image.load("background.jpg")
bg4 = pygame.image.load("background3.png")
# load the background sound effect
if 'win' in sys.platform:
soundExt = '.wav'
else:
soundExt = '.ogg'
SOUNDS['die'] = pygame.mixer.Sound('assets/audio/die' + soundExt)
SOUNDS['hit'] = pygame.mixer.Sound('assets/audio/hit' + soundExt)
SOUNDS['point'] = pygame.mixer.Sound('assets/audio/point' + soundExt)
SOUNDS['swoosh'] = pygame.mixer.Sound('assets/audio/swoosh' + soundExt)
SOUNDS['wing'] = pygame.mixer.Sound('assets/audio/wing' + soundExt)
while 1:
time.sleep(0.01)
# enter different pages
if startPage:
start_page()
elif instruction:
instruction_page()
elif history:
scoreboard_page()
elif mode1:
mode_player()
elif usernamemode:
mode_username()
usernamemode = False
mode2 = True
elif mode2:
mode_daynight()
elif playmode:
play_mode(score,life)
# add countdown effect when game starts
if countdown:
countdown = False
for i in range(3):
if i==2:
flags = True
my_font = pygame.font.Font("ComicSansMS3.ttf",30)
s = str(3-i)
text_surface = my_font.render(s, True, WHITE)
rect = text_surface.get_rect(center = (170, 110))
screen.blit(text_surface, rect)
pygame.display.flip()
time.sleep(1)
play_mode(score, life)
for event in pygame.event.get():
# when left click
if(event.type is MOUSEBUTTONUP):
# get the location when pressing the touchscreen
pos = pygame.mouse.get_pos()
x,y = pos
# in start page
if startPage:
if x < 160 and x > 10:
if y < 155 and y > 130:
# hit play button
startPage = False
mode1 = True
elif y < 180 and y > 155:
# hit score board button
startPage = False
history = True
elif y < 205 and y > 180:
# hit instruction button
startPage = False
instruction = True
# hit quit button
elif x < 310 and x > 250:
if y < 235 and y > 220:
pygame.quit()
# in score board page
elif history:
# hit back button
if x < 310 and x > 250:
if y < 235 and y > 220:
startPage = True
history = False
# in instruction page
elif instruction:
# hit back button
if x < 310 and x > 250:
if y < 235 and y > 220:
startPage = True
mode1 = False
instruction = False
# in single/dual selection page
elif mode1:
if x < 160 and x > 10:
# single player
if y < 120 and y > 95:
mode1 = False
mode2 = False
singlePlayer = True
usernamemode = True
# dual player mode
elif y < 145 and y > 120:
mode1 = False
mode2 = True
duelPlayer = True
elif x < 310 and x > 250:
# hit back button
if y < 235 and y > 220:
startPage = True
mode1 = False
# in day/night selection page
elif mode2:
if x < 160 and x > 10:
# daytime mode
if y < 120 and y > 95:
mode2 = False
playmode = True
daytime = True
countdown = True
# night mode
elif y < 145 and y > 120:
mode2 = False
playmode = True
nighttime = True
countdown = True
# hit back button
elif x < 310 and x > 250:
if y < 235 and y > 220:
mode1 = True
mode2 = False
# in play page
elif playmode:
# press the screen
press = True
# terminate the game
def terminate():
pygame.quit()
sys.exit()
# create pressed button effect
def button(x2, y2, width, height, active_color, action = None):
cur = pygame.mouse.get_pos()
if x2 + width > cur[0] > x2 and y2 + height > cur[1] > y2:
s = pygame.Surface((width, height), pygame.SRCALPHA) # per-pixel alpha transparent
s.fill((68,219,52,128)) # notice the alpha value in the color
screen.blit(s, (x2,y2))
else:
pass
# create start page
def start_page():
screen.fill(BLACK)
screen.blit(bg1, (0,0))
# add play button
playbutton = pygame.image.load("play_button2.png")
screen.blit(playbutton,(10,130))
# add pressed button effect 3 times
button(10,130,150,25,[68,219,52]) # play button
button(10,155,150,25,[68,219,52]) # score board button
button(10,180,150,25,[68,219,52]) # instruction button
my_font = pygame.font.Font("ComicSansMS3.ttf",18)
text_surface = my_font.render("Play", True, BLACK)
rect = text_surface.get_rect(center = (85, 142))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",18)
text_surface = my_font.render("Score Board", True, BLACK)
rect = text_surface.get_rect(center = (85, 167))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",18)
text_surface = my_font.render("Instruction", True, BLACK)
rect = text_surface.get_rect(center = (85, 192))
screen.blit(text_surface, rect)
button(250,220,60,15,[68,219,52]) # back button
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface = my_font.render("Quit", True, BLACK)
rect = text_surface.get_rect(center = (280, 227.5))
screen.blit(text_surface, rect)
pygame.display.flip()
# create score board page
def scoreboard_page():
screen.fill(BLACK)
screen.blit(bg3, (0,0))
button(250,220,60,15,[68,219,52]) # back button
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface = my_font.render("Back", True, BLACK)
rect = text_surface.get_rect(center = (280, 227.5))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",15)
text_surface = my_font.render("Ranking", True, BLACK)
rect = text_surface.get_rect(center = (55, 15))
screen.blit(text_surface, rect)
text_surface = my_font.render("User Name", True, BLACK)
rect = text_surface.get_rect(center = (155, 15))
screen.blit(text_surface, rect)
text_surface = my_font.render("Score", True, BLACK)
rect = text_surface.get_rect(center = (255, 15))
screen.blit(text_surface, rect)
# create 10 numbers
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
for i in range(10):
s = str(i+1)
text_surface = my_font.render(s, True, BLACK)
rect = text_surface.get_rect(center = (55, 35+i*20))
screen.blit(text_surface, rect)
# store the sorted json file content
score_list = readRecord()
for j in range(len(score_list)):
# add user name to each ranking
text_surface = my_font.render(score_list[j][1], True, BLACK)
rect = text_surface.get_rect(center = (155, 35 + j*20))
screen.blit(text_surface, rect)
# add score to each ranking
text_surface = my_font.render(str(score_list[j][0]), True, BLACK)
rect = text_surface.get_rect(center = (255, 35 + j*20))
screen.blit(text_surface, rect)
pygame.display.flip()
# read backend json file
def readRecord():
global json_file, name_list, score_list
json_file = 'record.json'
score_list = []
# read json file
with open(json_file, 'r') as infile:
try:
jsonlist = json.load(infile)
except:
jsonlist = []
# store the json file content
score_list = jsonlist['Record']
return score_list
# sort function
def sortRecord(elem):
return elem[0]
# write to the json file
def writeRecord(score):
global json_file, name_list, score_list
json_file = 'record.json'
# open the json file
with open(json_file, 'r') as infile:
try:
jsonlist = json.load(infile)
except:
jsonlist = []
# add new netid-score pair to the json file
jsonlist['Record'].append([score,username])
# sort the json file
jsonlist['Record'].sort(key=sortRecord, reverse = True)
# delete useless data
if len(jsonlist['Record']) > 10:
del jsonlist['Record'][10]
# write to json file
with open(json_file, 'w') as outfile:
json.dump(jsonlist, outfile)
# get keyboard value
def get_key():
while True:
event = pygame.event.poll()
if event.type == KEYDOWN:
return event.key
else:
pass
# display the user input to the screen
def display_box(message):
screen.fill(BLACK)
screen.blit(bg2, (0,0))
my_font = pygame.font.Font("ComicSansMS3.ttf",15)
# draw two rectangles as type in box
pygame.draw.rect(screen, (0,0,0),(10,110,150,25),1)
pygame.draw.rect(screen, (255,255,255),(8,108,154,29),1)
# draw the user input as string to screen
if len(message) != 0:
screen.blit(my_font.render(message, True, BLACK),(10,110))
pygame.display.flip()
# manage the user input
def ask():
current_string = []
question = "NetID: "
display_box(question + string.join(current_string,""))
while True:
inkey = get_key()
if inkey == K_BACKSPACE:
# delete last charactor
current_string = current_string[0:-1]
# hit enter button
elif inkey == K_RETURN:
break
# get "_" symbol
elif inkey == K_MINUS:
current_string.append("_")
# get charactors and numbers
elif (inkey <= 122 and inkey >= 97) or (inkey <= 90 and inkey >= 65) or (inkey <= 57 and inkey >= 48):
current_string.append(chr(inkey))
display_box(question + string.join(current_string,""))
return string.join(current_string,"")
# get username
def mode_username():
global username
username = ask()
# instrction page
def instruction_page():
screen.fill(BLACK)
screen.blit(bg4, (0,0))
button(250,220,60,15,[68,219,52]) # back button
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface = my_font.render("Back", True, BLACK)
rect = text_surface.get_rect(center = (280, 227.5))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",15)
text_surface = my_font.render("How to play?", True, BLACK)
rect = text_surface.get_rect(center = (155, 15))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",12)
text_surface = my_font.render("Single player", True, BLACK)
rect = text_surface.get_rect(center = (50, 30))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",12)
text_surface = my_font.render("Double player", True, BLACK)
rect = text_surface.get_rect(center = (52, 95))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",11)
text_surface = my_font.render("player", True, BLACK)
rect = text_surface.get_rect(center = (62, 55))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",11)
text_surface = my_font.render("player 1", True, BLACK)
rect = text_surface.get_rect(center = (65, 117))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",11)
text_surface = my_font.render("player 2", True, BLACK)
rect = text_surface.get_rect(center = (65, 163))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",11)
text_surface = my_font.render("or", True, BLACK)
rect = text_surface.get_rect(center = (117, 55))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",11)
text_surface = my_font.render("pause", True, BLACK)
rect = text_surface.get_rect(center = (190, 55))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",11)
text_surface = my_font.render("pause", True, BLACK)
rect = text_surface.get_rect(center = (190, 127))
screen.blit(text_surface, rect)
pygame.display.flip()
# single/dual player selection page
def mode_player():
screen.fill(BLACK)
screen.blit(bg2, (0,0))
# load the background
playbutton = pygame.image.load("play_button.png")
screen.blit(playbutton,(10,95))
button(10,95,150,25,[68,219,52]) # single player button
button(10,120,150,25,[68,219,52]) # dual player button
my_font = pygame.font.Font("ComicSansMS3.ttf",15)
text_surface = my_font.render("Single Player", True, BLACK)
rect = text_surface.get_rect(center = (85, 107))
screen.blit(text_surface, rect)
text_surface = my_font.render("Duel Player", True, BLACK)
rect = text_surface.get_rect(center = (85, 132))
screen.blit(text_surface, rect)
button(250,220,60,15,[68,219,52]) # back button
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface = my_font.render("Back", True, BLACK)
rect = text_surface.get_rect(center = (280, 227.5))
screen.blit(text_surface, rect)
pygame.display.flip()
# day/night selection page
def mode_daynight():
screen.fill(BLACK)
screen.blit(bg2, (0,0))
# load the background
playbutton = pygame.image.load("play_button.png")
screen.blit(playbutton,(10,95))
button(10,95,150,25,[68,219,52]) # daytime mode
button(10,120,150,25,[68,219,52]) # night mode
my_font = pygame.font.Font("ComicSansMS3.ttf",18)
text_surface = my_font.render("Daytime", True, BLACK)
rect = text_surface.get_rect(center = (85, 107))
screen.blit(text_surface, rect)
my_font = pygame.font.Font("ComicSansMS3.ttf",18)
text_surface = my_font.render("Night", True, BLACK)
rect = text_surface.get_rect(center = (85, 132))
screen.blit(text_surface, rect)
button(250,220,60,15,[68,219,52]) # back button
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface = my_font.render("Back", True, BLACK)
rect = text_surface.get_rect(center = (280, 227.5))
screen.blit(text_surface, rect)
pygame.display.flip()
# pause the game
def pause(stop):
my_font = pygame.font.Font('ComicSansMS3.ttf',90)
text_surface = my_font.render("Paused", True, BLACK)
rect = text_surface.get_rect(center = (150, 107))
screen.blit(text_surface, rect)
while stop:
for event in pygame.event.get():
# quit the game
if event.type == pygame.QUIT:
pygame.quit()
quit()
pygame.display.update()
clock.tick(15)
# un pause the game
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
stop = False
# create ramdom pipe with fixed gap
def getRandomPipe(PIPEGAPSIZE):
gapY = random.randrange(0, int(BASEY * 0.6 - PIPEGAPSIZE))
gapY += int(BASEY * 0.2)
pipeHeight = IMAGES['pipe'][0].get_height()
pipeX = SCREENWIDTH + 15
return [
{'x': pipeX, 'y': gapY - pipeHeight},
{'x': pipeX, 'y': gapY + PIPEGAPSIZE},
]
# play page
def play_mode(score, life):
# load different background in different mode
if daytime:
bg = pygame.image.load('background.jpg')
if singlePlayer:
bird = pygame.image.load("bird.png")
bird2 = pygame.image.load("bird2.png")
bird3 = pygame.image.load("bird3.png")
elif duelPlayer:
bird = pygame.image.load("bird.png")
bird2 = pygame.image.load("bird2.png")
elif nighttime:
bg = pygame.image.load('background2.jpg')
if singlePlayer:
bird = pygame.image.load("bird2.png")
bird2 = pygame.image.load("bird.png")
bird3 = pygame.image.load("bird3.png")
elif duelPlayer:
bird = pygame.image.load("bird2.png")
bird2 = pygame.image.load("bird.png")
# initialize variables
rectImg = bg.get_rect()
bgY1 = 0
bgX1 = 0
bgY2 = 0
bgX2 = rectImg.width
win = 0
live1 = True
live2 = True
location = (77, 120)
location2 = (77, 100)
count = 15
press = True
stop = False
score = 0
score2 = 0
PIPEGAPSIZE = 80
movingLeftSpeed = 2
# add score display
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface1 = my_font.render("Score 1:", True, WHITE)
rect1 = text_surface1.get_rect(center = (30, 15))
my_font = pygame.font.Font("ComicSansMS3.ttf",10)
s = str(score)
text_surface2 = my_font.render(s, True, WHITE)
rect2 = text_surface2.get_rect(center = (60, 15))
# add another score display
if duelPlayer:
my_font = pygame.font.Font("ComicSansMS3.ttf",13)
text_surface3 = my_font.render("Score 2:", True, WHITE)
rect3 = text_surface3.get_rect(center = (30, 37.5))
my_font = pygame.font.Font("ComicSansMS3.ttf",10)
s = str(score2)
text_surface4 = my_font.render(s, True, WHITE)
rect4 = text_surface4.get_rect(center = (60, 37.5))
birdRect2 = bird2.get_rect(center = location2)
# load heart image
heart = pygame.image.load("heart.png")
birdRect = bird.get_rect(center = location)
centerx = screenSize[0] / 2
centery = screenSize[1] / 2
speed = 5
# load pipe image in different mode
if daytime:
IMAGES['pipe'] = (
pygame.transform.rotate(pygame.image.load('pipe.png').convert_alpha(), 180),
pygame.image.load('pipe.png').convert_alpha(),
)
if nighttime:
IMAGES['pipe'] = (
pygame.transform.rotate(pygame.image.load('pipe2.png').convert_alpha(), 180),
pygame.image.load('pipe2.png').convert_alpha(),
)
# create two pairs of random pipe with fixed gap size
newPipe1 = getRandomPipe(PIPEGAPSIZE)
newPipe2 = getRandomPipe(PIPEGAPSIZE)
# set the locations of two upper pipes
upperPipes = [
{'x': SCREENWIDTH, 'y': newPipe1[0]['y']},
{'x': SCREENWIDTH+160, 'y': newPipe2[0]['y']},
]
# set locations of two lower pipes
lowerPipes = [
{'x': SCREENWIDTH, 'y': newPipe1[1]['y']},
{'x': SCREENWIDTH+160, 'y': newPipe2[1]['y']},
]
# initialize moving directions
moveLeft, moveRight, moveUp, moveDown, Jump = False, False, False, False, False
moveLeft2, moveRight2, moveUp2, moveDown2 = False, False, False, False
# erase the screen and load the background
screen.fill(BLACK)
screen.blit(bg,rectImg)
# load second score and bird for dual player mode
if duelPlayer:
screen.blit(text_surface3, rect3)
screen.blit(text_surface4, rect4)
screen.blit(bird2,birdRect2)
# load score and bird for single player mode
screen.blit(text_surface1, rect1)
screen.blit(text_surface2, rect2)
screen.blit(bird,birdRect)
pygame.display.flip()
if flags:
while True:
# set the delay
clock.tick(FPS)
# set the shifting left speed, upper boundary is 4
if movingLeftSpeed < 4:
movingLeftSpeed = movingLeftSpeed + 0.0001
else:
movingLeftSpeed = 4
if PIPEGAPSIZE > 65:
PIPEGAPSIZE -= 0.05
else:
PIPEGAPSIZE = 65
for event in pygame.event.get():
# when touch the screen, store this action
if(event.type is MOUSEBUTTONDOWN) and singlePlayer:
Jump = True
press = False
if(event.type is MOUSEBUTTONUP) and singlePlayer:
Jump = False
press = True
# quit game
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN:
# quit the game
if event.key == pygame.K_ESCAPE:
terminate()
# move up the bird
if event.key == pygame.K_UP:
moveUp = True
moveDown = False
# move down the bird
if event.key == pygame.K_DOWN:
moveUp = False
moveDown = True
# move up the second bird
if event.key == pygame.K_w:
moveUp2 = True
moveDown2 = False
# move down the second bird
if event.key == pygame.K_s:
moveUp2 = False
moveDown2 = True
# pause the game
if event.key == pygame.K_SPACE:
stop = True
pause(stop)
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
moveUp = False
if event.key == pygame.K_DOWN:
moveDown = False
if event.key == pygame.K_w:
moveUp2 = False
if event.key == pygame.K_s:
moveDown2 = False
birdRect.left,birdRect.bottom = location
if duelPlayer:
birdRect2.left,birdRect2.bottom = location2
# shift the background to left with increasing speed
bgX1 -= movingLeftSpeed
bgX2 -= movingLeftSpeed
# if reach the left boundary, reset the background
if bgX1 <= -rectImg.width:
bgX1 = rectImg.width
if bgX2 <= -rectImg.width:
bgX2 = rectImg.width
# move up the bird with fixed height, play the sound
if moveUp and birdRect.top > 0:
birdRect.centery -= speed
SOUNDS['wing'].play()
# move down the bird with fixed height
if moveDown and birdRect.bottom < screenSize[1] - 1:
birdRect.centery += 8
# move up the bird with fixed height
if moveUp2 and birdRect2.top > 0:
birdRect2.centery -= speed
# move down the bird with fixed height
if moveDown2 and birdRect2.bottom < screenSize[1] - 1:
birdRect2.centery += 8
# move up the bird when touch the screen, play the sound
if Jump and birdRect.top > 0:
birdRect.centery -= 2.5
SOUNDS['wing'].play()
# if no action made, bird will fall with fixed speed
if life != 0 and singlePlayer and not press:
birdRect.bottom = birdRect.bottom + 1
location = (birdRect.left,birdRect.bottom)
startAgain = False
press = True
elif life != 0 and singlePlayer and press:
startAgain = False
if count != 0:
birdRect.bottom = birdRect.bottom + 1
location = (birdRect.left,birdRect.bottom)
count = count - 1
else:
count = 15
press = False
# if no action made, first bird will fall with fixed speed
if live1 and duelPlayer:
birdRect.bottom = birdRect.bottom + 1
location = (birdRect.left,birdRect.bottom)
# if no action made, second bird will fall with fixed speed
if live2 and duelPlayer:
birdRect2.bottom = birdRect2.bottom + 1
location2 = (birdRect2.left,birdRect2.bottom)
# if bird hit the ground, lose one life and start the game again
if birdRect.bottom > 215 and singlePlayer and not startAgain:
SOUNDS['hit'].play()
life = life - 1
startAgain = True
birdRect.bottom = 120
birdRect.left = 77
location = (birdRect.left,birdRect.bottom)
upperPipes = {}
lowerPipes = {}
# generate two random pairs of pipes again
newPipe1 = getRandomPipe(PIPEGAPSIZE)
newPipe2 = getRandomPipe(PIPEGAPSIZE)
upperPipes = [{'x': SCREENWIDTH, 'y': newPipe1[0]['y']},
{'x': SCREENWIDTH+160, 'y': newPipe2[0]['y']},]
lowerPipes = [{'x': SCREENWIDTH, 'y': newPipe1[1]['y']},
{'x': SCREENWIDTH+160, 'y': newPipe2[1]['y']},]
time.sleep(2)
# if the first bird hit the ground, remove the first bird from the screen
if birdRect.bottom > 215 and duelPlayer:
SOUNDS['hit'].play()
live1 = False
birdRect.bottom = -20
birdRect.left = -20
location = (birdRect.left,birdRect.bottom)
if win == 0:
win = 2
# if the second bird hit the ground, remove the first bird from the screen
if birdRect.bottom > 215 and duelPlayer:
SOUNDS['hit'].play()
live2 = False
birdRect2.bottom = -20
birdRect2.left = -20
location2 = (birdRect2.left,birdRect2.bottom)
if win == 0:
win = 1
screen.blit(bg, (bgX1, bgY1))
screen.blit(bg, (bgX2, bgY2))
# shift the pipes to the left with increasing speed
for uPipe, lPipe in zip(upperPipes, lowerPipes):
uPipe['x'] -= movingLeftSpeed
lPipe['x'] -= movingLeftSpeed
if len(upperPipes) != 0:
# if one pipe is shifted to the left boundary of the scrren, add a new pipe
if 0 < upperPipes[0]['x'] < movingLeftSpeed:
newPipe = getRandomPipe(PIPEGAPSIZE)
upperPipes.append(newPipe[0])
lowerPipes.append(newPipe[1])
# increment life for two player if alive
if live1:
score += 1
if live2:
score2 += 1
SOUNDS['point'].play()
# remove one pair of pipe when gets to the left boundary
if upperPipes[0]['x'] < -IMAGES['pipe'][0].get_width():
upperPipes.pop(0)
lowerPipes.pop(0)
# get the pipe height and width
pipeW = IMAGES['pipe'][0].get_width()
pipeH = IMAGES['pipe'][0].get_height()
for uPipe, lPipe in zip(upperPipes, lowerPipes):
# get the rects of two birds
birdRect = bird.get_rect(center = location)
birdRect2 = bird2.get_rect(center = location2)
# get the rects of one pair of pipes
uPipeRect = pygame.Rect(uPipe['x'], uPipe['y'], pipeW, pipeH)
lPipeRect = pygame.Rect(lPipe['x'], lPipe['y'], pipeW, pipeH)
screen.blit(IMAGES['pipe'][0], (uPipe['x'], uPipe['y']))
screen.blit(IMAGES['pipe'][1], (lPipe['x'], lPipe['y']))
# bird rect hit pipr rect, lose one life, start the game again
if singlePlayer and (uPipeRect.colliderect(birdRect) or lPipeRect.colliderect(birdRect)):
SOUNDS['hit'].play()
life = life - 1
startAgain = True
birdRect.bottom = 120
birdRect.left = 77
location = (birdRect.left,birdRect.bottom)
upperPipes = {}
lowerPipes = {}
newPipe1 = getRandomPipe(PIPEGAPSIZE)
newPipe2 = getRandomPipe(PIPEGAPSIZE)
upperPipes = [{'x': SCREENWIDTH, 'y': newPipe1[0]['y']},
{'x': SCREENWIDTH+160, 'y': newPipe2[0]['y']},]
lowerPipes = [{'x': SCREENWIDTH, 'y': newPipe1[1]['y']},
{'x': SCREENWIDTH+160, 'y': newPipe2[1]['y']},]
time.sleep(2)
break
# if first bird hit the pipe, remove the first bird
if duelPlayer and live1 and (uPipeRect.colliderect(birdRect) or lPipeRect.colliderect(birdRect)):
SOUNDS['hit'].play()
live1 = False
birdRect.bottom = -20
birdRect.left = -20
location = (birdRect.left,birdRect.bottom)
if win == 0:
win = 2
# if second bird hit the pipe, remove the second bird
if duelPlayer and live2 and (uPipeRect.colliderect(birdRect2) or lPipeRect.colliderect(birdRect2)):
SOUNDS['hit'].play()
live2 = False
birdRect2.bottom = -20
birdRect2.left = -20
location2 = (birdRect2.left,birdRect2.bottom)
if win == 0:
win = 1
pygame.display.update()
# update the score for first player
s = str(score)
text_surface2 = my_font.render(s, True, WHITE)
rect2 = text_surface2.get_rect(center = (60, 15))
if duelPlayer:
# update the score for second player
s = str(score2)
text_surface4 = my_font.render(s, True, WHITE)
rect4 = text_surface4.get_rect(center = (60, 37.5))
screen.blit(text_surface3, rect3)
screen.blit(text_surface4, rect4)
screen.blit(text_surface1, rect1)
screen.blit(text_surface2, rect2)
# create heart image
if singlePlayer:
for i in range(life):
heartRect = heart.get_rect(center = (17.5+20*i,37.5))
screen.blit(heart,heartRect)
# change the bird image when score is greater or equal to 10
if score <10:
screen.blit(bird,birdRect)
elif score >= 10:
screen.blit(bird3,birdRect)
if duelPlayer:
screen.blit(bird,birdRect)
screen.blit(bird2,birdRect2)
pygame.display.flip()
# if no life left, game over and return to start page. write the netid-score pair to json
if life == 0:
SOUNDS['die'].play()
my_font = pygame.font.Font("ComicSansMS3.ttf",30)
text_surface = my_font.render("Game Over", True, WHITE)
rect = text_surface.get_rect(center = (170, 110))
screen.blit(text_surface, rect)
pygame.display.flip()
startAgain = False
location = (77, 120)
time.sleep(4)
life = 3
writeRecord(score)
main()
if duelPlayer:
# if both birds die, print which player wins
if live1 == False and live2 == False:
if win == 1:
my_font = pygame.font.Font("ComicSansMS3.ttf",30)
text_surface = my_font.render("Player 1 wins", True, WHITE)
rect = text_surface.get_rect(center = (170, 110))
screen.blit(text_surface, rect)
if win == 2:
my_font = pygame.font.Font("ComicSansMS3.ttf",30)
text_surface = my_font.render("Player 2 wins", True, WHITE)
rect = text_surface.get_rect(center = (170, 110))
screen.blit(text_surface, rect)
pygame.display.flip()
time.sleep(4)
main()
if __name__ == '__main__':
main()