多个弹球与矩形碰撞示例程序,本程序用海龟画图模块演示基本的矩形碰撞原理

"""多个弹球与矩形碰撞示例程序,本程序用海龟画图模块演示基本的矩形碰撞原理"""

from turtle import Turtle, Screen
from random import choice,randint

class Board(Turtle):
    def __init__(self):
        """初始化不可见的矩形"""
        Turtle.__init__(self, shape='square', visible=False)
        self.penup()
        self.color('yellow')
        self.shapesize(10, 10)
        self.st()
        
    def up_move(self):
        """向上移动10个单位"""
        y = self.ycor() + 10
        self.sety(y)
        
    def down_move(self):
        """向下移动10个单位"""        
        y = self.ycor() - 10
        self.sety(y)
        
    def left_move(self):
        """向左移动10个单位"""
        x = self.xcor() - 10
        self.setx(x)
        
    def right_move(self):
        """向右移动10个单位"""
        x = self.xcor() + 10
        self.setx(x)

class Ball(Turtle):
    def __init__(self,board):
        """初始化不可见圆形,参数为矩形"""
        Turtle.__init__(self, shape='circle', visible=False)
        self.board = board
        rect = self.screen.cv.coords(self.board.turtle._item)
        self.board_width = abs(rect[0] - rect[2])   # 求矩形宽度
        self.board_height = abs(rect[1] - rect[5])  # 求矩形高度        
        self.penup()                                # 抬笔       
        self.color('red')                           # 设置小球颜色  
        self.radius = 10                            # 海龟画图默认圆形的半径为10        
        self.sh = self.screen.window_height()       # 获取屏幕高度
        self.sw = self.screen.window_width()        # 获取屏幕的宽度         
        self.ht()
        self.init_move()

    def init_move(self):
        x = randint(-self.sw // 2, self.sh // 2)
        y = randint(-self.sh // 2, self.sw // 2)
        # 有些小球会生成在矩形内,可以重新调整位置让小球都生成在矩形外面
        self.goto(x, y)
        # 设置小球的单位移动距离
        self.xspeed = choice([-1,-2,-3,-4,-5,1,2,3,4,5])
        self.yspeed = choice([-1,-2,-3,-4,-5,1,2,3,4,5])
        self.st()

    def move(self):
        """移动"""
        x = self.xcor() + self.xspeed
        y = self.ycor() + self.yspeed
        self.goto(x, y)
        
        # 边缘检测
        if abs(self.xcor()) + self.radius >= self.sw // 2:
            self.xspeed = -self.xspeed
        if abs(self.ycor()) + self.radius >= self.sh // 2:
            self.yspeed = -self.yspeed

        # 碰到矩形检测
        self.collide_board_check() 
            
    def collide_board_check(self):
        """矩形碰撞检测"""
        board_left = self.board.xcor() - self.board_width//2
        board_right = self.board.xcor() + self.board_width//2
        board_top = self.board.ycor() + self.board_height//2
        board_bottom = self.board.ycor() - self.board_height//2
        
        ball_left = self.xcor() - self.radius
        ball_right = self.xcor() + self.radius
        ball_top = self.ycor() + self.radius
        ball_bottom = self.ycor() - self.radius

        # 没有碰到矩形的条件
        c1 = ball_right < board_left or ball_left > board_right
        c2 = ball_bottom > board_top or ball_top<board_bottom

        # 如果没有碰到,直接返回
        if c1 or c2 :return

        # 在矩形的左边,向右碰撞过去的 
        if ball_right > board_left and ball_bottom > board_bottom and ball_top<board_top:
            self.xspeed = -self.xspeed
            return

        # 在矩形的右边,向左移动碰撞过去
        if ball_left < board_right and ball_bottom > board_bottom and ball_top<board_top:
            self.xspeed = -self.xspeed
            return
        
        # 在矩形的上边,向下撞过去
        if ball_bottom < board_top and ball_left > board_left and ball_right<board_right:
            self.yspeed = -self.yspeed
            return
        
        # 在矩形的下边,向上撞过去
        if ball_top > board_bottom and ball_left > board_left and ball_right<board_right:
            self.yspeed = -self.yspeed
            return 
 
             

if __name__ == '__main__':
    
    # 声明一个空列表,用于存放小球对象
    ps = []
    # 计数
    count = 0
    # 设置小球总数
    amount = 20

    # 新建一个屏幕
    screen = Screen()
    # 设置屏幕背景色
    screen.bgcolor('white')
    # 设置屏幕宽高
    screen.setup(700, 500)
    # 设置屏幕标题
    screen.title('多个弹球与矩形碰撞示例程序,作者:李兴球')
    screen.delay(0)

    # 创建挡板对象
    d = Board()

    screen.onkeypress(d.up_move, 'Up')
    screen.onkeypress(d.down_move, 'Down')
    screen.onkeypress(d.left_move, 'Left')
    screen.onkeypress(d.right_move, 'Right')
    screen.update()
    screen.listen()


    while True:
        if count < amount:
            p = Ball(d)
            ps.append(p)
            count += 1

        [p.move() for p in ps]
        screen.update()



python矩形碰撞小球示例图