要求在这里。我在codeskulptor上保存不了代码, program template也总是打不开。
反正交不了作业,我就没有完全按下面的步骤做。比如第12步没有做,现在这个难度对我来说已经很高了,5次只能接到1次。
画paddle到底有没有简便方法?现在这么画好累。
这个作业是要求创建“乒乓”游戏,步骤如下:
1 画出一个乒乓球,建议参照 "Motion"视频的第二部分,增加positional update。
2 写 function spawn_ball
的代码,在桌子中间出现一个新的乒乓球,暂时赋予它一个固定的速度。暂时不要管 direction
参数。
3 new_game
是用来开始另外一局比赛的function,它要调用 spawn_ball
4 修改代码,让乒乓球撞到上、下边线时会弹回。用不同的初始速度值来测试这部分代码。
5 在 spawn_ball(direction)
中添加randomization (随机性?)如果direction == RIGHT
,则速度增加,方向向右。 direction == LEFT
同理。具体的纵向和横向速度由 random.randrange()
.来产生。横向速度建议 random.randrange(120, 240)
pixels per second,纵向速度建议random.randrange(60, 180)
(You will need to set the signs of velocities appropriately.)
6 在draw handler 中添加代码,测试乒乓球是否能跟gutter碰撞(不要忘记,gutters 跟左右边线的距离是paddle的宽度,参考本周的最后一个视频)
7 添加代码,画出左边和右边的paddle。这两个paddle的垂直位置取决于两个 global variables (paddle1_pos
和 paddle2_pos
)。
8 添加代码,通过对draw handler的更新 ,修改这两个垂直位置的值。更新的应该是包含两个paddle垂直速度的 global variables( paddle1_vel
paddle2_vel
)。
9 使用key handlers更新这两个垂直速度的值, 用"w" 和 "s"控制左边paddle垂直速度,上下箭头控制右边 paddle垂直速度。我们的要求是,当按"w"时,paddle匀速上行,当按"s"时,paddle匀速下行,两个键都不按则停止不动(两个都按时的动作随便你)。这需要你使用keydown 和 keyup handler。
10 要避免paddle 移出canvas,就需要在你更新 draw handler中它们的垂直位置之前添加检查代码。具体来说,就是检查最新的位置更新是否会让paddle 一部分移动出canvas。如果会,就要拒绝这个更新。
11 修改关于左右gutter的碰撞代码(在第6步),检查乒乓球是否接触gutter的时候其实撞到了paddle,如果是,则让乒乓球弹回。这种碰撞模式剔除了乒乓撞到paddle边缘上的可能性,大大简化你的碰撞/反弹代码。
12 要增加难度,就让乒乓的速度每次撞到paddle时,速度加快10%。
13 添加代码,让乒乓每次撞到gutter的时候,对方球员就得1分,并且重新发球。
14添加代码到 new_game
,在调用spawn_ball
. 前归零比分。添加一个“Restart”按钮,调用 new_game
归零比分,并重新发球。
# 4 mini-project pong
import simplegui
import random
# Initialize globals
WIDTH=600
HEIGHT=400
BALL_RADIUS=15
PADDLE_W=30
PADDLE_L=60
GUTTER_W=30
ball_pos=[WIDTH/2,HEIGHT/2]
Vel=[1,0]
Paddle1_cen_h=30
Paddle2_cen_h=30
paddle1_pos=[[0,Paddle1_cen_h-PADDLE_L/2],[0,Paddle1_cen_h+PADDLE_L/2],[PADDLE_W,Paddle1_cen_h+PADDLE_L/2],[PADDLE_W,Paddle1_cen_h-PADDLE_L/2]]
paddle2_pos=[[WIDTH-PADDLE_W,Paddle2_cen_h-PADDLE_L/2],[WIDTH-PADDLE_W,Paddle2_cen_h+PADDLE_L/2],[WIDTH,Paddle2_cen_h+PADDLE_L/2],[WIDTH,Paddle2_cen_h-PADDLE_L/2]]
paddle1_vel=[0,0]
paddle2_vel=[0,0]
message1=0
message2=0
#Difine event handlers
def draw(canvas):
global paddle1_pos
global paddle2_pos
global Paddle1_cen_h
global Paddle2_cen_h
global message1
global message2
#draw pong
canvas.draw_circle(ball_pos,BALL_RADIUS,2,"Orange","Orange")
#draw gutter
canvas.draw_polyline([(GUTTER_W,0), (GUTTER_W,HEIGHT)], 1,"Teal")
canvas.draw_polyline([(WIDTH-GUTTER_W,0), (WIDTH-GUTTER_W,HEIGHT)], 1,"Teal")
#draw centerline
canvas.draw_polyline([(WIDTH/2,0), (WIDTH/2,HEIGHT)], 1,"Teal")
#draw Paddle1
canvas.draw_polygon(paddle1_pos,2,"Teal")
#draw Paddle2
canvas.draw_polygon(paddle2_pos,2,"Teal")
#draw paddle1 text
canvas.draw_text(str(message1),[WIDTH/2-50,HEIGHT/2-80],24,"White")
canvas.draw_text(str(message2),[WIDTH/2+50,HEIGHT/2-80],24,"White")
#update ball positon
ball_pos[0]+=Vel[0]
ball_pos[1]+=Vel[1]
# collide and reflect off up and down
if ball_pos[1]<=BALL_RADIUS:
Vel[1]=-Vel[1]
elif ball_pos[1]>=HEIGHT-BALL_RADIUS:
Vel[1]=-Vel[1]
# touch the gutter?
if ball_pos[0]<=GUTTER_W+BALL_RADIUS:
if abs(ball_pos[1]-Paddle1_cen_h)< PADDLE_L/2+BALL_RADIUS:
Vel[0]=-Vel[0]
else:
spawn_ball("RIGHT")
message2 +=1
elif ball_pos[0]>=WIDTH-GUTTER_W-BALL_RADIUS:
if abs(ball_pos[1]-Paddle2_cen_h)< PADDLE_L/2+BALL_RADIUS:
Vel[0]=-Vel[0]
else:
spawn_ball("LEFT")
message1 +=1
#update paddle positon
if Paddle1_cen_h+paddle1_vel[1]>PADDLE_L/2 and Paddle1_cen_h+paddle1_vel[1]<HEIGHT-PADDLE_L/2:
Paddle1_cen_h +=paddle1_vel[1]
else: paddle1_vel[1]=0
if Paddle2_cen_h+paddle2_vel[1]>PADDLE_L/2 and Paddle2_cen_h+paddle2_vel[1]<HEIGHT-PADDLE_L/2:
Paddle2_cen_h +=paddle2_vel[1]
else: paddle2_vel[1]=0
paddle1_pos=[[0,Paddle1_cen_h-PADDLE_L/2],[0,Paddle1_cen_h+PADDLE_L/2],[PADDLE_W,Paddle1_cen_h+PADDLE_L/2],[PADDLE_W,Paddle1_cen_h-PADDLE_L/2]]
paddle2_pos=[[WIDTH-PADDLE_W,Paddle2_cen_h-PADDLE_L/2],[WIDTH-PADDLE_W,Paddle2_cen_h+PADDLE_L/2],[WIDTH,Paddle2_cen_h+PADDLE_L/2],[WIDTH,Paddle2_cen_h-PADDLE_L/2]]
# paddle control
def keydown(key):
acc=1
if key==simplegui.KEY_MAP["w"]:
paddle1_vel[1]-=acc
elif key==simplegui.KEY_MAP["s"]:
paddle1_vel[1]+=acc
elif key==simplegui.KEY_MAP["d"]:
paddle1_vel[1]=0
elif key==simplegui.KEY_MAP["up"]:
paddle2_vel[1]-=acc
elif key==simplegui.KEY_MAP["down"]:
paddle2_vel[1]+=acc
elif key==simplegui.KEY_MAP["left"]:
paddle2_vel[1]=0
def spawn_ball(direction):
global ball_pos
global Vel
ball_pos=[WIDTH/2,HEIGHT/2]
Vel=[-1,1]
#randomization
if direction == "RIGHT":
Vel[0]=random.randrange(2, 5)
Vel[1]=random.randrange(1, 6)
elif direction == "LEFT":
Vel[0]=random.randrange(-5,-2)
Vel[1]=random.randrange(1, 6)
# start a new game
def new_game():
global message1
global message2
spawn_ball
message1=0
message2=0
#create frame
frame=simplegui.create_frame("Pong",WIDTH,HEIGHT)
# add a button to start a new game
button= frame.add_button('start new game', new_game,180)
#register event handlers
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
# start frame
frame.start()