2019/04/10 10:10

# 140行代码实现Flippy Bird

1. python main.py运行游戏；
2. 鼠标点击是暂停，再点击则是继续；
3. 空格键进行跳跃；

1. 管道的出现可以更加随机，包括位置和长度等，目前是很简单的方式出现；
2. 游戏速度可以越来越快，目前是固定的；
3. 小鸟的自由落体速度、跳跃速度等需要优化，目前操作感觉没有那么流畅；
4. 增加计分系统、开始、重来等按钮；

## 关键代码分析

### 随时间移动的管道

tunnel_list = [x-speed if x-speed>-200 else 2100 for x in tunnel_list ]

def draw_tunnel():
for x in tunnel_list:
pygame.draw.rect(screen,COLORS['darkgreen'],(x,0,100,350),0)
pygame.draw.rect(screen,COLORS['darkgreen'],(x+100,550,100,350),0)


### 自由落体的小鸟和点击空格后跳起

G = 9.8*30 # g
JUMP_V = -300
bird_x,bird_y = 700,450
bird_v = 0

if not jump:
bird_v += G*frame
else:
bird_v = JUMP_V
jump = False
bird_y += frame*bird_v

def draw_bird():
screen.blit(birdImg,[bird_x,bird_y])


### 碰撞检测

def rect_cover(rect1,rect2,up=True):
# bird
left_up1 = (rect1[0],rect1[1])
left_down1 = (rect1[0],left_up1[1]+rect1[3])
right_up1 = (left_up1[0]+rect1[2],rect1[1])
right_down1 = (left_up1[0]+rect1[2],left_up1[1]+rect1[3])
# tunnel
left_up2 = (rect2[0],rect2[1])
left_down2 = (rect2[0],left_up2[1]+rect2[3])
right_up2 = (left_up2[0]+rect2[2],rect2[1])
right_down2 = (left_up2[0]+rect2[2],left_up2[1]+rect2[3])
# check
if (left_up2[0]<=right_up1[0]<=right_up2[0]): # x,肯定是右侧线接触，因此判断bird的right即可
if up and (left_up2[1]<=right_up1[1]<=left_down2[1]):
return True
elif (not up) and (left_up2[1]<=right_down1[1]<=left_down2[1]):
return True
return False


### pygame绘制rect不支持透明度下实现的透明图层

def draw_dead():
s = pygame.Surface(SIZE, pygame.SRCALPHA)
s.fill((255,255,255,240))
screen.blit(s, (0,0))
x,y = 450,400
screen.blit(txt,(x,y))


## 全部代码

import sys

import pygame
from pygame.color import THECOLORS as COLORS

def draw_background():
# white background
screen.fill(COLORS['lightblue'])
pygame.draw.rect(screen,COLORS['black'],(-100,902,3000,200),5)

def draw_tunnel():
for x in tunnel_list:
pygame.draw.rect(screen,COLORS['darkgreen'],(x,0,100,350),0)
pygame.draw.rect(screen,COLORS['darkgreen'],(x+100,550,100,350),0)

def draw_bird():
screen.blit(birdImg,[bird_x,bird_y])

def draw_context():
txt = font50.render('Count time: '+str(int(count_time))+' S',True,COLORS['black'])
x,y = 10,920
screen.blit(txt,(x,y))

def draw_pause():
s = pygame.Surface(SIZE, pygame.SRCALPHA)
s.fill((255,255,255,220))
screen.blit(s, (0,0))
txt = font120.render('PAUSE',True,COLORS['darkgray'])
x,y = 550,400
screen.blit(txt,(x,y))

s = pygame.Surface(SIZE, pygame.SRCALPHA)
s.fill((255,255,255,240))
screen.blit(s, (0,0))
x,y = 450,400
screen.blit(txt,(x,y))

def rect_cover(rect1,rect2,up=True):
# bird
left_up1 = (rect1[0],rect1[1])
left_down1 = (rect1[0],left_up1[1]+rect1[3])
right_up1 = (left_up1[0]+rect1[2],rect1[1])
right_down1 = (left_up1[0]+rect1[2],left_up1[1]+rect1[3])
# tunnel
left_up2 = (rect2[0],rect2[1])
left_down2 = (rect2[0],left_up2[1]+rect2[3])
right_up2 = (left_up2[0]+rect2[2],rect2[1])
right_down2 = (left_up2[0]+rect2[2],left_up2[1]+rect2[3])
# check
if (left_up2[0]<=right_up1[0]<=right_up2[0]): # x,肯定是右侧线接触，因此判断bird的right即可
if up and (left_up2[1]<=right_up1[1]<=left_down2[1]):
return True
elif (not up) and (left_up2[1]<=right_down1[1]<=left_down2[1]):
return True
return False

bird_rect = (bird_x,bird_y,70,70)
if bird_rect[1]+bird_rect[3]>900:
return True
for x in tunnel_list:
up_rect = (x,0,100,350)
down_rect = (x+100,550,100,350)
if rect_cover(bird_rect,up_rect) or rect_cover(bird_rect,down_rect,up=False):
return True
return False

if __name__ == "__main__":
# init pygame
pygame.init()

# contant
SIZE = [1500,1000]
font50 = pygame.font.SysFont('Times', 50)
font120 = pygame.font.SysFont('Times', 120)
G = 9.8*30 # g
JUMP_V = -300

# brid
birdPath = 'bird.png'

# tunnel
tunnel_list = [100,600,1100,1600,2100]

# create screen 500*500
screen = pygame.display.set_mode(SIZE)

# variable parameter
bird_x,bird_y = 700,450
bird_v = 0
count_time = 0

# level
speed = 5
frame = 0.02

# main loop
running = True
pause = False
jump = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
break
elif event.type == pygame.MOUSEBUTTONDOWN:
pause = not pause
elif event.type == pygame.KEYUP:
if chr(event.key) == ' ':
jump = True

# update data
if not pause and not dead:
count_time += frame
tunnel_list = [x-speed if x-speed>-200 else 2100 for x in tunnel_list ]

if not jump:
bird_v += G*frame
else:
bird_v = JUMP_V
jump = False
bird_y += frame*bird_v

# background
draw_background()
# tunnel
draw_tunnel()
# choose item
draw_bird()
# point
draw_context()
# pause
draw_pause()
# flip
pygame.display.flip()

# pause 20ms
pygame.time.delay(int(frame*1000))

# check win or not
#break

pygame.quit()


0
0 收藏

0 评论
0 收藏
0