Last active
September 17, 2022 13:22
-
-
Save cormullion/a157d7ff1a876f6d3bf15c50ad407d49 to your computer and use it in GitHub Desktop.
julia pool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Luxor, Colors, Combinatorics, Random | |
mutable struct Ball | |
id::Int | |
position::Point | |
velocity::Point | |
color::Union{NTuple, Colorant, String} | |
ballradius::Float64 | |
end | |
function backdropf(scene, framenumber) | |
background("grey20") | |
end | |
function collisioncheck!(balls; | |
tol = 0.01) | |
for ballpair in combinations(1:length(balls), 2) | |
balla, ballb = balls[ballpair[1]], balls[ballpair[2]] | |
if intersection2circles(balla.position, balla.ballradius, ballb.position, ballb.ballradius) > tol | |
collision = ballb.position - balla.position | |
d = distance(ballb.position, balla.position) | |
# Get the components of the velocity vectors which are parallel to the collision. | |
# The perpendicular component remains the same for both | |
collision = (collision / d) | |
aci = dotproduct(balla.velocity, collision) | |
bci = dotproduct(ballb.velocity, collision) | |
# new velocities using the 1-dimensional elastic collision equations | |
# masses are the same | |
acf = bci | |
bcf = aci | |
# replace the velocity components | |
balls[ballpair[1]].velocity += (acf - aci) * collision | |
balls[ballpair[2]].velocity += (bcf - bci) * collision | |
end | |
end | |
return balls | |
end | |
function update(scene, framenumber) | |
balls = scene.opts | |
for ball in balls | |
ball.position = ball.position += ball.velocity | |
# check bouncing off walls | |
if (ball.position.x <= (-scene.movie.width/2 + ball.ballradius)) | |
ball.position = Point(-scene.movie.width/2 + ball.ballradius, ball.position.y) | |
ball.velocity = Point(-ball.velocity.x, ball.velocity.y) | |
end | |
if (ball.position.x >= (scene.movie.width/2 - ball.ballradius)) | |
ball.position = Point(scene.movie.width/2 - ball.ballradius, ball.position.y) | |
ball.velocity = Point(-ball.velocity.x, ball.velocity.y) | |
end | |
if (ball.position.y <= (-scene.movie.height/2 + ball.ballradius)) | |
ball.position = Point(ball.position.x, -scene.movie.width/2 + ball.ballradius) | |
ball.velocity = Point(ball.velocity.x, -ball.velocity.y) | |
end | |
if (ball.position.y >= (scene.movie.height/2 - ball.ballradius)) | |
ball.position = Point(ball.position.x, scene.movie.width/2 - ball.ballradius) | |
ball.velocity = Point(ball.velocity.x, -ball.velocity.y) | |
end | |
sethue(ball.color) | |
circle(ball.position, ball.ballradius, :fill) | |
end | |
collisioncheck!(balls) | |
end | |
function main() | |
juliaballmovie = Movie(200, 200, "julia-billiard-pool") | |
numberofballs = 3 | |
Random.seed!(42) | |
ballradius = 30 | |
pts = [polar(100, θ) for θ in range(0, 2π, length = 1 + numberofballs)] | |
cols = [Luxor.julia_red, Luxor.julia_green, Luxor.julia_purple, Luxor.julia_blue] | |
balls = [Ball(i, pts[i], pts[i] * rand(-0.15:0.01:0.15), cols[mod1(i, 4)], ballradius) for i in 1:numberofballs] | |
animate(juliaballmovie, [ | |
Scene(juliaballmovie, backdropf, 1:300), | |
Scene(juliaballmovie, update, optarg=balls, 1:300), | |
], creategif=true, pathname="/tmp/julia-billiard-pool.gif") | |
end | |
main() |
Author
cormullion
commented
Aug 16, 2017
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment