这个程序是一个简单的足球射门游戏,它使用Python的pgzrun
库来创建和管理游戏界面。游戏的目标是通过控制一个球员(皮皮)来踢五个球,并将它们射入球门。如果所有球都成功射入球门,则玩家获胜;否则,玩家失败。下面是对这个程序设计思路的总结分析,以及一个编程故事来讲解这个项目。
设计思路
初始化游戏元素:
- 使用字典
pics
来跟踪每个球是否已经被踢过。 - 定义全局变量
press_key
、kick_flag
、shoot
和score
来控制游戏逻辑和得分。
- 使用字典
绘制游戏界面:
- 使用
draw_picture
函数来绘制球和球员。 - 使用
for
循环来初始化球场上的球。
- 使用
控制球员移动和踢球:
- 使用
on_key_down
函数来检测空格键的按下,触发踢球动作。 - 使用
update
函数来控制球员的左右移动和球的飞行轨迹。
- 使用
球的物理运动:
- 使用三角函数和角度来计算球的移动方向和距离。
检测进球:
- 使用
collide_point
函数来检测球是否射入球门。
- 使用
游戏状态管理:
- 使用
state
变量来管理游戏的不同状态,如开始、运行和结束。
- 使用
声音和视觉效果:
- 使用
music
和sound
模块来增加背景音乐和音效,提升游戏体验。
- 使用
编程故事
很久很久以前,在一个充满激情的足球小镇上,居民们决定举办一场特别的足球比赛。这场比赛不同于普通的足球赛,它需要球员们用智慧和技巧来控制射门的角度和力量,以确保球能够准确地射入球门。
小镇的程序员们决定将这场比赛数字化,让全世界的人们都能参与。他们创建了一个名为“皮皮射门”的游戏,玩家将控制一个名叫皮皮的球员,通过键盘上的左右键来调整射门角度,空格键来踢球。
游戏开始时,皮皮站在球场中央,五个球随机分布在球场上。玩家的目标是踢中所有五个球,并将它们射入球门。每次成功的射门都会为皮皮赢得分数,而每次失败的射门都会让皮皮感到沮丧。
随着游戏的进行,皮皮的角度和力量控制得越来越好,他开始理解如何利用物理原理来提高射门的准确性。每当皮皮成功射入一个球,球场上就会响起欢呼声,激励他继续努力。
最终,如果皮皮能够成功射入所有五个球,他将赢得比赛,球场上会响起胜利的音乐。但如果他未能全部射中,游戏将结束,皮皮将不得不重新开始,直到他掌握射门的艺术。
这个游戏不仅考验了玩家的反应速度和策略思考,还向他们介绍了基本的物理概念,如角度、力量和运动轨迹。通过这个编程故事,程序员们不仅创造了一个有趣的游戏,还教育了下一代足球运动员。
'''
操作介绍:按键盘左右按键切换皮皮角度,(角度在-60~60之间)
点击空格键踢球,球的中心点在球门内则得分。
球场的球全部踢中就胜利,否则失败
'''
pics = {
1: False,2: False,3: False,4: False,5: False}
# 画图函数
def draw_picture(d):
if d in pics:
pics[d] = True
press_key = 'SPACE'
kick_flag = False
# 踢球函数
def kick():
global kick_flag
kick_flag = True
# 绘制足球和球员角色和球门(画图指令)
for i in range(1,5+1):
draw_picture(i)
# 如果按下空格键,则踢球(if语句)
if press_key == 'SPACE':
kick()
shoot = "YES"
# 进球得分,初始值为0
score = 0
# 当shoot变量的结果为'YES',表示射中了球门
if shoot == 'YES':
# 累积得分
score += 100
####################################################
from pgzrun import *
import math
start = Actor('开始',(336,147))
bg = Actor('bg')
ball1 = Actor('ball1')
ball2 = Actor('ball2')
ball3 = Actor('ball3')
ball4 = Actor('ball4')
ball5 = Actor('ball5')
goal = Actor('球门')
over = Actor('win', (300,169))
player = Actor('球员')
ban = Actor('分数板子')
music.play('WeWillRockYou')
music.volume = 0.6
ball_list = [ball1,ball2,ball3,ball4,ball5]
isadd = False
show_num = 0 # 这个变量表示界面上画几个球
for i in pics:
if not pics[i]:
ball_list[int(i)-1].pos = (1000,10)
else:
show_num += 1
state = 'start'
real_score = 0
def draw():
if state == 'start':
start.draw()
elif state == 'run':
bg.draw()
goal.draw()
for i in ball_list:
i.draw()
player.draw()
screen.draw.text('得分:'+str(real_score),(70,16),'white',25)
if isadd:
ban.pos = (t_x,t_y)
ban.draw()
screen.draw.text('+'+str(score),(t_x,t_y),'white',20)
else:
over.draw()
def change_run():
global state
state = 'run'
def stop_music():
music.stop()
def change_state():
global state
if real_score!= 0 and real_score == show_num*score:
state = 'win'
sound.play('进球欢呼')
else:
state = 'lose'
over.frame = 1
sound.play('遗憾')
clock.schedule(stop_music, 3)
frame_num = 0
def play_run():
global frame_num
player.frame = frame_num
frame_num += 1
if frame_num > 2:
frame_num = 0
clock.schedule_interval(play_run, 0.1)
def play_kick():
global frame_num
player.frame = frame_num
frame_num += 1
if frame_num > 6:
frame_num = 3
k_flag = []
def on_key_down(key):
global k_flag,frame_num
if key == 'SPACE':
sound.play('踢球音效')
clock.unschedule(play_run)
frame_num = 3
clock.schedule_interval(play_kick, 0.1)
for i in ball_list:
if i.collide_actor(player):
k_flag.append(i)
k_flag.append(player.angle)
# 画加分文字
def add():
global isadd
isadd =False
angle_change = 1
pipi_change = 5
kick_num = 0
ball_step = 8
t_x =0
t_y =0
def update():
global real_score,k_flag,pipi_change,kick_num,t_x,t_y,isadd
if state=='start':
clock.schedule(change_run,3)
# 皮皮移动
if len(k_flag)==0:
player.x+=pipi_change
clock.unschedule(play_kick)
clock.schedule_interval(play_run, 0.1)
if player.x<=20 or player.x>=580:
pipi_change *= -1
# 控制角度
if keyboard.right:
player.angle += angle_change
elif keyboard.left:
player.angle -= angle_change
if player.angle>=60:
player.angle = 60
elif player.angle<=-60:
player.angle = -60
# 球的移动
if kick_flag:
if len(k_flag)!=0:
k_flag[0].y -= math.cos((math.pi/180)*k_flag[1])*ball_step
k_flag[0].x += math.sin((math.pi/180)*k_flag[1])*ball_step
k_flag[0].frame = 1
k_flag[0].angle += 10
k_flag[0].scale -= 0.005
# 是否进球
if goal.collide_point(k_flag[0].pos):
real_score += score
isadd = True
t_x=k_flag[0].x
t_y =k_flag[0].y-30
clock.schedule(add, 1.5)
sound.play('胜利')
player.angle = 0
k_flag[0].pos = (1000,62)
k_flag = []
kick_num += 1
elif k_flag[0].y < 20:
player.angle = 0
sound.play('失败')
k_flag[0].pos = (1000,62)
k_flag = []
kick_num += 1
if kick_num == show_num:
clock.schedule(change_state, 1.0)
go()