[Interactive Python] Pong小游戏 Mini-project #4

9 篇文章 0 订阅
7 篇文章 0 订阅


学习一门语言的初期总是会碰很多壁,还好用时间从错误中换来经验和稳重。当目标明确时,就不容易动摇。所以,记得自己为什么学这门语言、需要在哪里用很重要哦!

很感激最终实现了Pong小游戏。这里吐槽下我走过的弯路:

由于跟着coursera的An Introduction to Interactive Programming in Python 课,他们使用codeskulptor编写,我在大陆无法连上那个在线IDE,一直使用Sublime Text3文本编辑器编写代码。其中的编译、逻辑、显示错误,很难知道,由此走了很多弯路。
1. 先是因为python中没有simpleGUI库,只好下载SimpleGUICS2Pygame库代替,但在install时出现encoding的错误,苦于无法解决考虑使用其它GUI库。

2. 我们一般使用R进行数据分析,久闻python在数据分析中更有优势,于是学习了python的数据表示方法,总结如下符号表示:

^

一行以...开头

$

一行以...结尾

.

对应任何字符

\s

对应空格

\S

对应任何非空格字符

*

可输入0-若干个字符

*?

可输入0-若干个字符(非贪婪策略)(指选择满足条件的最短部分)

+

可输入1-若干个字符

+?

可输入1-若干个字符(非贪婪策略)

[xxx]

对应方括号中的任一字符

[^xxx]

对应除方括号中字符以外的任一字符

[a-z0-9]

对应一定范围内字符

(

标示从哪里开始

)

标示到哪里结束

在网页爬取时,python3.5版本无法使用import urllib格式调用urllib.urlopen函数。得照此格式输入才可开始打开网页。

from urllib import request
import urllib.request

fhand = request.urlopen('http://www.py4inf.com/code/romeo.txt')

3. 对于python版本和simpleGUI库的问题,我最后买了VPN直接使用codeSkulptor编写程序,省了好多麻烦,也算解决问题了!

Pong的游戏规则很简单,就是用两个板把球弹到对方的边界,没接住者输,对方得分。这里左手边的方块用w,s控制上下,右手边的用↑、↓控制,两个人可以使用同一台电脑玩。

游戏要求见此:https://www.coursera.org/learn/interactive-python-1/supplement/wiv24/mini-project-description 

编程思路如下(也许你有更好的方法,欢迎指点~~):

(1) 首先确定引用库,全局变量,主函数:

import simplegui
import math
import random

# initialize globals - pos and vel encode vertical info for paddles
WIDTH = 600
HEIGHT = 400       
BALL_RADIUS = 20
PAD_WIDTH = 8
PAD_HEIGHT = 80
HALF_PAD_WIDTH = PAD_WIDTH / 2
HALF_PAD_HEIGHT = PAD_HEIGHT / 2
LEFT = False
RIGHT = True


# initialize ball_pos and ball_vel for new bal in middle of table
ball_pos = [WIDTH/2, HEIGHT/2]
ball_vel = [random.randrange(240, 300)/60, random.randrange(60, 240)/60]
time = 0
<pre name="code" class="python"># create frame
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
frame.set_keyup_handler(keyup)
timer = simplegui.create_timer(500,tick)

# start frame
new_game()
frame.start()
timer.start()

 

(2) 其次在draw(canvas)函数中绘制边线,球(ball),控制块(paddle):

def draw(canvas):
    global score1, score2, paddle1_pos, paddle2_pos, ball_pos, ball_vel
        
    # draw mid line and gutters
    canvas.draw_line([WIDTH / 2, 0],[WIDTH / 2, HEIGHT], 1, "White")
    canvas.draw_line([PAD_WIDTH, 0],[PAD_WIDTH, HEIGHT], 1, "White")
    canvas.draw_line([WIDTH - PAD_WIDTH, 0],[WIDTH - PAD_WIDTH, HEIGHT], 1, "White")

    # draw ball
    canvas.draw_circle(ball_pos, BALL_RADIUS, 2, "Red", "White")

    # draw paddles
    canvas.draw_polygon([(0,paddle1_pos-HALF_PAD_HEIGHT),(PAD_WIDTH,paddle1_pos-HALF_PAD_HEIGHT),\
        (PAD_WIDTH,paddle1_pos+HALF_PAD_HEIGHT),(0,paddle1_pos+HALF_PAD_HEIGHT)],2,'White','Gray')
    canvas.draw_polygon([(WIDTH-PAD_WIDTH,paddle2_pos-HALF_PAD_HEIGHT),(WIDTH,paddle2_pos-HALF_PAD_HEIGHT),\
        (WIDTH,paddle2_pos+HALF_PAD_HEIGHT),(WIDTH-PAD_WIDTH,paddle2_pos+HALF_PAD_HEIGHT)],2,'White','Gray')
(3) 确定游戏刚开始和进行新一轮的状态

def spawn_ball(direction):
    global ball_pos, ball_vel # these are vectors stored as lists
    global time
    if direction == RIGHT:
        ball_pos = [WIDTH/2+time*ball_vel[0], HEIGHT/2+time*ball_vel[1]]
    if direction == LEFT:
        ball_pos = [WIDTH/2-time*ball_vel[0], HEIGHT/2+time*ball_vel[1]]
def new_game():
    global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel  # these are numbers
    global score1, score2  # these are ints
    score1, score2 = 0, 0
    paddle1_pos = HEIGHT/2
    paddle2_pos = HEIGHT/2
    paddle1_vel, paddle2_vel = 0, 0
(4) 通过键盘'W''S'键和上下键分别控制左手边、右手边paddle

def keydown(key):
    global paddle1_vel, paddle2_vel,t
    acc = 7
    if key == simplegui.KEY_MAP["up"]:
        paddle2_vel -= acc
    elif key == simplegui.KEY_MAP["down"]:
        paddle2_vel += acc
    elif key == simplegui.KEY_MAP["w"]:
        paddle1_vel -= acc
    elif key == simplegui.KEY_MAP["s"]:
        paddle1_vel += acc
    print paddle1_pos, paddle2_pos
    
def keyup(key):
    global paddle1_vel, paddle2_vel,t
    acc = 7
    if key == simplegui.KEY_MAP["up"]:
        paddle2_vel += acc
    elif key == simplegui.KEY_MAP["down"]:
        paddle2_vel -= acc
    elif key == simplegui.KEY_MAP["w"]:
        paddle1_vel += acc
    elif key == simplegui.KEY_MAP["s"]:
        paddle1_vel -= acc
    print paddle1_pos, paddle2_pos
(5) 更新ball和paddle位置,写在绘制上方,这样可以更新后再绘制

</pre><pre name="code" class="python">    # update ball
    if (ball_pos[1] <= BALL_RADIUS) or (ball_pos[1] >=HEIGHT-BALL_RADIUS):
        ball_vel[1] = -ball_vel[1]
    ball_pos[0] = ball_pos[0]+ball_vel[0]
    ball_pos[1] = ball_pos[1]+ball_vel[1]
    # update paddle's vertical position, keep paddle on the screen
    if paddle1_pos+paddle1_vel>=HALF_PAD_HEIGHT and paddle1_pos+paddle1_vel<=HEIGHT-HALF_PAD_HEIGHT:
        paddle1_pos += paddle1_vel
    if paddle2_pos+paddle2_vel>=HALF_PAD_HEIGHT and paddle2_pos+paddle2_vel<=HEIGHT-HALF_PAD_HEIGHT:
        paddle2_pos += paddle2_vel    
(6) 确定球与控制块是否碰撞来确定转向还是开启下一轮

    # determine whether paddle and ball collide
    crit_x_d = PAD_WIDTH+BALL_RADIUS
    crit_y_d = HALF_PAD_HEIGHT
    pos_x1_d = math.fabs(0-ball_pos[0])
    pos_x2_d = math.fabs(WIDTH-ball_pos[0])
    pos_y1_d = math.fabs(paddle1_pos-ball_pos[1])
    pos_y2_d = math.fabs(paddle2_pos-ball_pos[1])

    if pos_x1_d<=BALL_RADIUS:
        score2 +=1
        spawn_ball(RIGHT)
    if  pos_x2_d<=BALL_RADIUS:
        score1 = score1+1
        spawn_ball(LEFT)
    elif (pos_x1_d<=crit_x_d and pos_y1_d<=crit_y_d) or (pos_x2_d<=crit_x_d and pos_y2_d<=crit_y_d):
        ball_vel[0]=-ball_vel[0]
(7) 最后编写绘制分数代码

    # draw scores
    canvas.draw_text('score1',(250,20),15,'Red')
    canvas.draw_text('score2',(350,20),15,'Red')
    canvas.draw_text(str(score1),(270,30),12,'Red')
    canvas.draw_text(str(score2),(370,30),12,'Red')

这是一次值得经历的过程,虽然创作过程坎坷,最后的显示简单,但其背后的思路分析、编写顺序是切身捋一次才能深刻学习到。下图便为游戏的界面显示。我要坚持下去,相信熟练后,可以添加更多丰富的细节!



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值