ZhangZhihui's Blog  

 

 

import turtle
import math
from random import uniform
from dataclasses import dataclass


WIDTH = 1200
HEIGHT = 800
MIN_V = 5
MAX_V = 15
MIN_SIZE_FACTOR = 0.7
MAX_SIZE_FACTOR = 4
START_DISTANCE = 600
R = 10
MARGIN = 50
SLEEP_MS = 20


@dataclass
class SimState:
    done: bool

    def set_done(self):
        self.done = True

    @classmethod
    def setup(cls):
        r = cls(False)
        turtle.listen()
        turtle.onkeypress(r.set_done, "space")
        return r


@dataclass
class Ball:
    m: turtle.Turtle
    r: float
    vx: float

    @classmethod
    def create(cls, original_position, size_factor, vx):
        m = turtle.Turtle()
        r = size_factor * R
        m.shape("circle")
        m.shapesize(size_factor)
        m.penup()
        m.goto(original_position, 0)

        return cls(m, r, vx)

    @property
    def mass(self):
        return math.pi * (self.r ** 2)

    def move(self):
        self.m.setx(self.m.xcor() + self.vx)

        if abs(self.m.xcor()) > WIDTH / 2 - self.r:
            self.vx *= -1


def setup_screen(title):
    turtle.setup(WIDTH + MARGIN, HEIGHT + MARGIN)
    turtle.tracer(0, 0)
    turtle.title(title)


def draw_vessel():
    m = turtle.Turtle()
    m.hideturtle()
    m.penup()
    m.goto(-WIDTH / 2, -HEIGHT / 2)
    m.pendown()
    m.sety(HEIGHT / 2)
    m.setx(WIDTH / 2)
    m.sety(-HEIGHT / 2)
    m.setx(-WIDTH / 2)


def balls_collide(b1, b2):
    return abs(b1.m.xcor() - b2.m.xcor()) <= b1.r + b2.r


def process_collision(b1, b2):
    m1, m2 = b1.mass, b2.mass
    v1 = (b1.vx * (m1 - m2) + 2 * m2 * b2.vx) / (m1 + m2)
    v2 = b1.vx + v1 - b2.vx
    
    b1.vx = v1
    b2.vx = v2


sim_state = SimState.setup()
setup_screen("Central collision")
draw_vessel()

ball1 = Ball.create(-START_DISTANCE / 2, uniform(MIN_SIZE_FACTOR, MAX_SIZE_FACTOR), uniform(MIN_V, MAX_V))
ball2 = Ball.create(START_DISTANCE / 2, uniform(MIN_SIZE_FACTOR, MAX_SIZE_FACTOR), -uniform(MIN_V, MAX_V))


def tick():
    if not sim_state.done:
        ball1.move()
        ball2.move()

        if balls_collide(ball1, ball2):
            process_collision(ball1, ball2)

        turtle.update()
        turtle.ontimer(tick, SLEEP_MS)


tick()
turtle.done()

 

posted on 2024-08-04 17:35  ZhangZhihuiAAA  阅读(9)  评论(0编辑  收藏  举报