课程全名:An Introduction to Interactive Programming in Python,来自 Rice University

授课教授:Joe Warren, Scott Rixner, John Greiner, Stephen Wong

工具:http://www.codeskulptor.org/, simplegui 模块

第四次作业,完成一个弹球的游戏,游戏的界面如下,规则也很简单,球不断在两边的paddle之间撞击后速度会不断加快,直到有一名玩家无法将球回击,则另一名玩家得分。

之前得了解一下控制物体移动的方式。

假设物体与点p相对应,第一种方式是直接通过控制点p的坐标来实现移动

在draw_handler中不用进行更新,只用绘制他的position就可以

坐标的变化放在key_handler中进行修改,比如

key_handler:

Left Arrow –> p[0] –= c

Right Arrow –> p[0] += c

Up Arrow –> p[1] –= c

Down Arrow –> p[1] += c

代码如下:

import simplegui

WIDTH = 500
HEIGHT = 300
p = [WIDTH/2, HEIGHT/2] def draw(canvas):
canvas.draw_circle(p, 30, 1, "White", "White") def key_down(key):
c = 4
if key == simplegui.KEY_MAP['up']:
p[1] -= c
elif key == simplegui.KEY_MAP['down']:
p[1] +=c
elif key == simplegui.KEY_MAP['left']:
p[0] -= c
elif key == simplegui.KEY_MAP['right']:
p[0] += c # Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Position Control", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(key_down) # Start the frame animation
frame.start()

第二种方式通过控制点p的速率(velocity)变化来实现移动。

draw_handler中进行坐标的更新和绘制

在key_handler中进行速率的调整

draw_handler:

p[0] += v[0]

p[1] += v[1]

key_handler:

Left Arrow –> v[0] –= c

Right Arrow –> v[0] += c

Up Arrow –> v[1] –= c

Down Arrow –> v[1] += c

代码如下:

import simplegui

WIDTH = 500
HEIGHT = 300
v = [0, 0]
p = [WIDTH/2, HEIGHT/2] def draw(canvas):
p[0] += v[0]
p[1] += v[1]
canvas.draw_circle(p, 30, 1, "White", "White") def key_down(key):
c = 1
if key == simplegui.KEY_MAP['up']:
v[1] -= c
elif key == simplegui.KEY_MAP['down']:
v[1] +=c
elif key == simplegui.KEY_MAP['left']:
v[0] -= c
elif key == simplegui.KEY_MAP['right']:
v[0] += c # Create a frame and assign callbacks to event handlers
frame = simplegui.create_frame("Position Control", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(key_down) # Start the frame animation
frame.start()

这里再提一下碰撞的处理,上下碰撞,只用把v[1]的方向取反,左右碰撞,把v[0]的方向取反。

主要就是边界位置的判断,对于一个假定中心为p,半径为r的求来说:

碰撞如下:

Left Wall:

p[0] <= r

Right Wall:

p[0] >= (width-1)-r

Top Wall:

p[1] <= r

Bottom Wall:

p[1] >= (height-1)-r

下面两张图来自老师的课件,关于定义

回归到这个游戏,基本要用到的知识也就这么多,移动paddle处理方式稍微特殊一点,keydown_handler进行velocity的正方向增加,那么keyup_handler进行velocity的负方向增加,这样就可以实现,按下按键后paddle持续移动,释放按键后paddle停止移动。

对于小球,初始随机给一个velocity,只要不是垂直或者水平,然后处理碰撞,在进行paddle碰撞后,要给予小球10%velocity上的增量。

完整代码如下:

# Implementation of classic arcade game Pong

import simplegui
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
# if direction is RIGHT, the ball's velocity is upper right, else upper left
def spawn_ball(direction):
global ball_pos, ball_vel # these are vectors stored as lists
ball_pos = [WIDTH/2, HEIGHT/2]
ball_dir = 1 if direction == RIGHT else -1
ball_vel = [ball_dir * random.randrange(2, 4), -random.randrange(1, 3)] # define event handlers
def new_game():
global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel # these are numbers
global score1, score2 # these are ints
spawn_ball(random.choice([LEFT, RIGHT]))
paddle1_pos, paddle2_pos = HEIGHT / 2, HEIGHT / 2
paddle1_vel, paddle2_vel = 0, 0
score1, score2 = 0, 0 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") # update ball
new_ball_posX = ball_pos[0] + ball_vel[0]
new_ball_posY = ball_pos[1] + ball_vel[1]
if new_ball_posY <= BALL_RADIUS:
ball_pos[1] = BALL_RADIUS
ball_vel[1] *= -1
elif new_ball_posY >= HEIGHT - 1 - BALL_RADIUS:
ball_pos[1] = HEIGHT - 1 - BALL_RADIUS
ball_vel[1] *= -1
else:
ball_pos[1] = new_ball_posY # hit the left gutter
if new_ball_posX <= PAD_WIDTH + BALL_RADIUS:
ball_pos[0] = PAD_WIDTH + BALL_RADIUS
if (ball_pos[1] >= paddle1_pos - HALF_PAD_HEIGHT
and ball_pos[1] <= paddle1_pos + HALF_PAD_HEIGHT):
ball_vel[0] = -(ball_vel[0] + 0.1 * ball_vel[0])
ball_vel[1] = ball_vel[1] + 0.1 * ball_vel[1]
else:
score2 = score2 + 1
spawn_ball(RIGHT) # hit the right gutter
elif new_ball_posX >= WIDTH - PAD_WIDTH - BALL_RADIUS:
ball_pos[0] = WIDTH - PAD_WIDTH - BALL_RADIUS
if (ball_pos[1] >= paddle2_pos - HALF_PAD_HEIGHT
and ball_pos[1] <= paddle2_pos + HALF_PAD_HEIGHT):
ball_vel[0] = -(ball_vel[0] + 0.1 * ball_vel[0])
ball_vel[1] = ball_vel[1] + 0.1 * ball_vel[1]
else:
score1 = score1 + 1
spawn_ball(LEFT)
else:
ball_pos[0] = new_ball_posX # draw ball
canvas.draw_circle(ball_pos, BALL_RADIUS, 1, "White", "White") # update paddle's vertical position, keep paddle on the screen
new_paddle1_pos = paddle1_pos + paddle1_vel
if new_paddle1_pos <= HALF_PAD_HEIGHT:
paddle1_pos = HALF_PAD_HEIGHT
elif new_paddle1_pos >= HEIGHT-HALF_PAD_HEIGHT:
paddle1_pos = HEIGHT-HALF_PAD_HEIGHT
else:
paddle1_pos = new_paddle1_pos new_paddle2_pos = paddle2_pos + paddle2_vel
if new_paddle2_pos <= HALF_PAD_HEIGHT:
paddle2_pos = HALF_PAD_HEIGHT
elif new_paddle2_pos >= HEIGHT-HALF_PAD_HEIGHT:
paddle2_pos = HEIGHT-HALF_PAD_HEIGHT
else:
paddle2_pos = new_paddle2_pos # draw paddles
canvas.draw_polygon([[0, paddle1_pos-HALF_PAD_HEIGHT],
[PAD_WIDTH-1, paddle1_pos-HALF_PAD_HEIGHT],
[PAD_WIDTH-1, paddle1_pos+HALF_PAD_HEIGHT],
[0, paddle1_pos+HALF_PAD_HEIGHT]], 1, "White", "White")
canvas.draw_polygon([[WIDTH-PAD_WIDTH+1, paddle2_pos-HALF_PAD_HEIGHT],
[WIDTH, paddle2_pos-HALF_PAD_HEIGHT],
[WIDTH, paddle2_pos+HALF_PAD_HEIGHT],
[WIDTH-PAD_WIDTH+1, paddle2_pos+HALF_PAD_HEIGHT]], 1, "White", "White")
# draw scores
canvas.draw_text(str(score1), (WIDTH/4, HEIGHT/5), 50, "Red")
canvas.draw_text(str(score2), (WIDTH/4*3, HEIGHT/5), 50, "Red")
canvas.draw_text("Author: Tiny656", (WIDTH/5*3, HEIGHT/20*18), 18, "Green")
canvas.draw_text("Mail: 236798656@qq.com", (WIDTH/5*3, HEIGHT/20*19), 18, "Green") def keydown(key):
global paddle1_vel, paddle2_vel
acc = 3
if key == simplegui.KEY_MAP['w']:
paddle1_vel -= acc
elif key == simplegui.KEY_MAP['s']:
paddle1_vel += acc
if key == simplegui.KEY_MAP['up']:
paddle2_vel -= acc
elif key == simplegui.KEY_MAP['down']:
paddle2_vel += acc def keyup(key):
global paddle1_vel, paddle2_vel
acc = 3
if key == simplegui.KEY_MAP['w']:
paddle1_vel += acc
elif key == simplegui.KEY_MAP['s']:
paddle1_vel -= acc
if key == simplegui.KEY_MAP['up']:
paddle2_vel += acc
elif key == simplegui.KEY_MAP['down']:
paddle2_vel -= acc def reset():
new_game() # create frame
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT)
frame.set_draw_handler(draw)
frame.set_keydown_handler(keydown)
frame.set_keyup_handler(keyup)
frame.add_button("Reset", reset, 200) # start frame
new_game()
frame.start()

Mini projects #4 ---- Pong的更多相关文章

  1. Mini projects #7 ---- Spaceship

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  2. Mini projects #8–RiceRocks

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  3. Mini projects #6 ---- Blackjack

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  4. Mini projects #3 ---- Stopwatch: The Game

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  5. Mini projects #5 ---- Memory

    课程全名:An Introduction to Interactive Programming in Python,来自 Rice University 授课教授:Joe Warren, Scott ...

  6. Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目

    Golang优秀开源项目汇总(持续更新...)我把这个汇总放在github上了, 后面更新也会在github上更新. https://github.com/hackstoic/golang-open- ...

  7. A Complete List of .NET Open Source Developer Projects

    http://scottge.net/2015/07/08/a-complete-list-of-net-open-source-developer-projects/?utm_source=tuic ...

  8. Building Xcode iOS projects and creating *.ipa file from the command line

    For our development process of iOS applications, we are using Jenkins set up on the Mac Mini Server, ...

  9. All the Apache Streaming Projects: An Exploratory Guide

    The speed at which data is generated, consumed, processed, and analyzed is increasing at an unbeliev ...

随机推荐

  1. 网络TCp数据的传输设计(黏包处理)

    //1.该片为引用别人的文章:http://www.cnblogs.com/alon/archive/2009/04/16/1437599.html 解决TCP网络传输"粘包"问题 ...

  2. 如何使用matplotlib绘制一个函数的图像

    我们经常会遇到这种情况,有一个数学函数,我们希望了解他的图像,这个时候使用python 的matplotlib就可以帮助我们. 用sigmoid函数来举个例子. sigmoid函数: 代码: impo ...

  3. Markdown syntax guide and writing on MWeb

    Philosophy Markdown is intended to be as easy-to-read and easy-to-write as is feasible.Readability, ...

  4. Oracle存储过程记录异常

    --建立错误日志表 create table PUB_PROC_ERR_LOG ( LOG_ID NUMBER, MODULE_NAME ), PROC_NAME ), ERR_TIME DATE, ...

  5. qt5中QPrinter的使用兼容性问题

    qt5与qt4在QPrinter中使用的不同点如下: 在.pro文件中加入如下语句:

  6. js-我理解的闭包

    一:什么是闭包 <JS高级程序设计>指出:闭包是指有有权访问另一个函数作用域中变量的函数. 二:闭包的使用 闭包的常见的创建方式是 子函数嵌套在父函数的内部,这样,子函数就可以访问父函数中 ...

  7. python学习之——安装Beautifulsoup、requests、lxml

    安装Beautiful soup: 1.下载安装包,解压到python的安装目录: 2.cmd 进入安装包解压后的存放位置: 3.使用命令:python  setup.py build   , pyt ...

  8. 【转】Linux学习之路--启动VNC服务

    我的Linux是Fedora 13,安装方法如下: 1.打开终端,执行 # yum install -y tigervnc tigervnc-server 2.编辑/etc/sysconfi/vncs ...

  9. TP框架,根据当前应用状态对应的配置文件

    index.php define('APP_STATUS','website'); /ThinkPHP/Library/Think/Dispatcher.class.php /** * 应用程序初始化 ...

  10. qweb

    qweb 是 odoo的模板系统, 在 odoo系统中, 它有不同的用途和实现, 一个是 web client 的 widget 的渲染引擎, 它是通过 javascript实现的,也是 最早引入到 ...