Forked from cormullion/julia-bouncing-balls-animation.jl
Created
June 26, 2021 06:53
-
-
Save Sov-trotter/61c99c1d3c572adc50266728607be337 to your computer and use it in GitHub Desktop.
julia bouncing balls
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
#!/usr/bin/env julia | |
using Luxor, Colors, Combinatorics | |
mutable struct Ball | |
id::Int | |
position::Point | |
velocity::Point | |
color::Color | |
ballradius::Float64 | |
end | |
function backdropf(scene, framenumber) | |
background("white") | |
end | |
function collisioncheck(balls) | |
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, | |
) > 0.01 | |
collision = ballb.position - balla.position | |
distance = Luxor.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 / distance) | |
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) | |
setopacity(0.9) | |
panes = Tiler(scene.movie.width, scene.movie.height, 1, 2, margin = 0) | |
panecenters = first.(collect(panes)) | |
panewidth = panes.tilewidth / 2 | |
paneheight = panes.tileheight / 2 | |
balls = collisioncheck(balls) | |
# on the left | |
@layer begin | |
translate(panecenters[1]) | |
box(O1, 2panewidth, 2paneheight, :stroke) | |
for ball in balls | |
ball.position = ball.position += ball.velocity | |
if (ball.position.x <= (-panewidth + ball.ballradius)) | |
ball.position = Point(-panewidth + ball.ballradius, ball.position.y) | |
ball.velocity = Point(-ball.velocity.x, ball.velocity.y) | |
end | |
if (ball.position.x >= (panewidth - ball.ballradius)) | |
ball.position = Point(panewidth - ball.ballradius, ball.position.y) | |
ball.velocity = Point(-ball.velocity.x, ball.velocity.y) | |
end | |
if (ball.position.y <= (-paneheight + ball.ballradius)) | |
ball.position = Point(ball.position.x, -panewidth + ball.ballradius) | |
ball.velocity = Point(ball.velocity.x, -ball.velocity.y) | |
end | |
if (ball.position.y >= (paneheight - ball.ballradius)) | |
ball.position = Point(ball.position.x, panewidth - ball.ballradius) | |
ball.velocity = Point(ball.velocity.x, -ball.velocity.y) | |
end | |
sethue(ball.color) | |
circle(ball.position, ball.ballradius, :fill) | |
end | |
end | |
# do the right thing | |
@layer begin | |
sethue("black") | |
fontsize(14) | |
fontface("Menlo") | |
translate(panecenters[2]) | |
data = [(b.position.x, b.position.y) for b in balls] | |
stringdata = map(x -> string(convert.(Int, floor.(x))), data) | |
textbox(stringdata, O - (panewidth, paneheight) + (5, 5), leading = 20) | |
end | |
end | |
function main() | |
juliaballmovie = Movie(256, 128, "juliaballs") | |
initialpts = ngon(O + (0, 10), 35, 3, pi / 6, vertices = true) | |
ballradius = 14 | |
balls = [ | |
# set position and initial velocity vectors | |
Ball(1, initialpts[1], initialpts[3] / 30, colorant"brown3", ballradius), | |
Ball(2, initialpts[2], initialpts[2] / 30, colorant"forestgreen", ballradius), | |
Ball(3, initialpts[3], initialpts[1] / 40, colorant"mediumorchid3", ballradius), | |
] | |
animate( | |
juliaballmovie, | |
[ | |
Scene(juliaballmovie, backdropf, 1:100), | |
Scene(juliaballmovie, (s, f) -> update(s, f, balls), 1:100), | |
], | |
framerate = 30, | |
creategif = true, | |
pathname = "juliapool.gif", | |
) | |
end | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment