/
AmuMax
/
Physics
Обзор
Документация
Войти
/
AmuMax
/
Physics
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
m2.py
165 строк
5 KB
Osipchuk Lidiya
clear
12 дек 2024, 10:52
12 дек 2024, 10:52
8cd182c
Код
Авторство
О чём код?
import random import pygame import sys import math # Инициализация Pygame pygame.init() # Константы WIDTH, HEIGHT = 500, 500 BALL_RADIUS = 15 WHITE = (255, 255, 255) RED = (255, 0, 0) GREEN = (0, 255, 0) BLACK = (0, 0, 0) FPS = 120 EPS = 10 dt = 1 # Настройки экрана screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Моделирование столкновений бильярдных шаров") clock = pygame.time.Clock() class Ball: def __init__(self, x, y, vx, vy, mass, color): self.x = x self.y = y self.vx = vx self.vy = vy self.mass = mass self.color = color def update(self): self.x += self.vx * dt self.y += self.vy * dt # Отражения от стенки if self.x - BALL_RADIUS < 0 or self.x + BALL_RADIUS > WIDTH: self.vx = -self.vx if self.y - BALL_RADIUS < 0 or self.y + BALL_RADIUS > HEIGHT: self.vy = -self.vy def draw(self, screen): pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), BALL_RADIUS) def close(self, other): dx = other.x - self.x dy = other.y - self.y distance = math.hypot(dx, dy) return distance < BALL_RADIUS * 2 def very_close(self, other): dx = other.x - self.x dy = other.y - self.y distance = math.hypot(dx, dy) return distance < EPS def collide(self, other): dx = other.x - self.x dy = other.y - self.y distance = math.hypot(dx, dy) if distance < BALL_RADIUS * 2: # Нормализация nx = dx / distance ny = dy / distance # Проекция скорости на нормаль p1 = self.vx * nx + self.vy * ny p2 = other.vx * nx + other.vy * ny # Обновление скоростей по одной оси self.vx += (2 * other.mass / (self.mass + other.mass)) * (p2 - p1) * nx self.vy += (2 * other.mass / (self.mass + other.mass)) * (p2 - p1) * ny other.vx += (2 * self.mass / (self.mass + other.mass)) * (p1 - p2) * nx other.vy += (2 * self.mass / (self.mass + other.mass)) * (p1 - p2) * ny balls = [] #ball1, ball2, ball3] speed_first_ball = 3 coord_first = [100, 100] coord_second = [100, 200] coord_third = [100, 300] mass_first = 1 mass_second = 1 mass_third = 1 HOLE = Ball(coord_third[0], coord_third[1], 0, 0, mass_third, BLACK) def recalc(): for ball in balls: ball.update() for i in range(len(balls)): for j in range(i + 1, len(balls)): balls[i].collide(balls[j]) def count_first_angle(): angle = 0 while angle < 360: ball1 = Ball(coord_first[0], coord_first[1], speed_first_ball * math.cos(math.radians(angle)), speed_first_ball * math.sin(math.radians(angle)), mass_first, RED) ball2 = Ball(coord_second[0], coord_second[1], 0, 0, mass_second, GREEN) ball3 = Ball(coord_third[0], coord_third[1], 0, 0, mass_third, BLACK) global balls balls = [ball1, ball2, ball3] Found_1_2 = False Found_3_2 = False for i in range(1000): recalc() if(balls[0].close(balls[1])): Found_1_2 = True if(Found_1_2 and balls[1].very_close(HOLE)): Found_3_2 = True break if balls[0].close(HOLE): Found_3_2 = False break if(Found_3_2): return angle angle += 0.1 return None res_angle = count_first_angle() if res_angle is None: print("Нет ответа") res_angle = random.randint(0, 360) print("надо лететь под углом:", res_angle) ball1 = Ball(coord_first[0], coord_first[1], speed_first_ball * math.cos(math.radians(res_angle)), speed_first_ball * math.sin(math.radians(res_angle)), mass_first, RED) ball2 = Ball(coord_second[0], coord_second[1],0, 0, mass_second, GREEN) balls = [ball1, ball2] freeze = False while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() while freeze: pass screen.fill(WHITE) HOLE.draw(screen) for ball in balls: ball.draw(screen) # Проверка коллизий recalc() if balls[1].very_close(HOLE): freeze = True for i in range(8): screen.fill(WHITE) for ball in balls: ball.draw(screen) recalc() pygame.display.flip() clock.tick(FPS) pygame.display.flip() clock.tick(FPS) pygame.quit() sys.exit()