Browse Source

initial rewrite

master
Yorick van Pelt 5 years ago
parent
commit
d7d7ff308f
  1. 5
      LemmingSim.html
  2. 65
      bodies/robotbody_longerleft.svg
  3. 65
      bodies/robotbody_longerleft_mediumright.svg
  4. 65
      bodies/robotbody_longleft.svg
  5. 65
      bodies/robotbody_longleft_mediumright.svg
  6. 147
      bodies/robotbody_longleft_rabbit.svg
  7. 1021
      lemming_sim_student.js
  8. 14
      mouse.js
  9. 4
      pathseg.js
  10. 30
      robotbody.svg
  11. 174
      sensors.js
  12. 41
      utils.js

5
LemmingSim.html

@ -20,12 +20,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Lemmings</title>
<script language="JavaScript" src="pathseg.js"></script>
<script language="JavaScript" src="mouse.js"></script>
<script language="JavaScript" src="graphics.js"></script>
<script language="JavaScript" src="utils.js"></script>
<script language="JavaScript" src="sensors.js"></script>
<script language="JavaScript" src="lemming_sim_student.js"></script>
<script language="JavaScript" src="matter.js"></script>
<script language="JavaScript" src="jquery-1.11.0.min.js"></script>
<script language="JavaScript" src="pathseg.js"></script>
<script language="JavaScript" src="decomp.js"></script>
</head>
<body onload="init();">

65
bodies/robotbody_longerleft.svg

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Licensed as CC0 Public Domain Dedication, see https://creativecommons.org/publicdomain/zero/1.0/. -->
<svg
xmlns:ns="http://creativecommons.org/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
width="306.19147"
height="186.78011"
viewBox="0 0 306.19147 186.78011"
xml:space="preserve"
id="svg11"
sodipodi:docname="robotbody_longerleft.svg"
inkscape:version="0.92.2 (unknown)"><metadata
id="metadata17"><rdf:RDF><ns:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></ns:Work><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs15" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview13"
showgrid="false"
inkscape:zoom="1.5742187"
inkscape:cx="193.78259"
inkscape:cy="72.49728"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg11"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:snap-global="false"><sodipodi:guide
position="87.480965,95.186771"
orientation="1,0"
id="guide863"
inkscape:locked="false" /><sodipodi:guide
position="87.480965,95.186771"
orientation="0,1"
id="guide867"
inkscape:locked="false" /></sodipodi:namedview><path
id="robotbody"
d="m 21.840805,32.282261 c -29.4070742,38.075324 -29.2031002,89.304329 1.126302,124.879399 28.308167,33.20432 96.216923,41.60047 129.034143,9.08347 20.97597,3.07228 22.33436,4.02195 28.5988,-5.90513 5.06112,-8.02021 -4.86652,-25.70583 -4.67439,-28.06416 2.47109,-30.33143 1.21949,-67.484605 -2.03551,-83.758545 -0.8545,-4.27227 140.86445,3.74803 131.89259,-6.66691 C 295.93739,30.421398 158.23428,27.099346 155.90436,24.175764 133.57052,-3.8490539 58.313014,-14.940787 21.840805,32.282261 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscssssss"
style="stroke-width:0.99999988" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

65
bodies/robotbody_longerleft_mediumright.svg

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Licensed as CC0 Public Domain Dedication, see https://creativecommons.org/publicdomain/zero/1.0/. -->
<svg
xmlns:ns="http://creativecommons.org/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
width="316.32892"
height="186.78011"
viewBox="0 0 316.32892 186.78011"
xml:space="preserve"
id="svg11"
sodipodi:docname="robotbody_longerleft_mediumright.svg"
inkscape:version="0.92.2 (unknown)"><metadata
id="metadata17"><rdf:RDF><ns:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></ns:Work><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs15" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview13"
showgrid="false"
inkscape:zoom="1.5742187"
inkscape:cx="193.78259"
inkscape:cy="72.49728"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg11"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:snap-global="false"><sodipodi:guide
position="87.480965,95.186771"
orientation="1,0"
id="guide863"
inkscape:locked="false" /><sodipodi:guide
position="87.480965,95.186771"
orientation="0,1"
id="guide867"
inkscape:locked="false" /></sodipodi:namedview><path
id="robotbody"
d="m 21.840805,32.282261 c -29.4070742,38.075324 -29.2031002,89.304329 1.126302,124.879399 28.308167,33.20432 96.216923,41.60047 129.034143,9.08347 20.97597,3.07228 40.7562,3.38671 47.02064,-6.54037 5.06112,-8.02021 -23.28836,-25.07059 -23.09623,-27.42892 2.47109,-30.33143 1.21949,-67.484605 -2.03551,-83.758545 -0.8545,-4.27227 151.02822,1.84232 142.05636,-8.572618 C 306.10116,28.515691 158.23428,27.099346 155.90436,24.175764 133.57052,-3.8490539 58.313014,-14.940787 21.840805,32.282261 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscssssss"
style="stroke-width:0.99999988" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

65
bodies/robotbody_longleft.svg

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Licensed as CC0 Public Domain Dedication, see https://creativecommons.org/publicdomain/zero/1.0/. -->
<svg
xmlns:ns="http://creativecommons.org/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
width="239.8282"
height="186.78011"
viewBox="0 0 239.8282 186.78011"
xml:space="preserve"
id="svg11"
sodipodi:docname="robotbody_longleft.svg"
inkscape:version="0.92.2 (unknown)"><metadata
id="metadata17"><rdf:RDF><ns:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></ns:Work><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs15" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview13"
showgrid="false"
inkscape:zoom="1.5742187"
inkscape:cx="193.78259"
inkscape:cy="72.49728"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg11"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:snap-global="false"><sodipodi:guide
position="87.480965,95.186771"
orientation="1,0"
id="guide863"
inkscape:locked="false" /><sodipodi:guide
position="87.480965,95.186771"
orientation="0,1"
id="guide867"
inkscape:locked="false" /></sodipodi:namedview><path
id="robotbody"
d="m 21.840805,32.282261 c -29.4070742,38.075324 -29.2031002,89.304329 1.126302,124.879399 28.308167,33.20432 96.216923,41.60047 129.034143,9.08347 20.97597,3.07228 22.33436,4.02195 28.5988,-5.90513 5.06112,-8.02021 -4.86652,-25.70583 -4.67439,-28.06416 2.47109,-30.33143 1.21949,-67.484605 -2.03551,-83.758545 -0.8545,-4.27227 74.1647,3.74803 65.19284,-6.66691 C 229.23764,30.421398 158.23428,27.099346 155.90436,24.175764 133.57052,-3.8490539 58.313014,-14.940787 21.840805,32.282261 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscssssss"
style="stroke-width:0.99999988" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

65
bodies/robotbody_longleft_mediumright.svg

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Licensed as CC0 Public Domain Dedication, see https://creativecommons.org/publicdomain/zero/1.0/. -->
<svg
xmlns:ns="http://creativecommons.org/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
width="239.19885"
height="186.78011"
viewBox="0 0 239.19885 186.78011"
xml:space="preserve"
id="svg11"
sodipodi:docname="robotbody_longleft_mediumright.svg"
inkscape:version="0.92.2 (unknown)"><metadata
id="metadata17"><rdf:RDF><ns:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></ns:Work><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs15" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview13"
showgrid="false"
inkscape:zoom="1.5742187"
inkscape:cx="193.78259"
inkscape:cy="72.49728"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg11"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:snap-global="false"><sodipodi:guide
position="87.480964,95.18677"
orientation="1,0"
id="guide863"
inkscape:locked="false" /><sodipodi:guide
position="87.480964,95.18677"
orientation="0,1"
id="guide867"
inkscape:locked="false" /></sodipodi:namedview><path
id="robotbody"
d="m 21.840805,32.282261 c -29.4070742,38.075324 -29.2031002,89.304329 1.126302,124.879399 28.308167,33.20432 96.216923,41.60047 129.034143,9.08347 20.97597,3.07228 40.7562,3.38671 47.02064,-6.54037 5.06112,-8.02021 -23.28836,-25.07059 -23.09623,-27.42892 2.47109,-30.33143 1.21949,-67.484605 -2.03551,-83.758545 -0.8545,-4.27227 73.52946,-1.96909 64.5576,-12.384033 C 228.6024,24.704276 158.23428,27.099346 155.90436,24.175764 133.57052,-3.8490539 58.313014,-14.940787 21.840805,32.282261 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscssssss"
style="stroke-width:0.99999988" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

147
bodies/robotbody_longleft_rabbit.svg

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Licensed as CC0 Public Domain Dedication, see https://creativecommons.org/publicdomain/zero/1.0/. -->
<svg
xmlns:ns="http://creativecommons.org/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
width="186.78011"
height="239.8282"
viewBox="0 0 186.7801 239.82821"
xml:space="preserve"
id="svg11"
sodipodi:docname="robotbody_longleft_rabbit.svg"
inkscape:version="0.92.2 (unknown)"><metadata
id="metadata17"><rdf:RDF><ns:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></ns:Work><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs15"><inkscape:path-effect
effect="powerstroke"
id="path-effect254"
is_visible="true"
offset_points="0,0.5"
sort_points="true"
interpolator_type="CubicBezierJohan"
interpolator_beta="0.2"
start_linecap_type="zerowidth"
linejoin_type="extrp_arc"
miter_limit="4"
end_linecap_type="zerowidth" /><inkscape:path-effect
effect="powerstroke"
id="path-effect25"
is_visible="true"
offset_points="3,0.5"
sort_points="true"
interpolator_type="CubicBezierJohan"
interpolator_beta="0.2"
start_linecap_type="zerowidth"
linejoin_type="extrp_arc"
miter_limit="4"
end_linecap_type="zerowidth" /><inkscape:path-effect
effect="powerstroke"
id="path-effect254-3"
is_visible="true"
offset_points="0,0.5"
sort_points="true"
interpolator_type="CubicBezierJohan"
interpolator_beta="0.2"
start_linecap_type="zerowidth"
linejoin_type="extrp_arc"
miter_limit="4"
end_linecap_type="zerowidth" /></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview13"
showgrid="true"
inkscape:zoom="1.1131407"
inkscape:cx="-110.31088"
inkscape:cy="158.83002"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg11"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:snap-global="false"><sodipodi:guide
position="89.835902,94.776877"
orientation="0,1"
id="guide867"
inkscape:locked="false" /><inkscape:grid
type="xygrid"
id="grid17" /></sodipodi:namedview><path
id="robotbody"
d="m 32.361665,218.1462 c 38.075324,29.40707 89.304325,29.2031 124.879395,-1.12631 33.20432,-28.30816 41.60047,-96.21692 9.08347,-129.034138 3.07228,-20.97597 4.02195,-22.33436 -5.90513,-28.5988 -8.02021,-5.06112 -25.70583,4.86652 -28.06416,4.67439 -30.33143,-2.47109 -67.484601,-1.21949 -83.758541,2.03551 -4.27227,0.8545 3.74803,-74.1646999 -6.66691,-65.19283985 C 30.500802,10.749362 27.17875,81.752722 24.255168,84.082642 -3.7696494,106.41648 -14.861383,181.67399 32.361665,218.1462 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscssssss"
style="stroke-width:0.99999988" /><path
style="fill:#000000;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.124644,167.33654 c 6.249246,0 16.791976,0 28.678396,0 -3.42704,2.30174 -8.60423,5.77896 -13.40834,9.0056 -6.21057,-4.10993 -11.750517,-7.77606 -14.994123,-9.92257 C 86.237314,160.35566 58.747523,142.1639 49.584259,136.09998 Z M 49.032393,136.93392 c 9.163263,6.06391 36.653054,24.25567 45.816318,30.31959 3.291923,2.17847 8.949109,5.92219 15.272109,10.10653 l 0.27798,0.18396 0.27673,-0.18586 c 4.88158,-3.27867 10.16593,-6.82786 15.04751,-10.10653 l 1.36244,-0.91507 h -1.64122 c -12.553,0 -23.78418,0 -30.319616,0 z"
id="path23"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect25"
inkscape:original-d="m 95.124644,166.83654 h 30.319616 l -15.04751,10.10653 z" /><circle
style="fill:#ffffff"
id="path31"
cx="114.10249"
cy="114.61942"
r="4.8286796" /><circle
style="fill:#ffffff"
id="path31-3"
cx="64.355865"
cy="114.95629"
r="4.8286796" /><path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 88.836131,156.72999 V 169.7562 Z"
id="path48"
inkscape:connector-curvature="0" /><path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 43.91818,156.28081 v 17.29341 H 61.88536 V 154.93327 H 43.469 v 1.34754 z"
id="path60"
inkscape:connector-curvature="0" /><path
style="fill:#ffffff;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 73.82141,145.13271 30,-0.22312 -15.162041,12.27813 z"
id="path27"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" /><rect
style="fill:#ffffff;stroke-width:1.553774"
id="rect81"
width="1.0844152"
height="14.149155"
x="87.989937"
y="156.28081" /><path
style="fill:#ffffff;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 88.836131,170.42997 9.432769,8.53441 15.49669,-9.20818 -15.49669,8.98359 z"
id="path91"
inkscape:connector-curvature="0" /><path
style="fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 88.56847,170.11108 c 0,0 -0.460602,-0.19454 -0.460602,-0.19454 -1.097812,2.59925 -3.173212,5.69885 -7.130345,7.65121 -2.915718,1.43854 -6.462603,2.02817 -10.134523,1.51988 -3.670134,-0.50805 -7.018082,-2.05238 -9.574048,-4.30369 -3.479573,-3.06484 -4.833237,-6.79321 -5.256314,-9.75475 0.421762,2.95233 1.689623,6.71395 5.123891,9.90118 2.525356,2.3437 5.881966,4.02058 9.630593,4.65147 3.746208,0.63048 7.448089,0.14174 10.555612,-1.28956 4.23834,-1.95215 6.535016,-5.21337 7.706338,-7.98666 0,0 -0.460602,-0.19454 -0.460602,-0.19454 z"
id="path252"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect254"
inkscape:original-d="m 88.56847,170.11108 c -6.309095,14.93779 -30.208051,11.35258 -32.555832,-5.08189" /><path
style="fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 88.639962,170.16354 c 0,0 -0.460602,0.19454 -0.460602,0.19454 1.171322,2.77329 3.467997,6.03451 7.706337,7.98666 3.107522,1.4313 6.809403,1.92004 10.555603,1.28956 3.74863,-0.63089 7.10524,-2.30777 9.6306,-4.65147 3.43427,-3.18723 4.70213,-6.94885 5.12389,-9.90118 -0.42308,2.96154 -1.77674,6.68991 -5.25631,9.75475 -2.55597,2.25131 -5.90392,3.79564 -9.57405,4.30369 -3.67192,0.50829 -7.218805,-0.0813 -10.134523,-1.51988 -3.957132,-1.95236 -6.032531,-5.05196 -7.130343,-7.65121 0,0 -0.460602,0.19454 -0.460602,0.19454 z"
id="path252-5"
inkscape:connector-curvature="0"
inkscape:path-effect="#path-effect254-3"
inkscape:original-d="m 88.639962,170.16354 c 6.309093,14.93779 30.208048,11.35258 32.555828,-5.08189" /></svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

1021
lemming_sim_student.js

File diff suppressed because it is too large Load Diff

14
mouse.js

@ -58,17 +58,15 @@ function addMouseTracker(elem) {
this.mouse.hasFocus = false;
});
elem.addInteractiveElement = function(obj) {
if (!obj.mouseHit) obj.mouseHit = mouseHit
this.mouse.interactiveElements.push(obj);
};
}
function mouseHit(x, y) {
return (x < this.x + this.getWidth() && x > this.x &&
y < this.y + this.getHeight() && y > this.y)
}
function findElement(x, y) {
for (var i = this.mouse.interactiveElements.length - 1; i >= 0; --i) {
if (x < this.mouse.interactiveElements[i].x + this.mouse.interactiveElements[i].getWidth() && x > this.mouse.interactiveElements[i].x &&
y < this.mouse.interactiveElements[i].y + this.mouse.interactiveElements[i].getHeight() && y > this.mouse.interactiveElements[i].y) {
return this.mouse.interactiveElements[i];
}
}
return null;
return this.mouse.interactiveElements.find(elem => elem.mouseHit(x, y))
}

4
pathseg.js

@ -5,7 +5,7 @@
// SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
// changes which were implemented in Firefox 43 and Chrome 46.
(function() { "use strict";
window.pathseg = (function() { "use strict";
if (!("SVGPathSeg" in window)) {
// Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
@ -841,4 +841,4 @@
return builder.pathSegList;
}
}
}());
});

30
robotbody.svg

@ -13,13 +13,13 @@
version="1.1"
x="0px"
y="0px"
width="300"
height="300"
viewBox="0 0 300 300"
width="239.19885"
height="186.78011"
viewBox="0 0 239.19885 186.78011"
xml:space="preserve"
id="svg11"
sodipodi:docname="robotbody.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
sodipodi:docname="robotbody_longleft_mediumright.svg"
inkscape:version="0.92.2 (unknown)"><metadata
id="metadata17"><rdf:RDF><ns:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></ns:Work><cc:Work
@ -34,32 +34,32 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1676"
inkscape:window-height="1011"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview13"
showgrid="false"
inkscape:zoom="1.5742187"
inkscape:cx="256.30163"
inkscape:cy="152.71994"
inkscape:window-x="1366"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:cx="193.78259"
inkscape:cy="72.49728"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg11"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-center="true"
inkscape:snap-page="true"
inkscape:snap-global="false"><sodipodi:guide
position="150,150"
position="87.480964,95.18677"
orientation="1,0"
id="guide863"
inkscape:locked="false" /><sodipodi:guide
position="150,150"
position="87.480964,95.18677"
orientation="0,1"
id="guide867"
inkscape:locked="false" /></sodipodi:namedview><path
id="robotbody"
d="m 84.359841,90.688926 c -29.407074,38.075324 -29.2031,89.304324 1.126302,124.879394 28.308167,33.20432 96.216927,41.60047 129.034147,9.08347 20.97597,3.07228 22.33436,4.02195 28.5988,-5.90513 5.06112,-8.02021 -4.86652,-25.70583 -4.67439,-28.06416 2.47109,-30.33143 1.21949,-67.4846 -2.03551,-83.75854 -0.8545,-4.27227 15.72301,-15.309039 6.75115,-25.723984 C 233.31499,69.77099 220.75332,85.506011 218.4234,82.582429 196.08956,54.557611 120.83205,43.465878 84.359841,90.688926 Z"
d="m 21.840805,32.282261 c -29.4070742,38.075324 -29.2031002,89.304329 1.126302,124.879399 28.308167,33.20432 96.216923,41.60047 129.034143,9.08347 20.97597,3.07228 40.7562,3.38671 47.02064,-6.54037 5.06112,-8.02021 -23.28836,-25.07059 -23.09623,-27.42892 2.47109,-30.33143 1.21949,-67.484605 -2.03551,-83.758545 -0.8545,-4.27227 73.52946,-1.96909 64.5576,-12.384033 C 228.6024,24.704276 158.23428,27.099346 155.90436,24.175764 133.57052,-3.8490539 58.313014,-14.940787 21.840805,32.282261 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscssssss"
style="stroke-width:0.99999988" /></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

174
sensors.js

@ -0,0 +1,174 @@
// Description of robot(s), and attached sensor(s) used by InstantiateRobot()
class Sensor {
constructor(id, props) {
Object.assign(this, {
id,
parent: null,
lookAngle:0,
attachRadius: simInfo.robotSize,
value: null,
valueStr: "<uninit>",
minVal: 0,
maxVal: 50
}, props)
this.info = this
this.setAngle(this.attachAngle)
}
setAngle(attachAngle) {
this.attachAngle = attachAngle
Object.assign(this, Vec2.fromPolar(Vec2.zero, this.attachRadius, this.attachAngle))
}
plotSensor(context, x = this.x, y = this.y) {
context.beginPath();
context.arc(x, y, this.getWidth()/2, 0, 2*Math.PI);
context.closePath();
context.fillStyle = 'black';
context.strokeStyle = this.color ? convrgb(this.color) : 'black';
context.fill();
context.stroke();
}
onDragging(sensor, event) {
const {x, y} = sim.bay.transformMouse(event.mouse),
mAngle = Math.atan2(y, x),
mRadius = Math.sqrt(x*x + y*y);
this.attachRadius = mRadius
this.setAngle(mAngle)
sim.bay.repaint()
}
getWidth() { return 2 }
getHeight() { return 2 }
mouseHit(x, y) {
const mouse = sim.bay.transformMouse({x,y})
return Vec2.distLess(this, mouse, this.getWidth()/2 + 1)
}
};
class DistanceSensor extends Sensor {
rayCast() {
/* Distance sensor simulation based on ray casting. Called from sensor
* object, returns nothing, updates a new reading into this.value.
*
* Idea: Cast a ray with a certain length from the sensor, and check
* via collision detection if objects intersect with the ray.
* To determine distance, run a Binary search on ray length.
* Note: Sensor ray needs to ignore robot (parts), or start outside of it.
* The latter is easy with the current circular shape of the robots.
* Note: Order of tests are optimized by starting with max ray length, and
* then only testing the maximal number of initially resulting objects.
* Note: The sensor's "ray" could have any other (convex) shape;
* currently it's just a very thin rectangle.
*/
var bodies = Matter.Composite.allBodies(sim.engine.world);
if (this.filter) bodies = bodies.filter(this.filter)
const robotAngle = this.parent.body.angle,
rayAngle = robotAngle + this.attachAngle + this.lookAngle;
const rPos = this.parent.body.position,
rSize = this.attachRadius,
startPoint = Vec2.fromPolar(rPos, this.attachRadius, robotAngle+this.attachAngle)
function getEndpoint(rayLength) {
return Vec2.fromPolar(startPoint, rayLength, rayAngle)
};
function sensorRay(bodies, rayLength) {
// Cast ray of supplied length and return the bodies that collide with it.
const rayWidth = 1e-100,
ray = Vec2.avg(startPoint, getEndpoint(rayLength)),
rayRect = Matter.Bodies.rectangle(ray.x, ray.y, rayLength, rayWidth,
{isSensor: true, isStatic: true,
angle: rayAngle, role: 'sensor'});
return bodies.filter(body => {
// coarse check on body boundaries, to increase performance:
return Matter.Bounds.overlaps(body.bounds, rayRect.bounds) &&
body.parts.some((part, pp) => {
// skip the first part, if it's not the only one
if (pp == 0 && body.parts.length > 1) return false
// finer, more costly check on actual geometry:
if (Matter.Bounds.overlaps(part.bounds, rayRect.bounds)) {
const collision = Matter.SAT.collides(part, rayRect);
if (collision.collided) {
return true
}
}
})
})
};
// call 1x with full length, and check all bodies in the world;
// in subsequent calls, only check the bodies resulting here
var rayLength = this.maxVal;
bodies = sensorRay(bodies, rayLength);
function binarySearch(lo, hi, cond) {
let x = hi
while (lo < x) {
if (cond(x)) {
hi = x
} else {
lo = x
}
x = Math.floor(lo + (hi-lo)/2)
}
return x
}
// if some collided, search for maximal ray length without collisions
if (bodies.length > 0) {
rayLength = binarySearch(0, rayLength, len => sensorRay(bodies, len).length > 0)
}
// increase length to (barely) touch closest body (if any)
rayLength += 1;
bodies = sensorRay(bodies, rayLength);
return [bodies, rayLength, startPoint, getEndpoint(rayLength)]
}
sense() {
const context = document.getElementById('arenaLemming').getContext('2d');
const [bodies, rayLength, startPoint, endPoint] = this.rayCast()
if (simInfo.debugSensors) { // if invisible, check order of object drawing
// draw the resulting ray
context.strokeStyle = convrgb(this.parent.info.color)
context.lineWidth = 0.5;
drawVertices(context, [startPoint, endPoint])
// mark all objects's lines intersecting with the ray
bodies.forEach(({vertices}) => drawVertices(context, vertices))
}
let rl
// indicate if the sensor exceeded its maximum length by returning infinity
if (rayLength > this.maxVal) {
rl = Infinity;
}
else {
rl = Math.floor(rayLength + gaussNoise(3));
rl = Matter.Common.clamp(rl, this.minVal, this.maxVal);
}
this.value = rl;
this.valueStr = padnumber(this.value, 2);
}
}
function clamp(x, min, max) {
return x < min ? min : x > max ? max : x
}
class ColorSensor extends DistanceSensor {
sense() {
const [bodies, rayLength] = this.rayCast()
let color
if (bodies.length) {
color = bodies[0].color.map(x => clamp(x + gaussNoise(), 0, 255))
} else {
color = [255,255,255]
}
this.value = color
this.valueStr = `</span><span style="color: ${convrgb(color)}">` +
color.map(x => format(x)).join(', ')
}
}
class Gyroscope extends Sensor {
sense() {
this.value = (this.parent.body.angle * (180/Math.PI) + gaussNoise()) % 360
this.valueStr = format(this.value) + '&deg;'
}
}

41
utils.js

@ -0,0 +1,41 @@
"use strict"
const Vec2 = {
add({x:x1, y:y1}, {x:x2, y:y2}) {
return Object.freeze({x:x1+x2, y:y1+y2})
},
avg({x:x1, y:y1}, {x:x2, y:y2}) {
return Object.freeze({x:(x1+x2)/2, y:(y1+y2)/2})
},
fromPolar({x,y}, radius, angle) {
return Object.freeze({x: x + radius * Math.cos(angle),
y: y + radius * Math.sin(angle)})
},
sub({x:x1, y:y1}, {x:x2, y:y2}) {
return Object.freeze({x:x1-x2, y: y1-y2})
},
distLess(a, b, radius) {
const {x, y} = Vec2.sub(a, b)
return ((x*x) + (y*y)) < (radius * radius)
},
zero: Object.freeze({x:0, y:0})
};
function drawVertices(context, vertices, draw=true, close=true) {
if (draw) context.beginPath();
context.moveTo(vertices[0].x, vertices[0].y);
vertices.slice(1).forEach(({x, y}) =>
context.lineTo(x, y))
if (close) context.lineTo(vertices[0].x, vertices[0].y);
if (draw) context.stroke();
}
function convrgb(values) {
return 'rgb(' + values.map(x=>x|0).join(', ') + ')';
};
// apply mild noise on the sensor reading, and clamp between valid values
function gaussNoise(sigma=1) {
const x0 = 1.0 - Math.random();
const x1 = 1.0 - Math.random();
return sigma * Math.sqrt(-2 * Math.log(x0)) * Math.cos(2 * Math.PI * x1);
};
Loading…
Cancel
Save