一、实验目的
以经典的飞机大战代码为参考,实现食物在舍友之间的单向传递,共有三次失误机会,机会全部用完后则视为游戏失败。
二、游戏操作
舍友一:A:向左移动,D:向右移动
舍友二:左方向键:向左移动,右方向键:向右移动
空格键:向对面的舍友发射食物
三、游戏成品
四、游戏代码
import sys
import pygame
import time
import setting
pygame.init()
#主窗口
scene_image = pygame.display.set_mode((800,600))
scene_rect = scene_image.get_rect()
scene_image.fill(setting.color_1)
#标题栏
pygame.display.set_caption("双人成行")
zhangjin_image = pygame.image.load('zhangjin.bmp')
zhangjin_image = pygame.transform.scale(zhangjin_image,(90,80))
zhangjin_image = pygame.transform.rotate(zhangjin_image,90)
zhangjin_rect = zhangjin_image.get_rect()
zhangjin_rect.midtop = scene_rect.midtop
zhangjin_rect.y = scene_rect.y+20
liyi_image = pygame.image.load('liyi.bmp')
liyi_image = pygame.transform.scale(liyi_image,(90,80)) #更改liyi大小
liyi_rect = liyi_image.get_rect()
liyi_rect.midbottom = scene_rect.midbottom
liyi_rect.bottom = scene_rect.bottom -20
liyi_moving_left = False
liyi_moving_right = False
zhangjin_moving_left = False
zhangjin_moving_right = False
#食物
foods = pygame.sprite.Group()
# foods = []
lives_isleft = 0
#文字
button_rect = pygame.Rect(0,0,200,50)
button_rect.center = scene_rect.center
play_font = pygame.font.SysFont(None,48)
play_image = play_font.render("play",True,setting.color_2,setting.color_3)
play_rect = play_image.get_rect()
play_rect.center = button_rect.center
#统计信息
score = 0
food_points = 1
score_str = str(score)
score_font = pygame.font.SysFont(None,36)
score_image = score_font.render(f"recent score:{score_str}",True,setting.color_3,setting.color_1)
score_rect = score_image.get_rect()
score_rect.right = scene_rect.right - 20
score_rect.top = 20
scene_image.blit(score_image,score_rect)
high_score = 0
high_score_str = str(high_score)
high_score_font = pygame.font.SysFont(None,36)
high_score_image = high_score_font.render(f"highest score:{high_score_str}",True,setting.color_3,setting.color_1)
high_score_rect = high_score_image.get_rect()
high_score_rect.midtop =score_rect.midbottom
high_score_rect.right = score_rect.right
scene_image.blit(high_score_image,high_score_rect)
pygame.display.flip()
#剩余可不吃
zhuzi_group = pygame.sprite.Group()
for zhuzi_number in range(setting.zhuzi_limit - 1):
zhuzi = pygame.sprite.Sprite()
zhuzi.image = pygame.image.load('zhuzi.bmp')
zhuzi.image = pygame.transform.scale(zhuzi.image, (45, 40))
zhuzi.rect = zhuzi.image.get_rect()
zhuzi.rect.x = 5+(zhuzi.rect.width + 5) * zhuzi_number
zhuzi.rect.y = 5
zhuzi_group.add(zhuzi)
zhuzi_group.draw(scene_image)
while True:
pygame.mixer.music.play(-1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
liyi_moving_left = True
if event.key == pygame.K_RIGHT:
liyi_moving_right = True
if event.key == pygame.K_a:
zhangjin_moving_left = True
if event.key == pygame.K_d:
zhangjin_moving_right = True
if event.key == pygame.K_q:
sys.exit()
if event.key == pygame.K_SPACE:
if len(foods) < setting.foods_number:
food = pygame.sprite.Sprite()
f = pygame.image.load('food.bmp')
f = pygame.transform.scale(f, (20, 20))
food.rect = f.get_rect()
food.image = f
food.rect.midbottom = liyi_rect.midtop
foods.add(food)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
liyi_moving_left = False
if event.key == pygame.K_RIGHT:
liyi_moving_right = False
if event.key == pygame.K_a:
zhangjin_moving_left = False
if event.key == pygame.K_d:
zhangjin_moving_right = False
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
if button_rect.collidepoint(mouse_pos):
lives_isleft = setting.zhuzi_limit
pygame.mouse.set_visible(False)
foods.empty()
if lives_isleft > 0:
if liyi_moving_left and liyi_rect.left > 0:
liyi_rect.x -= setting.speed
if liyi_moving_right and liyi_rect.right < scene_rect.right:
liyi_rect.x += setting.speed
if zhangjin_moving_left and zhangjin_moving_left > 0:
zhangjin_rect.x -= setting.speed
if zhangjin_moving_right and zhangjin_moving_right < scene_rect.right:
zhangjin_rect.x += setting.speed
zhangjin_sprite = pygame.sprite.Sprite()
zhangjin_sprite.rect = zhangjin_rect
zhangjin_sprite.image = zhangjin_image
scene_image.fill(setting.color_1)
scene_image.blit(zhangjin_image, zhangjin_rect)
scene_image.blit(liyi_image, liyi_rect)
# 张锦没吃上food
for item in foods:
item.rect.y -= setting.speed
if item.rect.bottom < 0:
lives_isleft -= 1
foods.remove(item)
scene_image.blit(food.image, item)
if lives_isleft == 0:
# time.sleep(0.5)
liyi_rect.bottom = scene_rect.bottom - 20
zhangjin_rect.y = scene_rect.y + 20
foods.empty()
# 张锦
zhangjin_rect = zhangjin_image.get_rect()
zhangjin_rect.midtop = scene_rect.midtop
zhangjin_rect.y = scene_rect.y + 20
# 李毅
liyi_rect = liyi_image.get_rect()
liyi_rect.midbottom = scene_rect.midbottom
liyi_rect.bottom = scene_rect.bottom - 20
#张锦和food碰撞
if pygame.sprite.spritecollide(zhangjin_sprite,foods,True):
score += 1
if score > high_score:
high_score = score
# 统计信息
score_str = str(score)
score_font = pygame.font.SysFont(None, 36)
score_image = score_font.render(f"recent score:{score_str}", True, setting.color_3, setting.color_1)
score_rect = score_image.get_rect()
score_rect.right = scene_rect.right - 20
score_rect.top = 20
scene_image.blit(score_image, score_rect)
high_score_str = str(high_score)
high_score_font = pygame.font.SysFont(None, 36)
high_score_image = high_score_font.render(f"highest score:{high_score_str}", True, setting.color_3,
setting.color_1)
high_score_rect = high_score_image.get_rect()
high_score_rect.midtop = score_rect.midbottom
high_score_rect.right = score_rect.right
scene_image.blit(high_score_image, high_score_rect)
pygame.display.flip()
# 剩余可不吃
zhuzi_group = pygame.sprite.Group()
for zhuzi_number in range(lives_isleft - 1):
zhuzi = pygame.sprite.Sprite()
zhuzi.image = pygame.image.load('zhuzi.bmp')
zhuzi.image = pygame.transform.scale(zhuzi.image, (45, 40))
zhuzi.rect = zhuzi.image.get_rect()
zhuzi.rect.x = 5 + (zhuzi.rect.width + 5) * zhuzi_number
zhuzi.rect.y = 5
zhuzi_group.add(zhuzi)
zhuzi_group.draw(scene_image)
else:
pygame.draw.rect(scene_image,setting.color_4,button_rect)
scene_image.blit(play_image,play_rect)
pygame.mouse.set_visible(True)
score = 0
pygame.display.flip()
time.sleep(setting.time)
五、分段解析
1、实现长按方向键连续移动
liyi_moving_left = False
liyi_moving_right = False
zhangjin_moving_left = False
zhangjin_moving_right = False
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
liyi_moving_left = True
if event.key == pygame.K_RIGHT:
liyi_moving_right = True
if event.key == pygame.K_a:
zhangjin_moving_left = True
if event.key == pygame.K_d:
zhangjin_moving_right = True
if event.key == pygame.K_q:
sys.exit()
if event.key == pygame.K_SPACE:
if len(foods) < setting.foods_number:
food = pygame.sprite.Sprite()
f = pygame.image.load('food.bmp')
f = pygame.transform.scale(f, (20, 20))
food.rect = f.get_rect()
food.image = f
food.rect.midbottom = liyi_rect.midtop
foods.add(food)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
liyi_moving_left = False
if event.key == pygame.K_RIGHT:
liyi_moving_right = False
if event.key == pygame.K_a:
zhangjin_moving_left = False
if event.key == pygame.K_d:
zhangjin_moving_right = False
if liyi_moving_left and liyi_rect.left > 0:
liyi_rect.x -= setting.speed
if liyi_moving_right and liyi_rect.right < scene_rect.right:
liyi_rect.x += setting.speed
if zhangjin_moving_left and zhangjin_moving_left > 0:
zhangjin_rect.x -= setting.speed
if zhangjin_moving_right and zhangjin_moving_right < scene_rect.right:
zhangjin_rect.x += setting.speed
根据pygame中event.get()函数对键盘,鼠标等动作的捕捉,可以初步实现一令一动的目的。但是要实现连续移动,就要设置moving_right,moving_left两个阀门,当其为true的时候,x轴位置可以连续发生改变
2、按钮以及文本的显示实现
button_rect = pygame.Rect(0,0,200,50)
button_rect.center = scene_rect.center
play_font = pygame.font.SysFont(None,48)
play_image = play_font.render("play",True,setting.color_2,setting.color_3)
play_rect = play_image.get_rect()
play_rect.center = button_rect.center
#变量的赋值
pygame.draw.rect(scene_image,setting.color_4,button_rect)
scene_image.blit(play_image,play_rect)
#参数的调用
pygame中的文本是以image格式实现,rect规定了大小以及位置信息,image则代表了内容(对于文字来说就是文字颜色,背景色,文本内容等信息,对于图片来说就是图片地址)
3、鼠标的隐藏和出现
pygame.mouse.set_visible(False)
set_Visible函数中参数False代表鼠标消失,True代表鼠标出现
4、统计信息的实现方法
#统计信息
score = 0
food_points = 1
score_str = str(score)
score_font = pygame.font.SysFont(None,36)
score_image = score_font.render(f"recent score:{score_str}",True,setting.color_3,setting.color_1)
score_rect = score_image.get_rect()
score_rect.right = scene_rect.right - 20
score_rect.top = 20
scene_image.blit(score_image,score_rect)
high_score = 0
high_score_str = str(high_score)
high_score_font = pygame.font.SysFont(None,36)
high_score_image = high_score_font.render(f"highest score:{high_score_str}",True,setting.color_3,setting.color_1)
high_score_rect = high_score_image.get_rect()
high_score_rect.midtop =score_rect.midbottom
high_score_rect.right = score_rect.right
scene_image.blit(high_score_image,high_score_rect)
pygame.display.flip()
while true:
#张锦和food碰撞
if pygame.sprite.spritecollide(zhangjin_sprite,foods,True):
score += 1
if score > high_score:
high_score = score
# 统计信息
score_str = str(score)
score_font = pygame.font.SysFont(None, 36)
score_image = score_font.render(f"recent score:{score_str}",True,setting.color_3, setting.color_1)
score_rect = score_image.get_rect()
score_rect.right = scene_rect.right - 20
score_rect.top = 20
scene_image.blit(score_image, score_rect)
high_score_str = str(high_score)
high_score_font = pygame.font.SysFont(None, 36)
high_score_image = high_score_font.render(f"highest score:{high_score_str}",True, setting.color_3,setting.color_1)
high_score_rect = high_score_image.get_rect()
high_score_rect.midtop = score_rect.midbottom
high_score_rect.right = score_rect.right
scene_image.blit(high_score_image, high_score_rect)
pygame.display.flip()
用image规定文本内容,用rect规定文本的出现坐标,当舍友头像与食物发生碰撞的时候,说明成功进食,所以score加1,当当前分数高于最高分时,将目前分数赋值给最高分,每次重新开始游戏前将score归零
5、当出现没有及时享用的食物到达边框
zhuzi_group = pygame.sprite.Group()
for zhuzi_number in range(lives_isleft - 1):
zhuzi = pygame.sprite.Sprite()
zhuzi.image = pygame.image.load('zhuzi.bmp')
zhuzi.image = pygame.transform.scale(zhuzi.image, (45, 40))
zhuzi.rect = zhuzi.image.get_rect()
zhuzi.rect.x = 5 + (zhuzi.rect.width + 5) * zhuzi_number
zhuzi.rect.y = 5
zhuzi_group.add(zhuzi)
zhuzi_group.draw(scene_image)
左上角生命值减一(注:左上角生命+1为总生命值)
6、屏幕中最多出现十个食物
foods_number = 10
if event.key == pygame.K_SPACE:
if len(foods) < foods_number:
food = pygame.sprite.Sprite()
f = pygame.image.load('food.bmp')
f = pygame.transform.scale(f, (20, 20))
food.rect = f.get_rect()
food.image = f
food.rect.midbottom = liyi_rect.midtop
foods.add(food)
for item in foods:
item.rect.y -= setting.speed
if item.rect.bottom < 0:
lives_isleft -= 1
foods.remove(item)
scene_image.blit(food.image, item)
if lives_isleft == 0:
# time.sleep(0.5)
liyi_rect.bottom = scene_rect.bottom - 20
zhangjin_rect.y = scene_rect.y + 20
foods.empty()
# 张锦
zhangjin_rect = zhangjin_image.get_rect()
zhangjin_rect.midtop = scene_rect.midtop
zhangjin_rect.y = scene_rect.y + 20
# 李毅
liyi_rect = liyi_image.get_rect()
liyi_rect.midbottom = scene_rect.midbottom
liyi_rect.bottom = scene_rect.bottom - 20
食物最终有两种状态,当被舍友享用之后score加一,反之,到达边界后,生命值减一,并且将其移出食物所在列表,保持屏幕上最多有十个食物的规定。如果生命值耗费完,将页面恢复为最初的样子,且出现可重新开始游戏的字样。
完结撒花!