Compare commits

...

9 commits

13 changed files with 343 additions and 81 deletions

15
anime.html Normal file
View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Dumb Physics Engine</title>
<meta name="description" content="Converts SVGs into a set of circles and use those circles for dumb collision checking">
<link rel="stylesheet" href="style.css">
</head>
<body>
<img src="anime.png">
<svg id="hiragana-ni"></svg>
<svg id="hiragana-small-ya"></svg>
<svg id="hiragana-a"></svg>
<script src="script.js"></script>
</body>
</html>

BIN
anime.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

46
b.svg Normal file
View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg1"
sodipodi:docname="b.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="2.183982"
inkscape:cx="136.21907"
inkscape:cy="128.20618"
inkscape:window-width="1536"
inkscape:window-height="902"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 62.920833,22.328767 c -0.56898,15.096246 -3.307054,30.01181 -4.616352,45.027771 -2.016369,23.125149 -1.657893,29.595926 -2.636383,51.298572 -0.344254,7.63545 -0.896476,15.26087 -1.212665,22.89754 -0.404668,9.77366 -1.041894,19.77777 0.02504,29.52069 0.22274,2.03399 0.0531,4.27882 1.094617,6.04007 1.89801,3.2096 14.824157,-2.27826 14.854246,-2.28582 2.625745,-0.66005 5.29271,-1.17243 7.975326,-1.53819 23.346838,-3.18316 67.367348,0.31093 74.224728,-30.45433 0.972,-4.36083 0.44544,-9.07157 -0.72259,-13.38403 -5.32934,-19.67638 -16.98081,-28.20266 -33.5325,-38.14706 -5.8523,-3.516117 -11.5295,-7.488632 -17.88591,-9.980337 -13.041099,-5.112096 -30.424554,-7.218615 -43.280316,-0.30406"
id="path1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

46
d.svg Normal file
View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="d.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="2.183982"
inkscape:cx="136.21907"
inkscape:cy="128.20618"
inkscape:window-width="1536"
inkscape:window-height="902"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 123.29471,17.851924 c 0.51273,2.588687 1.24991,5.142879 1.53819,7.766061 0.58376,5.311795 0.78792,10.659209 1.07316,15.995367 1.70041,31.811571 1.42514,28.743224 0.83885,64.916898 -0.34192,21.09547 0.71038,31.68324 -6.27259,51.8584 -1.58707,4.58536 -3.85919,9.24844 -7.462,12.49867 -6.76053,6.09893 -20.424072,-2.75308 -24.437518,-4.7809 -5.571837,-2.8152 -19.537644,-10.37121 -23.482408,-17.20803 -5.351039,-9.27408 -5.737078,-21.45199 -2.285819,-31.38619 3.501565,-10.07901 14.384144,-19.095512 23.131844,-23.900938 4.386238,-2.409518 9.443823,-3.323029 14.224661,-4.802366 3.58684,-1.109877 7.12144,-2.708109 10.86748,-2.961907 2.62843,-0.178078 5.16922,1.035441 7.71777,1.702739 2.53075,0.66264 4.9762,2.940757 7.5085,2.28403 1.43871,-0.373115 0.45192,-2.938058 0.67788,-4.407087"
id="path1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -6,7 +6,7 @@
height="200" height="200"
viewBox="0 0 200 200" viewBox="0 0 200 200"
version="1.1" version="1.1"
id="hiragana-a" id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hiragana-a.svg" sodipodi:docname="hiragana-a.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -24,7 +24,7 @@
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:zoom="1.3575939" inkscape:zoom="1.3575939"
inkscape:cx="-103.49192" inkscape:cx="-102.75532"
inkscape:cy="160.57821" inkscape:cy="160.57821"
inkscape:window-width="1536" inkscape:window-width="1536"
inkscape:window-height="902" inkscape:window-height="902"
@ -39,16 +39,17 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1"> id="layer1">
<path <path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round" style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 12.784166,48.2633 c 6.810296,-0.0161 13.608098,-0.70428 20.417184,-0.656946 8.339073,0.05797 16.662758,0.833983 25.001807,0.895073 34.613369,0.253565 37.757077,-1.380655 75.497083,-1.862985 9.91666,-0.126739 19.84279,-0.01771 29.74891,0.456642 24.06701,1.15225 14.13856,4.282188 22.44406,1.479181" d="m 21.013028,52.575053 c 6.39466,-0.01512 12.777587,-0.661298 19.171111,-0.616852 7.830134,0.05443 15.645821,0.783085 23.475932,0.840446 32.500896,0.23809 35.452742,-1.296393 70.889459,-1.749285 9.31144,-0.119005 18.63177,-0.01663 27.93331,0.428772 22.59819,1.081927 13.27568,4.020844 21.07429,1.388906"
id="path1" /> id="path1" />
<path <path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round" style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="M 77.515495,8.2192151 C 75.516564,32.199537 75.530182,56.33753 75.541992,80.400969 c 0.0056,11.348185 -0.02805,22.701441 0.317652,34.042571 0.353335,11.59151 1.100709,23.16309 1.778856,34.73524 1.053836,17.98307 4.207218,12.37774 0.282507,18.48794" d="m 81.793766,14.974882 c -1.876935,22.516789 -1.864148,45.181627 -1.853058,67.77646 0.0053,10.655598 -0.02634,21.315958 0.298265,31.964928 0.331771,10.88407 1.033532,21.74944 1.670292,32.61534 0.989519,16.88555 3.950449,11.62231 0.265265,17.3596"
id="path2" /> id="path2" />
<path <path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round" style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 125.70777,69.526531 c -0.69486,3.385925 -3.63293,17.853348 -4.07195,19.06547 -8.71461,24.060549 -19.52078,47.577849 -34.680923,68.388329 -5.193067,7.12857 -11.141846,14.13769 -18.645251,18.77272 -12.126114,7.49057 -27.245849,4.86443 -34.058991,-9.14824 -7.660344,-15.75512 -5.83572,-36.61123 3.067622,-51.35112 3.931406,-6.50862 9.029684,-12.95456 15.761122,-16.490912 16.544317,-8.691539 41.019976,-8.7624 58.602761,-4.619642 24.18531,5.698413 40.76727,10.598274 54.53221,31.135644 3.54089,5.28304 7.29148,11.80223 6.15485,18.05974 -1.42005,7.81773 -7.43918,14.32401 -13.0577,19.94234 -15.76644,15.76589 -18.71398,16.59872 -31.88644,22.27876" d="m 125.43119,85.286289 c -8.18275,22.592121 -20.5392,49.830321 -34.774113,69.370721 -4.876132,6.69352 -10.461853,13.27487 -17.507321,17.62701 -11.386051,7.03342 -25.58302,4.56756 -31.980351,-8.58991 -7.192829,-14.79358 -5.479563,-34.37683 2.880403,-48.21713 3.69147,-6.1114 8.478597,-12.16394 14.799212,-15.484461 15.534608,-8.16109 38.516503,-8.227625 55.0262,-4.337703 22.70926,5.350634 38.27922,9.951454 51.20408,29.235414 3.32479,4.96061 6.84648,11.08193 5.77922,16.95755 -1.33339,7.3406 -6.98517,13.44981 -12.26079,18.72525 -14.8042,14.80368 -17.57185,15.58568 -29.94039,20.91906"
id="path4" /> id="path4"
sodipodi:nodetypes="csssssssssc" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -6,7 +6,7 @@
height="200" height="200"
viewBox="0 0 200 200" viewBox="0 0 200 200"
version="1.1" version="1.1"
id="hiragana-ni" id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hiragana-ni.svg" sodipodi:docname="hiragana-ni.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -24,7 +24,7 @@
inkscape:deskcolor="#d1d1d1" inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:zoom="1.7276112" inkscape:zoom="1.7276112"
inkscape:cx="-45.438465" inkscape:cx="-45.438464"
inkscape:cy="107.08428" inkscape:cy="107.08428"
inkscape:window-width="1536" inkscape:window-width="1536"
inkscape:window-height="902" inkscape:window-height="902"
@ -39,16 +39,16 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1"> id="layer1">
<path <path
style="fill:none;fill-opacity:1;stroke:currentColor;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" style="fill:none;fill-opacity:1;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 27.966735,16.083962 c -1.000438,1.124839 -2.372955,2.006558 -3.001316,3.374511 -0.890902,1.939519 -1.163631,4.125026 -1.417007,6.244278 -0.773668,6.470962 -1.184352,12.980894 -1.65866,19.480661 -1.990683,27.279717 -2.379566,30.990179 -1.454185,59.744588 0.793536,24.65759 1.788458,47.0885 5.760979,71.28514 0.564082,3.43584 1.988484,6.67372 2.982725,10.01058" d="m 30.276367,23.144761 c -0.906482,1.0192 -2.150098,1.818112 -2.719447,3.057593 -0.807232,1.757368 -1.054348,3.737623 -1.283928,5.657844 -0.701009,5.86324 -1.073123,11.761789 -1.502886,17.651128 -1.803727,24.717732 -2.156088,28.079725 -1.317615,54.133654 0.719011,22.34186 1.620494,42.66617 5.219935,64.59037 0.511106,3.11316 1.801734,6.04695 2.702601,9.07043"
id="path7" /> id="path7" />
<path <path
style="fill:none;fill-opacity:1;stroke:currentColor;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" style="fill:none;fill-opacity:1;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 61.803371,47.19668 c 1.248756,-0.907498 2.287696,-2.21703 3.746279,-2.722487 3.4894,-1.209225 7.188566,-1.722283 10.831328,-2.329273 9.225962,-1.537319 18.442605,-3.263583 27.758222,-4.100892 28.83951,-2.592158 58.01616,-0.884141 86.89226,-0.03718" d="m 60.935223,51.335517 c 1.131478,-0.82227 2.072846,-2.008817 3.394446,-2.466804 3.161691,-1.09566 6.513449,-1.560534 9.814099,-2.110518 8.359503,-1.392941 16.710561,-2.957082 25.151299,-3.715755 26.131033,-2.348715 52.567553,-0.801107 78.731743,-0.03369"
id="path8" /> id="path8" />
<path <path
style="fill:none;fill-opacity:1;stroke:currentColor;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1" style="fill:none;fill-opacity:1;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 87.045007,122.0222 c -1.118643,1.0562 -2.453734,1.92242 -3.355924,3.1686 -5.781083,7.98538 -13.117144,21.43086 -4.884465,30.77813 4.323739,4.90911 10.049889,8.7611 16.126165,11.18451 7.326277,2.92194 15.374477,3.78432 23.228367,4.51127 11.20859,1.03744 22.50545,0.60682 33.76085,0.76354 26.66878,0.37137 14.44172,-1.00144 26.91889,0.59627" d="m 83.806281,119.13377 c -1.013585,0.95701 -2.22329,1.74188 -3.040751,2.87102 -5.23815,7.23543 -11.885243,19.41817 -4.425739,27.88759 3.917674,4.44807 9.10605,7.9383 14.611671,10.13411 6.638227,2.64753 13.930578,3.42892 21.046868,4.0876 10.15593,0.94 20.39184,0.54983 30.59019,0.69183 24.16417,0.33649 13.08542,-0.90739 24.39079,0.54027"
id="path9" /> id="path9" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -6,7 +6,7 @@
height="200" height="200"
viewBox="0 0 200 200" viewBox="0 0 200 200"
version="1.1" version="1.1"
id="hiragana-small-ya" id="svg1"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
sodipodi:docname="hiragana-small-ya.svg" sodipodi:docname="hiragana-small-ya.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@ -25,7 +25,7 @@
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:zoom="1.381533" inkscape:zoom="1.381533"
inkscape:cx="-121.24213" inkscape:cx="-121.24213"
inkscape:cy="98.441371" inkscape:cy="98.441369"
inkscape:window-width="1536" inkscape:window-width="1536"
inkscape:window-height="902" inkscape:window-height="902"
inkscape:window-x="0" inkscape:window-x="0"
@ -39,16 +39,17 @@
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1"> id="layer1">
<path <path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round" style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round;stroke-dasharray:none;stroke-linecap:round"
d="m 22.318281,66.024742 c 3.522764,-5.501248 1.310196,-3.074172 12.511103,-6.879934 18.486357,-6.281155 31.10176,-9.525165 51.481112,-11.33282 17.781294,-1.577204 56.822334,-3.535437 75.702734,3.133648 12.25208,4.327774 13.15313,16.159869 5.86791,25.022203 -9.89215,12.033627 -30.4193,21.729881 -44.13131,27.517921 -1.60362,0.6769 -3.45533,0.42408 -5.18299,0.63612" d="m 22.318281,66.024742 c 3.522764,-5.501248 1.310196,-3.074172 12.511103,-6.879934 18.486357,-6.281155 31.10176,-9.525165 51.481112,-11.33282 17.781294,-1.577204 56.822334,-3.535437 75.702734,3.133648 12.25208,4.327774 13.15313,16.159869 5.86791,25.022203 -9.89215,12.033627 -30.4193,21.729881 -44.13131,27.517921 -1.60362,0.6769 -3.45533,0.42408 -5.18299,0.63612"
id="path1" /> id="path1" />
<path <path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round" style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round;stroke-dasharray:none;stroke-linecap:round"
d="m 39.84223,19.392328 c 2.395717,4.499876 5.306115,8.761481 7.187149,13.499629 2.029237,5.111447 3.134124,10.546481 4.476386,15.879684 3.417985,13.580674 6.331658,27.285733 9.802138,40.853088 7.475495,29.224441 16.236122,57.535541 27.425749,85.593431" d="m 39.84223,19.392328 c 2.395717,4.499876 5.306115,8.761481 7.187149,13.499629 2.029237,5.111447 3.134124,10.546481 4.476386,15.879684 3.417985,13.580674 6.331658,27.285733 9.802138,40.853088 7.475495,29.224441 16.236122,57.535541 27.425749,85.593431"
id="path2" /> id="path2" />
<path <path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linejoin:round" style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 95.63708,19.155587 c 2.853869,14.957057 9.67911,28.437868 14.84236,42.573525 2.10119,5.752511 3.81797,11.638235 5.72695,17.457352" d="m 94.189413,24.222422 c 2.853869,14.957057 11.126777,23.371033 16.290027,37.50669 2.10119,5.752511 3.09414,6.5714 5.00312,12.390517"
id="path3" /> id="path3"
sodipodi:nodetypes="csc" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,19 +1,20 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Dumb physics engine</title> <title>Dumb Physics Engine</title>
<meta name="description" content="Converts SVGs into a set of circles and use those circles for dumb collision checking"> <meta name="description" content="Converts SVGs into a set of circles and use those circles for dumb collision checking">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
</head> </head>
<body> <body>
<!-- <!--
Draw 200x200 SVGs in Inkscape with the pencil tool and a stroke width of 20 Draw SVGs in Inkscape with the scale set to 1
Make sure the scale is set to 1 and that the id is set to a unique value Use the pencil tool with a stroke width of 20 and round endcaps
Also, change the stroke to currentColor so we can style the color with CSS Then change the stroke color to currentColor so we can style it with CSS (might have to do this in a text editor)
--> -->
<svg id="hiragana-ni"></svg> <svg id="d"></svg>
<svg id="hiragana-small-ya"></svg> <svg id="u"></svg>
<svg id="hiragana-a"></svg> <svg id="m"></svg>
<svg id="b"></svg>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>

46
m.svg Normal file
View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg1"
sodipodi:docname="u.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="2.183982"
inkscape:cx="136.21907"
inkscape:cy="128.20618"
inkscape:window-width="1536"
inkscape:window-height="902"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 25.820096,70.504458 c -0.279617,1.740895 -0.848527,3.459504 -0.838849,5.222685 0.255376,46.524227 2.633835,-8.937146 0.06976,45.446307 -0.38795,8.2283 -1.154661,16.43771 -1.445181,24.67003 -1.112944,31.53691 1.02998,17.34175 8.486863,-0.97836 9.231101,-22.67903 15.257165,-37.23546 30.12881,-57.828718 5.387068,-7.459651 16.655579,-25.382745 28.24006,-10.842437 4.127353,5.180466 4.496278,12.510895 5.805765,19.003777 6.355886,31.514668 0.750221,21.373238 3.124668,55.728908 0.33136,4.79442 1.432408,9.56987 3.078158,14.08515 0.22154,0.60781 1.59405,-0.21261 1.74924,-0.84063 0.88884,-3.59699 0.71191,-7.37743 1.18942,-11.05171 2.49506,-19.199 3.03872,-28.15433 10.14309,-46.5427 0.98625,-2.55271 9.91829,-31.035682 21.57041,-32.505852 3.19784,-0.403478 6.46382,2.288236 8.3241,4.920413 4.21712,5.966936 6.65388,13.046334 9.21124,19.890918 8.46856,22.665491 7.3761,24.100021 11.40406,45.446301 0.9279,4.91746 1.97788,9.81113 2.98515,14.71295 0.55477,2.69973 1.60942,5.33696 1.70095,8.09158 0.0538,1.61871 -1.05646,-3.06206 -1.58469,-4.5931"
id="path1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

116
script.js
View file

@ -6,27 +6,44 @@ document.querySelectorAll("svg").forEach(function(svg) {
svg.outerHTML = req.responseText svg.outerHTML = req.responseText
}) })
let rad = 10 // Stroke width let rad = 10 // Stroke radius
let size = 200 // SVG width and height
let A = [] // Objects let A = [] // Objects
let cnt = 0 let idcnt = 0
let ix = 0
let iy = 0
let ny = 0
document.querySelectorAll("svg").forEach(function(svg) { document.querySelectorAll("svg").forEach(function(svg) {
// Move objects so they aren't overlapping // Position objects so they aren't overlapping
svg.style.left = 1.5 * size * cnt++ + "px" if (ix + svg.width.baseVal.value > window.innerWidth) {
svg.style.top = "50px" ix = 0
iy += ny
ny = 0
}
svg.style.left = ix + "px"
svg.style.top = iy + "px"
ix += svg.width.baseVal.value
ny = Math.max(svg.height.baseVal.value, ny)
svg.id = idcnt++
const rect = svg.getBoundingClientRect()
let a = { let a = {
id: svg.id, // Unique ID id: svg.id, // Unique ID
p: [], // Collision circles p: [], // Collision circles
cm: svg.createSVGPoint(), // Center of mass cm: svg.createSVGPoint(), // Position of center of mass relative to top left corner
x: rect.x, // x position of center of mass
y: rect.y, // y position of center of mass
vx: Math.random(), // x velocity vx: Math.random(), // x velocity
vy: Math.random(), // y velocity vy: Math.random(), // y velocity
th: 0, // Angular position th: 0, // Angular position
w: Math.random() / 100 // Angular velocity w: Math.random() / 100, // Angular velocity
m: 0, // Mass
mi: 0, // Moment of inertia
r: 0 // Distance to farthest point from center of mass
} }
svg.querySelectorAll("path").forEach(function(path) { svg.querySelectorAll("path").forEach(function(path) {
// Get circles on path for collision checking // Get circles on path for collision checking
for (let i = 0; i < path.getTotalLength(); i += 5) { let num = Math.floor(path.getTotalLength() * 2 / rad)
const p = path.getPointAtLength(i) for (let i = 0; i <= num; i++) {
const p = path.getPointAtLength(i / num * path.getTotalLength())
a.cm.x += p.x a.cm.x += p.x
a.cm.y += p.y a.cm.y += p.y
a.p.push(p) a.p.push(p)
@ -34,7 +51,7 @@ document.querySelectorAll("svg").forEach(function(svg) {
/* let circle = document.createElementNS("http://www.w3.org/2000/svg", "circle") /* let circle = document.createElementNS("http://www.w3.org/2000/svg", "circle")
circle.setAttribute("cx", p.x) circle.setAttribute("cx", p.x)
circle.setAttribute("cy", p.y) circle.setAttribute("cy", p.y)
circle.setAttribute("r", rad) circle.setAttribute("r", 10)
circle.setAttribute("fill", "red") circle.setAttribute("fill", "red")
svg.appendChild(circle) */ svg.appendChild(circle) */
} }
@ -42,17 +59,16 @@ document.querySelectorAll("svg").forEach(function(svg) {
a.cm.x /= a.p.length a.cm.x /= a.p.length
a.cm.y /= a.p.length a.cm.y /= a.p.length
// Change origin to center of mass // Change origin to center of mass
const rect = svg.getBoundingClientRect() a.x += a.cm.x
a.x = rect.x + a.cm.x // Position of center of mass a.y += a.cm.y
a.y = rect.y + a.cm.y // Position of center of mass
for (const p of a.p) { for (const p of a.p) {
p.x -= a.cm.x p.x -= a.cm.x
p.y -= a.cm.y p.y -= a.cm.y
} }
svg.style.transformOrigin = a.cm.x + "px " + a.cm.y + "px" svg.style.transformOrigin = a.cm.x + "px " + a.cm.y + "px"
a.m = a.p.length // Mass a.m = a.p.length
a.mi = 0 // Moment of inertia
for (const p of a.p) a.mi += p.x ** 2 + p.y ** 2 for (const p of a.p) a.mi += p.x ** 2 + p.y ** 2
for (const p of a.p) a.r = Math.max(Math.sqrt(p.x ** 2 + p.y ** 2), a.r)
A.push(a) A.push(a)
}) })
@ -92,15 +108,15 @@ function collide(a, b, c, n) {
b.vx += n.x * j / b.m b.vx += n.x * j / b.m
b.vy += n.y * j / b.m b.vy += n.y * j / b.m
b.w += -cr(cb, n) * j / b.mi b.w += -cr(cb, n) * j / b.mi
console.log('boop') // console.log('boop')
} }
// Collision of object a with wall at position k and direction d // Collision of object a with wall at position k and direction d
function wallCollide(a, k, d) { function wallCollide(a, k, d) {
if ((d == 0 && Math.abs(a.x - k) < size) || (d == 1 && Math.abs(a.y - k) < size)) { if ((!d && Math.abs(a.x - k) < a.r + rad) || (d && Math.abs(a.y - k) < a.r + rad)) {
let c = {x: 0, y: 0, cnt: 0} let c = {x: 0, y: 0, cnt: 0}
for (const p of a.p.map(x => rot(a, x))) { for (const p of a.p.map(x => rot(a, x))) {
if ((d == 0 && Math.abs(p.x - k) < rad) || (d == 1 && Math.abs(p.y - k) < rad)) { if ((!d && Math.abs(p.x - k) < rad) || (d && Math.abs(p.y - k) < rad)) {
c.x += p.x c.x += p.x
c.y += p.y c.y += p.y
c.cnt++ c.cnt++
@ -119,24 +135,31 @@ function wallCollide(a, k, d) {
// Collision of object a with object b // Collision of object a with object b
function objectsCollide(a, b) { function objectsCollide(a, b) {
if (ds(a, b) < size * size) { if (ds(a, b) < (a.r + b.r + 2 * rad) ** 2) {
// Objects are close // Objects are close
let c = {x: 0, y: 0, cnt: 0} let c = {x: 0, y: 0, cnt: 0}
let n = {x: 0, y: 0} let n = {x: 0, y: 0}
// Slight performance optimization?
// Only consider points close to other object
let aa = []
let bb = []
for (const p of a.p.map(x => rot(a, x))) { for (const p of a.p.map(x => rot(a, x))) {
// p is close to object b if (ds(p, b) < (a.r + b.r + 2 * rad) ** 2) aa.push(p)
if (ds(p, b) < size * size) { }
for (const q of b.p.map(x => rot(b, x))) { for (const p of b.p.map(x => rot(b, x))) {
const d = ds(p, q) if (ds(p, a) < (a.r + b.r + 2 * rad) ** 2) bb.push(p)
if (d < 4 * rad * rad) { }
// Collision! for (const p of aa) {
// These calculations are a bit sketchy but I guess they work? for (const q of bb) {
c.x += p.x + q.x const d = ds(p, q)
c.y += p.y + q.y if (d < (2 * rad) ** 2) {
c.cnt++ // Collision!
n.x += (p.x - q.x) / d // These calculations are a bit sketchy but I guess they work?
n.y += (p.y - q.y) / d c.x += p.x + q.x
} c.y += p.y + q.y
c.cnt++
n.x += (p.x - q.x) / d
n.y += (p.y - q.y) / d
} }
} }
} }
@ -152,17 +175,29 @@ function objectsCollide(a, b) {
} }
} }
// Move stuff, check collisions, and render
function tick() { function tick() {
// Move each object one step // Move each object one step
for (let a of A) { for (let a of A) {
a.x += a.vx a.x += a.vx
a.y += a.vy a.y += a.vy
a.th += a.w a.th += a.w
// Don't allow glitching into walls
/* const px = a.p.map(x => rot(a, x).x)
let k = Math.min(...px) - rad
if (k < 0) a.x -= k
k = window.innerWidth - Math.max(...px) - rad
if (k < 0) a.x += k
const py = a.p.map(x => rot(a, x).y)
k = Math.min(...py) - rad
if (k < 0) a.y -= k
k = window.innerHeight - Math.max(...py) - rad
if (k < 0) a.y += k */
// Friction
if (Math.abs(a.vx) > 0.001) a.vx -= 0.001 * Math.sign(a.vx) if (Math.abs(a.vx) > 0.001) a.vx -= 0.001 * Math.sign(a.vx)
if (Math.abs(a.vy) > 0.001) a.vy -= 0.001 * Math.sign(a.vy) if (Math.abs(a.vy) > 0.001) a.vy -= 0.001 * Math.sign(a.vy)
if (Math.abs(a.w) > 0.00001) a.w -= 0.00001 * Math.sign(a.w) if (Math.abs(a.w) > 0.00001) a.w -= 0.00001 * Math.sign(a.w)
} }
// Check wall collisions // Check wall collisions
for (let a of A) { for (let a of A) {
wallCollide(a, 0, 0) wallCollide(a, 0, 0)
@ -170,18 +205,16 @@ function tick() {
wallCollide(a, 0, 1) wallCollide(a, 0, 1)
wallCollide(a, window.innerHeight, 1) wallCollide(a, window.innerHeight, 1)
} }
// Check collisions between objects // Check collisions between objects
for (let i = 0; i < A.length; i++) { for (let i = 0; i < A.length; i++) {
for (let j = i + 1; j < A.length; j++) { for (let j = i + 1; j < A.length; j++) {
objectsCollide(A[i], A[j]) objectsCollide(A[i], A[j])
} }
} }
// Render every 10ms // Render every 10ms
cnt++ tickcnt++
if (cnt == 10) { if (tickcnt == 10) {
cnt = 0 tickcnt = 0
for (a of A) { for (a of A) {
let e = document.getElementById(a.id) let e = document.getElementById(a.id)
e.style.left = a.x - a.cm.x + "px" e.style.left = a.x - a.cm.x + "px"
@ -194,11 +227,10 @@ function tick() {
// Use click to update velocities // Use click to update velocities
function updatev(event) { function updatev(event) {
for (a of A) { for (a of A) {
let d = ds(a, {x: event.clientX, y: event.clientY}) let d = Math.max(ds(a, {x: event.clientX, y: event.clientY}), 100)
a.vx += 100 * (a.x - event.clientX) / d a.vx += 100 * (a.x - event.clientX) / d
a.vy += 100 * (a.y - event.clientY) / d a.vy += 100 * (a.y - event.clientY) / d
} }
// Display spreading out circles // Display spreading out circles
let circle = document.createElement("div") let circle = document.createElement("div")
circle.style.width = circle.style.height = "10px" circle.style.width = circle.style.height = "10px"
@ -213,6 +245,6 @@ function updatev(event) {
}, 1000) }, 1000)
} }
cnt = 0 let tickcnt = 0
setInterval(tick, 1) setInterval(tick, 1)
document.addEventListener("click", updatev) document.addEventListener("click", updatev)

25
stress.html Normal file
View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>Dumb Physics Engine</title>
<meta name="description" content="Converts SVGs into a set of circles and use those circles for dumb collision checking">
<link rel="stylesheet" href="style.css">
</head>
<body>
<svg id="d"></svg>
<svg id="u"></svg>
<svg id="m"></svg>
<svg id="b"></svg>
<svg id="hiragana-ni"></svg>
<svg id="hiragana-small-ya"></svg>
<svg id="hiragana-a"></svg>
<svg id="d"></svg>
<svg id="u"></svg>
<svg id="m"></svg>
<svg id="b"></svg>
<svg id="hiragana-ni"></svg>
<svg id="hiragana-small-ya"></svg>
<svg id="hiragana-a"></svg>
<script src="script.js"></script>
</body>
</html>

View file

@ -1,12 +1,8 @@
body { body {
/* background-image: url("catgirl.png"); */ position: fixed;
background-size: auto 100vh; margin: 0;
background-position: center; overflow: hidden;
background-repeat: no-repeat; touch-action: none;
background-attachment: fixed;
overflow-y: hidden;
overflow-x: hidden;
touch-action: manipulation;
} }
@keyframes color { @keyframes color {
@ -52,3 +48,10 @@ div {
background-color: #007bff; background-color: #007bff;
transition: transform 1000ms ease-in-out, opacity 1000ms ease-in-out; transition: transform 1000ms ease-in-out, opacity 1000ms ease-in-out;
} }
img {
position: absolute;
left: 50vw;
transform: translateX(-50%);
height: 100vh;
}

46
u.svg Normal file
View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg1"
sodipodi:docname="u.svg"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="2.183982"
inkscape:cx="136.21907"
inkscape:cy="128.20618"
inkscape:window-width="1536"
inkscape:window-height="902"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:none;stroke:currentColor;stroke-width:20;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
d="m 39.205909,75.448123 c -1.498412,21.24945 -1.980381,15.368861 0.162762,36.841387 1.664601,16.67795 1.855938,28.58373 11.379014,43.39479 7.014054,10.90883 14.345223,15.67333 26.607076,10.56342 14.155609,-5.8991 25.514139,-20.96366 32.740149,-33.27494 3.77953,-6.43935 6.03572,-13.68473 8.3724,-20.77627 2.74841,-8.3411 4.85188,-16.888539 6.85567,-25.439128 0.90679,-3.869478 1.23323,-7.852388 1.8655,-11.776081 0.19943,-1.237642 -0.55199,-4.126579 0.62958,-3.707749 1.6647,0.590086 1.91192,3.04222 2.33232,4.757652 1.34098,5.471824 1.81443,11.122727 2.91362,16.648202 2.98001,14.980134 5.50472,23.937134 9.18799,39.057454 1.76107,7.22944 3.37115,14.49585 5.20122,21.70813 0.96895,3.81861 2.29395,7.54367 3.19442,11.37901 1.46077,6.22176 1.75258,6.08352 -0.35056,4.17457"
id="path1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB