coursera例子之小球碰撞边界反弹

# ball physics code for generic 2D domain

# the functions inside() and normal() encode the shape of the ennvironment

import simplegui

import random

import math

# Canvas size

width = 600

height = 400

# Ball traits

radius = 20

color = "White"

# math helper function

def dot(v, w):

return v[0] * w[0] + v[1] * w[1]

class RectangularDomain:

def __init__(self, width, height):

self.width = width

self.height = height

self.border = 2

# return if bounding circle is inside the domain

def inside(self, center, radius):

in_width = ((radius + self.border) < center[0] <

(self.width - self.border - radius))

in_height = ((radius + self.border) < center[1] <

(self.height - self.border - radius))

return in_width and in_height

# return a unit normal to the domain boundary point nearest center

def normal(self, center):

left_dist = center[0]

right_dist = self.width - center[0]

top_dist = center[1]

bottom_dist = self.height - center[1]

if left_dist < min(right_dist, top_dist, bottom_dist):

return (1, 0)

elif right_dist < min(left_dist, top_dist, bottom_dist):

return (-1, 0)

elif top_dist < min(bottom_dist, left_dist, right_dist):

return (0, 1)

else:

return (0, -1)

# return random location

def random_pos(self, radius):

x = random.randrange(radius, self.width - radius - self.border)

y = random.randrange(radius, self.height - radius - self.border)

return [x, y]

# Draw boundary of domain

def draw(self, canvas):

canvas.draw_polygon([[0, 0], [self.width, 0],

[self.width, self.height], [0, self.height]],

self.border*2, "Red")

class CircularDomain:

def __init__(self, center, radius):

self.center = center

self.radius = radius

self.border = 2

# return if bounding circle is inside the domain

def inside(self, center, radius):

dx = center[0] - self.center[0]

dy = center[1] - self.center[1]

dr = math.sqrt(dx ** 2 + dy ** 2)

return dr < (self.radius - radius - self.border)

# return a unit normal to the domain boundary point nearest center

def normal(self, center):

dx = center[0] - self.center[0]

dy = center[1] - self.center[1]

dr = math.sqrt(dx ** 2 + dy ** 2)

return [dx / dr, dy / dr]

# return random location

def random_pos(self, radius):

r = random.random() * (self.radius - radius - self.border)

theta = random.random() * 2 * math.pi

x = r * math.cos(theta) + self.center[0]

y = r * math.sin(theta) + self.center[1]

return [x, y]

# Draw boundary of domain

def draw(self, canvas):

canvas.draw_circle(self.center, self.radius, self.border*2, "Red")

class Ball:

def __init__(self, radius, color, domain):

self.radius = radius

self.color = color

self.domain = domain

self.pos = self.domain.random_pos(self.radius)

self.vel = [random.random() + .1, random.random() + .1]

# bounce

def reflect(self):

norm = self.domain.normal(self.pos)

norm_length = dot(self.vel, norm)

self.vel[0] = self.vel[0] - 2 * norm_length * norm[0]

self.vel[1] = self.vel[1] - 2 * norm_length * norm[1]

# update ball position

def update(self):

self.pos[0] += self.vel[0]

self.pos[1] += self.vel[1]

if not self.domain.inside(self.pos, self.radius):

self.reflect()

# draw

def draw(self, canvas):

canvas.draw_circle(self.pos, self.radius, 1,

self.color, self.color)

# generic update code for ball physics

def draw(canvas):

ball.update()

field.draw(canvas)

ball.draw(canvas)

field = RectangularDomain(width, height)

# field = CircularDomain([width/2, height/2], 180)

ball = Ball(radius, color, field)

frame = simplegui.create_frame("Ball physics", width, height)

frame.set_draw_handler(draw)

frame.start()

你可能感兴趣的:(coursera例子之小球碰撞边界反弹)