First commit
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*pycache*
|
||||
BIN
assets/ARCO.ttf
Normal file
BIN
assets/background.png
Normal file
|
After Width: | Height: | Size: 328 KiB |
43
assets/blue_arrive.svg
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="49.999992mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 49.999992 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-126.9132,-174.99535)">
|
||||
<rect
|
||||
style="fill:#e26465;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect131"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="127.44092"
|
||||
y="175.52307"
|
||||
ry="0" />
|
||||
<path
|
||||
id="path146"
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:#3b4f63;stroke-width:0.793999;stroke-opacity:1"
|
||||
transform="matrix(1.0541644,0,0,1.0541644,-110.60368,74.286918)"
|
||||
d="m 250.53942,103.41605 3.48296,10.57748 11.13607,0.0439 a 1.5908266,1.5908266 71.999982 0 1 0.93386,2.87412 l -8.98348,6.58112 3.39951,10.60459 a 1.590828,1.590828 144.00001 0 1 -2.44488,1.77631 l -9.03506,-6.51012 -9.03507,6.51012 a 1.5908289,1.5908289 36.000002 0 1 -2.44488,-1.77631 l 3.39951,-10.60459 -8.98348,-6.58112 a 1.5908266,1.5908266 108.00002 0 1 0.93386,-2.87412 l 11.13607,-0.0439 3.48297,-10.57748 a 1.5908286,1.5908286 1.7041414e-5 0 1 3.02204,0 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/blue_pane.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
104
assets/blue_robot.svg
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50.000008mm"
|
||||
height="50mm"
|
||||
viewBox="0 0 50.000008 50"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-127.36029,-5.8010774)">
|
||||
<rect
|
||||
style="fill:#e26465;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect96"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="127.88802"
|
||||
y="6.3288074"
|
||||
ry="8.6410732" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect138"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="136.64062"
|
||||
y="36.123081"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect132"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="138.3127"
|
||||
y="36.96928"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect136"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="136.71138"
|
||||
y="19.479122"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect137"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="139.65242"
|
||||
y="22.50359"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect133"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="156.16737"
|
||||
y="19.479122"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect135"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="159.12572"
|
||||
y="22.613567"
|
||||
ry="1.3447782" />
|
||||
<path
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path152"
|
||||
d="m 163.13239,6.8746271 a 10.772104,10.772104 0 0 1 -5.38605,9.3289159 10.772104,10.772104 0 0 1 -10.7721,0 10.772104,10.772104 0 0 1 -5.38605,-9.3289159 h 10.7721 z" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse155"
|
||||
cx="133.69824"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse156"
|
||||
cx="171.05814"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
164
assets/blue_robot_inactive.svg
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="51.000004mm"
|
||||
height="51.000004mm"
|
||||
viewBox="0 0 51.000004 51.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="tiles_and_sprites.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="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.37558051"
|
||||
inkscape:cx="49.257083"
|
||||
inkscape:cy="669.63007"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:export-bgcolor="#ffffff00"
|
||||
showgrid="false">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="51.000004"
|
||||
height="51.000004"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7"
|
||||
inkscape:swatch="gradient">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-185.35863,-5.3288078)">
|
||||
<rect
|
||||
style="fill:#e26465;fill-opacity:1;stroke:#202a35;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect19"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="186.35863"
|
||||
y="6.3288074"
|
||||
ry="8.6410732"
|
||||
inkscape:export-filename="blue_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.413953;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:0.484455"
|
||||
id="rect20"
|
||||
width="51"
|
||||
height="51"
|
||||
x="185.35863"
|
||||
y="5.3288074"
|
||||
ry="9.813427"
|
||||
inkscape:export-filename="blue_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189"
|
||||
rx="0" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect138"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="195.11122"
|
||||
y="36.123081"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect132"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="196.78329"
|
||||
y="36.96928"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect136"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="195.18198"
|
||||
y="19.479122"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect137"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="198.12302"
|
||||
y="22.50359"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect133"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="214.63797"
|
||||
y="19.479122"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect135"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="217.59631"
|
||||
y="22.613567"
|
||||
ry="1.3447782" />
|
||||
<path
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path152"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="210.83089"
|
||||
sodipodi:cy="6.8746271"
|
||||
sodipodi:rx="10.772104"
|
||||
sodipodi:ry="10.772104"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 221.60299,6.8746271 a 10.772104,10.772104 0 0 1 -5.38605,9.3289159 10.772104,10.772104 0 0 1 -10.77211,0 10.772104,10.772104 0 0 1 -5.38605,-9.3289159 h 10.77211 z" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse155"
|
||||
cx="192.16884"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse156"
|
||||
cx="229.52873"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
BIN
assets/blue_text.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/bw_btn.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
assets/bw_dark_btn.png
Normal file
|
After Width: | Height: | Size: 9 KiB |
BIN
assets/completed_card.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
assets/delete_btn.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/delete_dark_btn.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
46
assets/floor.svg
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50mm"
|
||||
viewBox="0 0 50 50"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-5.5368996,-5.801076)">
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:none;stroke-width:1.07822;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect94"
|
||||
width="50"
|
||||
height="50"
|
||||
x="6.0760098"
|
||||
y="6.3401856"
|
||||
ry="0" />
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect146"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.0646296"
|
||||
y="6.3288054"
|
||||
ry="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/fw_btn.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
assets/fw_dark_btn.png
Normal file
|
After Width: | Height: | Size: 9 KiB |
BIN
assets/go_btn.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
assets/go_dark_btn.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
43
assets/green_arrive.svg
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="49.999992mm"
|
||||
viewBox="0 0 50 49.999992"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-127.93943,-116.38636)">
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect149"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="128.46716"
|
||||
y="116.91409"
|
||||
ry="0" />
|
||||
<path
|
||||
id="path149"
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:#5a8639;stroke-width:0.793999;stroke-opacity:1"
|
||||
transform="matrix(1.0541644,0,0,1.0541644,-109.57743,15.67794)"
|
||||
d="m 250.53942,103.41605 3.48296,10.57748 11.13607,0.0439 a 1.5908266,1.5908266 71.999982 0 1 0.93386,2.87412 l -8.98348,6.58112 3.39951,10.60459 a 1.590828,1.590828 144.00001 0 1 -2.44488,1.77631 l -9.03506,-6.51012 -9.03507,6.51012 a 1.5908289,1.5908289 36.000002 0 1 -2.44488,-1.77631 l 3.39951,-10.60459 -8.98348,-6.58112 a 1.5908266,1.5908266 108.00002 0 1 0.93386,-2.87412 l 11.13607,-0.0439 3.48297,-10.57748 a 1.5908286,1.5908286 1.7041414e-5 0 1 3.02204,0 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/green_pane.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
104
assets/green_robot.svg
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50.000008mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 50.000008 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-127.40481,-61.09372)">
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect139"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="127.93254"
|
||||
y="61.621449"
|
||||
ry="8.6410732" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect140"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="136.56062"
|
||||
y="91.4384"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect141"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="138.2327"
|
||||
y="92.284622"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect142"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="136.64868"
|
||||
y="74.056625"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect143"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="139.58972"
|
||||
y="77.0811"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect144"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="156.16737"
|
||||
y="74.056625"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect145"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="159.04572"
|
||||
y="77.016617"
|
||||
ry="1.3447782" />
|
||||
<path
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path151"
|
||||
d="m 163.17692,62.151119 a 10.772104,10.772104 0 0 1 -5.38605,9.328916 10.772104,10.772104 0 0 1 -10.77211,0 10.772104,10.772104 0 0 1 -5.38605,-9.328916 h 10.77211 z" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse154"
|
||||
cx="133.69824"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path153"
|
||||
cx="171.05814"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
164
assets/green_robot_inactive.svg
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="51.000004mm"
|
||||
height="51mm"
|
||||
viewBox="0 0 51.000004 51"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="tiles_and_sprites.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="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.37558051"
|
||||
inkscape:cx="49.257083"
|
||||
inkscape:cy="669.63007"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:export-bgcolor="#ffffff00"
|
||||
showgrid="false">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="51.000004"
|
||||
height="51"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7"
|
||||
inkscape:swatch="gradient">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-185.34769,-60.565987)">
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:#202a35;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect139"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="186.40314"
|
||||
y="61.621449"
|
||||
ry="8.6410732"
|
||||
inkscape:export-filename="green_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.413953;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:0.484455"
|
||||
id="rect18"
|
||||
width="51"
|
||||
height="51"
|
||||
x="185.34769"
|
||||
y="60.565987"
|
||||
ry="9.813427"
|
||||
inkscape:export-filename="blue_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189"
|
||||
rx="0" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect140"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="195.03122"
|
||||
y="91.4384"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect141"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="196.70329"
|
||||
y="92.284622"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect142"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="195.11928"
|
||||
y="74.056625"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect143"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="198.06032"
|
||||
y="77.0811"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect144"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="214.63797"
|
||||
y="74.056625"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect145"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="217.51631"
|
||||
y="77.016617"
|
||||
ry="1.3447782" />
|
||||
<path
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path151"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="210.87541"
|
||||
sodipodi:cy="62.151119"
|
||||
sodipodi:rx="10.772104"
|
||||
sodipodi:ry="10.772104"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 221.64752,62.151119 a 10.772104,10.772104 0 0 1 -5.38606,9.328916 10.772104,10.772104 0 0 1 -10.7721,0 10.772104,10.772104 0 0 1 -5.38605,-9.328916 h 10.7721 z" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse154"
|
||||
cx="192.16884"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path153"
|
||||
cx="229.52873"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
BIN
assets/green_text.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
4536
assets/gui.svg
Normal file
|
After Width: | Height: | Size: 198 KiB |
4087
assets/gui.svg.2026_10_02_19_17_27.0.svg
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
assets/locked.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/menu_btn.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
assets/menu_card.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/menu_dark_btn.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
62
assets/orange_door.svg
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 50 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-64.814606,-117.50717)">
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect123"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="118.0349"
|
||||
ry="0" />
|
||||
<path
|
||||
id="path123"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,118.5635 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path124"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 76.582814,118.56338 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path125"
|
||||
style="fill:#f8961e;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 95.427254,118.5635 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path126"
|
||||
style="fill:#f8961e;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 76.582814,118.56338 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path127"
|
||||
style="fill:#a56414;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 100.04875,118.56326 -4.621346,2.02189 v 6.04416 l 9.240666,-4.04283 v -4.02322 z m 4.61932,4.89521 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 l 9.240666,-4.04282 z m 0,7.03143 -9.240666,4.04234 v 6.04464 l 9.240666,-4.04284 z m 0,6.91614 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path128"
|
||||
style="fill:#a56414;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 81.20431,118.56313 -4.621346,2.0219 v 6.04416 l 9.240666,-4.04283 v -4.02323 z m 4.61932,4.89522 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 L 85.82363,150.482 Z m 0,7.03142 -9.240666,4.04235 v 6.04464 l 9.240666,-4.04284 z m 0,6.91615 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
48
assets/orange_press.svg
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 50 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-6.0760088,-117.50717)">
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect122"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037388"
|
||||
y="118.0349"
|
||||
ry="0" />
|
||||
<circle
|
||||
style="fill:#f8961e;fill-opacity:1;stroke:none;stroke-width:0.913567;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle123"
|
||||
cx="31.07601"
|
||||
cy="142.50717"
|
||||
r="21.640015" />
|
||||
<path
|
||||
id="path131"
|
||||
style="fill:#a56414;fill-opacity:1;stroke:none;stroke-width:0.18323;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.804079,131.7742 v 24.37118 h 3.359806 v -8.72705 a 7.8228271,7.8228271 0 0 0 6.76655,-3.8954 7.8228271,7.8228271 0 0 0 0.01251,-7.83008 7.8228271,7.8228271 0 0 0 -6.779057,-3.91865 z m 3.359806,3.15337 a 4.6701503,4.6701503 0 0 1 4.037094,2.3388 4.6701503,4.6701503 0 0 1 -0.0075,4.67436 4.6701503,4.6701503 0 0 1 -4.02959,2.32482 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/panel.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
assets/paused_card.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
assets/play_btn.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/play_dark_btn.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/quit_btn.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/quit_dark_btn.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
62
assets/red_door.svg
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50.000008mm"
|
||||
viewBox="0 0 50 50.000008"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-64.814606,-61.093724)">
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect117"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="61.621452"
|
||||
ry="0" />
|
||||
<path
|
||||
id="path117"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,62.150048 h 9.240566 v 47.887592 h -9.240566 z" />
|
||||
<path
|
||||
id="path118"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="M 76.582814,62.149927 H 85.82338 V 110.03752 H 76.582814 Z" />
|
||||
<path
|
||||
id="path119"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,62.150048 h 9.240566 v 47.887592 h -9.240566 z" />
|
||||
<path
|
||||
id="path120"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="M 76.582814,62.149927 H 85.82338 V 110.03752 H 76.582814 Z" />
|
||||
<path
|
||||
id="path121"
|
||||
style="fill:#ac2d2f;fill-opacity:1;stroke-width:0.509742"
|
||||
d="M 100.04875,62.149806 95.427404,64.1717 v 6.044159 l 9.240666,-4.042831 v -4.023222 z m 4.61932,4.895213 -9.240666,4.042833 v 6.044159 l 9.240666,-4.042355 z m 0,7.031429 -9.240666,4.042832 v 6.044159 l 9.240666,-4.042353 z m 0,7.03143 -9.240666,4.042831 v 6.044638 l 9.240666,-4.042833 z m 0,6.916629 -9.240666,4.042354 v 6.044633 l 9.240666,-4.042827 z m 0,7.031429 -9.240666,4.042344 v 6.04464 l 9.240666,-4.04284 z m 0,6.916144 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path122"
|
||||
style="fill:#ac2d2f;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 81.20431,62.149685 -4.621346,2.021894 v 6.044159 l 9.240666,-4.042831 v -4.023222 z m 4.61932,4.895213 -9.240666,4.042833 v 6.044159 l 9.240666,-4.042355 z m 0,7.031429 -9.240666,4.042832 v 6.044159 l 9.240666,-4.042353 z m 0,7.03143 -9.240666,4.042831 v 6.044638 l 9.240666,-4.042833 z m 0,6.916629 -9.240666,4.042354 v 6.044633 l 9.240666,-4.042827 z m 0,7.031429 -9.240666,4.042344 v 6.044641 l 9.240666,-4.04284 z m 0,6.916145 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
48
assets/red_press.svg
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 50 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-6.0760088,-61.093727)">
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect116"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037388"
|
||||
y="61.621456"
|
||||
ry="0" />
|
||||
<circle
|
||||
style="fill:#f94144;fill-opacity:1;stroke:none;stroke-width:0.913567;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle117"
|
||||
cx="31.07601"
|
||||
cy="86.093727"
|
||||
r="21.640015" />
|
||||
<path
|
||||
id="path130"
|
||||
style="fill:#ac2d2f;fill-opacity:1;stroke:none;stroke-width:0.18323;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.804079,74.738089 v 24.371174 h 3.359806 v -8.72705 a 7.8228271,7.8228271 0 0 0 6.76655,-3.895397 7.8228271,7.8228271 0 0 0 0.01251,-7.830081 7.8228271,7.8228271 0 0 0 -6.779057,-3.918646 z m 3.359806,3.153368 a 4.6701503,4.6701503 0 0 1 4.037094,2.338798 4.6701503,4.6701503 0 0 1 -0.0075,4.674359 4.6701503,4.6701503 0 0 1 -4.02959,2.32482 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/resume_btn.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/resume_dark_btn.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/retry_btn.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
assets/retry_dark_btn.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/select_card.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
62
assets/teal_door.svg
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 50 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-64.814606,-173.92063)">
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect93"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="174.44835"
|
||||
ry="0" />
|
||||
<path
|
||||
id="path114"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,174.97696 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path110"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 76.582814,174.97684 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path115"
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 95.427254,174.97696 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path111"
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 76.582814,174.97684 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path116"
|
||||
style="fill:#2b6e5a;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 100.04875,174.97672 -4.621346,2.02189 v 6.04416 l 9.240666,-4.04283 v -4.02322 z m 4.61932,4.89521 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 l 9.240666,-4.04282 z m 0,7.03143 -9.240666,4.04234 v 6.04464 l 9.240666,-4.04284 z m 0,6.91614 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="rect99"
|
||||
style="fill:#2b6e5a;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 81.20431,174.97659 -4.621346,2.0219 v 6.04416 l 9.240666,-4.04283 v -4.02323 z m 4.61932,4.89522 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 l 9.240666,-4.04282 z m 0,7.03142 -9.240666,4.04235 v 6.04464 l 9.240666,-4.04284 z m 0,6.91615 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
48
assets/teal_press.svg
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50.000004mm"
|
||||
viewBox="0 0 50 50.000004"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-6.0760088,-173.92063)">
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect97"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037388"
|
||||
y="174.44835"
|
||||
ry="0" />
|
||||
<circle
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke:none;stroke-width:0.913567;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path97"
|
||||
cx="31.07601"
|
||||
cy="198.92062"
|
||||
r="21.640015" />
|
||||
<path
|
||||
id="rect128"
|
||||
style="fill:#2b6e5a;fill-opacity:1;stroke:none;stroke-width:0.18323;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.804079,188.31218 v 24.37118 h 3.359806 v -8.72705 a 7.8228271,7.8228271 0 0 0 6.76655,-3.8954 7.8228271,7.8228271 0 0 0 0.01251,-7.83008 7.8228271,7.8228271 0 0 0 -6.779057,-3.91865 z m 3.359806,3.15337 a 4.6701503,4.6701503 0 0 1 4.037094,2.3388 4.6701503,4.6701503 0 0 1 -0.0075,4.67436 4.6701503,4.6701503 0 0 1 -4.02959,2.32482 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
759
assets/tiles_and_sprites.svg
Normal file
|
|
@ -0,0 +1,759 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="tiles_and_sprites.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="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.0623021"
|
||||
inkscape:cx="844.86324"
|
||||
inkscape:cy="221.68835"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:export-bgcolor="#ffffff00"
|
||||
showgrid="false" />
|
||||
<defs
|
||||
id="defs1">
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect151"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect149"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1 @ F,0,1,1,0,4.8312155,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect146"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<linearGradient
|
||||
id="linearGradient7"
|
||||
inkscape:swatch="gradient">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#f94144;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect87"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="0"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:#f3722c;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect88"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="24.48016"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:#f8961e;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect89"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="48.96032"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:none;stroke-width:0.794;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect90"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="73.440483"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:#90be6d;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect91"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="97.920647"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect92"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="122.40081"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:#577590;fill-opacity:1;stroke:none;stroke-width:0.79375;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect86"
|
||||
width="21.310066"
|
||||
height="21.310066"
|
||||
x="146.88098"
|
||||
y="-32.053158" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:none;stroke-width:1.07822;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect94"
|
||||
width="50"
|
||||
height="50"
|
||||
x="6.0760098"
|
||||
y="6.3401856"
|
||||
ry="0" />
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect146"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037378"
|
||||
y="6.8679175"
|
||||
ry="0"
|
||||
inkscape:export-filename="floor.svg"
|
||||
inkscape:export-xdpi="520.19"
|
||||
inkscape:export-ydpi="520.19" />
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect149"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="128.46716"
|
||||
y="116.91409"
|
||||
ry="0"
|
||||
inkscape:export-filename="green_arrive.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#e26465;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect131"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="127.44092"
|
||||
y="175.52307"
|
||||
ry="0"
|
||||
inkscape:export-filename="blue_arrive.svg"
|
||||
inkscape:export-xdpi="520.19208"
|
||||
inkscape:export-ydpi="520.19208" />
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:#202a35;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect1"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="127.93254"
|
||||
y="61.621449"
|
||||
ry="8.6410732"
|
||||
inkscape:export-filename="green_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189" />
|
||||
<rect
|
||||
style="fill:#f9c74f;fill-opacity:1;stroke:#202a35;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect139"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="186.40314"
|
||||
y="61.621449"
|
||||
ry="8.6410732"
|
||||
inkscape:export-filename="green_robot_inactive.svg"
|
||||
inkscape:export-xdpi="509.99213"
|
||||
inkscape:export-ydpi="509.99213" />
|
||||
<rect
|
||||
style="fill:#e26465;fill-opacity:1;stroke:#202a35;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect2"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="127.88802"
|
||||
y="6.3288074"
|
||||
ry="8.6410732"
|
||||
inkscape:export-filename="blue_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189" />
|
||||
<rect
|
||||
style="fill:#e26465;fill-opacity:1;stroke:#202a35;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect19"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="186.35863"
|
||||
y="6.3288074"
|
||||
ry="8.6410732"
|
||||
inkscape:export-filename="blue_robot_inactive.png"
|
||||
inkscape:export-xdpi="509.99213"
|
||||
inkscape:export-ydpi="509.99213" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.413953;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:0.484455"
|
||||
id="rect20"
|
||||
width="51"
|
||||
height="51"
|
||||
x="185.35863"
|
||||
y="5.3288074"
|
||||
ry="9.813427"
|
||||
inkscape:export-filename="blue_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189"
|
||||
rx="0" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.413953;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:0.484455"
|
||||
id="rect18"
|
||||
width="51"
|
||||
height="51"
|
||||
x="185.34769"
|
||||
y="60.565987"
|
||||
ry="9.813427"
|
||||
inkscape:export-filename="blue_robot.svg"
|
||||
inkscape:export-xdpi="520.19189"
|
||||
inkscape:export-ydpi="520.19189"
|
||||
rx="0" />
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect116"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037388"
|
||||
y="61.621456"
|
||||
ry="0"
|
||||
inkscape:export-filename="red_press.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect122"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037388"
|
||||
y="118.0349"
|
||||
ry="0"
|
||||
inkscape:export-filename="orange_press.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#ffdc89;fill-opacity:1;stroke:#2f3d47;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect97"
|
||||
width="48.944542"
|
||||
height="48.944538"
|
||||
x="6.6037388"
|
||||
y="174.44835"
|
||||
ry="0"
|
||||
inkscape:export-filename="teal_press.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect98"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="6.3288054"
|
||||
ry="0"
|
||||
inkscape:export-filename="wall.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect117"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="61.621452"
|
||||
ry="0"
|
||||
inkscape:export-filename="red_door.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect123"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="118.0349"
|
||||
ry="0"
|
||||
inkscape:export-filename="orange_door.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect93"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="174.44835"
|
||||
ry="0"
|
||||
inkscape:export-filename="teal_door.svg"
|
||||
inkscape:export-xdpi="520.19202"
|
||||
inkscape:export-ydpi="520.19202" />
|
||||
<circle
|
||||
style="fill:#f94144;fill-opacity:1;stroke:none;stroke-width:0.913567;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle117"
|
||||
cx="31.07601"
|
||||
cy="86.093727"
|
||||
r="21.640015" />
|
||||
<circle
|
||||
style="fill:#f8961e;fill-opacity:1;stroke:none;stroke-width:0.913567;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle123"
|
||||
cx="31.07601"
|
||||
cy="142.50717"
|
||||
r="21.640015" />
|
||||
<circle
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke:none;stroke-width:0.913567;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path97"
|
||||
cx="31.07601"
|
||||
cy="198.92062"
|
||||
r="21.640015" />
|
||||
<path
|
||||
id="path117"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,62.150048 h 9.240566 v 47.887592 h -9.240566 z" />
|
||||
<path
|
||||
id="path123"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,118.5635 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path114"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,174.97696 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path118"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="M 76.582814,62.149927 H 85.82338 V 110.03752 H 76.582814 Z" />
|
||||
<path
|
||||
id="path124"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 76.582814,118.56338 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path110"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 76.582814,174.97684 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path119"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="m 95.427254,62.150048 h 9.240566 v 47.887592 h -9.240566 z" />
|
||||
<path
|
||||
id="path125"
|
||||
style="fill:#f8961e;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 95.427254,118.5635 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path115"
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 95.427254,174.97696 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path120"
|
||||
style="fill:#f94144;stroke-width:0.509742"
|
||||
d="M 76.582814,62.149927 H 85.82338 V 110.03752 H 76.582814 Z" />
|
||||
<path
|
||||
id="path126"
|
||||
style="fill:#f8961e;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 76.582814,118.56338 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path111"
|
||||
style="fill:#43aa8b;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 76.582814,174.97684 h 9.240566 v 47.88759 h -9.240566 z" />
|
||||
<path
|
||||
id="path121"
|
||||
style="fill:#ac2d2f;fill-opacity:1;stroke-width:0.509742"
|
||||
d="M 100.04875,62.149806 95.427404,64.1717 v 6.044159 l 9.240666,-4.042831 v -4.023222 z m 4.61932,4.895213 -9.240666,4.042833 v 6.044159 l 9.240666,-4.042355 z m 0,7.031429 -9.240666,4.042832 v 6.044159 l 9.240666,-4.042353 z m 0,7.03143 -9.240666,4.042831 v 6.044638 l 9.240666,-4.042833 z m 0,6.916629 -9.240666,4.042354 v 6.044633 l 9.240666,-4.042827 z m 0,7.031429 -9.240666,4.042344 v 6.04464 l 9.240666,-4.04284 z m 0,6.916144 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path127"
|
||||
style="fill:#a56414;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 100.04875,118.56326 -4.621346,2.02189 v 6.04416 l 9.240666,-4.04283 v -4.02322 z m 4.61932,4.89521 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 l 9.240666,-4.04282 z m 0,7.03143 -9.240666,4.04234 v 6.04464 l 9.240666,-4.04284 z m 0,6.91614 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path116"
|
||||
style="fill:#2b6e5a;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 100.04875,174.97672 -4.621346,2.02189 v 6.04416 l 9.240666,-4.04283 v -4.02322 z m 4.61932,4.89521 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04235 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 l 9.240666,-4.04282 z m 0,7.03143 -9.240666,4.04234 v 6.04464 l 9.240666,-4.04284 z m 0,6.91614 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path122"
|
||||
style="fill:#ac2d2f;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 81.20431,62.149685 -4.621346,2.021894 v 6.044159 l 9.240666,-4.042831 v -4.023222 z m 4.61932,4.895213 -9.240666,4.042833 v 6.044159 l 9.240666,-4.042355 z m 0,7.031429 -9.240666,4.042832 v 6.044159 l 9.240666,-4.042353 z m 0,7.03143 -9.240666,4.042831 v 6.044638 l 9.240666,-4.042833 z m 0,6.916629 -9.240666,4.042354 v 6.044633 l 9.240666,-4.042827 z m 0,7.031429 -9.240666,4.042344 v 6.044641 l 9.240666,-4.04284 z m 0,6.916145 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path128"
|
||||
style="fill:#a56414;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 81.20431,118.56313 -4.621346,2.0219 v 6.04416 l 9.240666,-4.04283 v -4.02323 z m 4.61932,4.89522 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 L 85.82363,150.482 Z m 0,7.03142 -9.240666,4.04235 v 6.04464 l 9.240666,-4.04284 z m 0,6.91615 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="rect99"
|
||||
style="fill:#2b6e5a;fill-opacity:1;stroke-width:0.509742"
|
||||
d="m 81.20431,174.97659 -4.621346,2.0219 v 6.04416 l 9.240666,-4.04283 v -4.02323 z m 4.61932,4.89522 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04416 l 9.240666,-4.04236 z m 0,7.03143 -9.240666,4.04283 v 6.04464 l 9.240666,-4.04284 z m 0,6.91663 -9.240666,4.04235 v 6.04463 l 9.240666,-4.04282 z m 0,7.03142 -9.240666,4.04235 v 6.04464 l 9.240666,-4.04284 z m 0,6.91615 -9.240666,4.04236 v 4.0232 h 4.620126 l 4.62054,-2.0214 z" />
|
||||
<path
|
||||
id="path130"
|
||||
style="fill:#ac2d2f;fill-opacity:1;stroke:none;stroke-width:0.18323;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.804079,74.738089 v 24.371174 h 3.359806 v -8.72705 a 7.8228271,7.8228271 0 0 0 6.76655,-3.895397 7.8228271,7.8228271 0 0 0 0.01251,-7.830081 7.8228271,7.8228271 0 0 0 -6.779057,-3.918646 z m 3.359806,3.153368 a 4.6701503,4.6701503 0 0 1 4.037094,2.338798 4.6701503,4.6701503 0 0 1 -0.0075,4.674359 4.6701503,4.6701503 0 0 1 -4.02959,2.32482 z" />
|
||||
<path
|
||||
id="path131"
|
||||
style="fill:#a56414;fill-opacity:1;stroke:none;stroke-width:0.18323;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.804079,131.7742 v 24.37118 h 3.359806 v -8.72705 a 7.8228271,7.8228271 0 0 0 6.76655,-3.8954 7.8228271,7.8228271 0 0 0 0.01251,-7.83008 7.8228271,7.8228271 0 0 0 -6.779057,-3.91865 z m 3.359806,3.15337 a 4.6701503,4.6701503 0 0 1 4.037094,2.3388 4.6701503,4.6701503 0 0 1 -0.0075,4.67436 4.6701503,4.6701503 0 0 1 -4.02959,2.32482 z" />
|
||||
<path
|
||||
id="rect128"
|
||||
style="fill:#2b6e5a;fill-opacity:1;stroke:none;stroke-width:0.18323;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.804079,188.31218 v 24.37118 h 3.359806 v -8.72705 a 7.8228271,7.8228271 0 0 0 6.76655,-3.8954 7.8228271,7.8228271 0 0 0 0.01251,-7.83008 7.8228271,7.8228271 0 0 0 -6.779057,-3.91865 z m 3.359806,3.15337 a 4.6701503,4.6701503 0 0 1 4.037094,2.3388 4.6701503,4.6701503 0 0 1 -0.0075,4.67436 4.6701503,4.6701503 0 0 1 -4.02959,2.32482 z" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="136.56062"
|
||||
y="91.4384"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect140"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="195.03122"
|
||||
y="91.4384"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="136.64062"
|
||||
y="36.123081"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:1.1049;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect138"
|
||||
width="32.757622"
|
||||
height="6.6924181"
|
||||
x="195.11122"
|
||||
y="36.123081"
|
||||
ry="1.7611626" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect5"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="138.2327"
|
||||
y="92.284622"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect141"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="196.70329"
|
||||
y="92.284622"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect6"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="138.3127"
|
||||
y="36.96928"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.904968;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect132"
|
||||
width="29.413462"
|
||||
height="5"
|
||||
x="196.78329"
|
||||
y="36.96928"
|
||||
ry="1.3157895" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect7"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="136.64868"
|
||||
y="74.056625"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect142"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="195.11928"
|
||||
y="74.056625"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect8"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="136.71138"
|
||||
y="19.479122"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect136"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="195.18198"
|
||||
y="19.479122"
|
||||
ry="2.6417439" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect9"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="139.58972"
|
||||
y="77.0811"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect143"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="198.06032"
|
||||
y="77.0811"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect10"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="139.65242"
|
||||
y="22.50359"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect137"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="198.12302"
|
||||
y="22.50359"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect11"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="156.16737"
|
||||
y="74.056625"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect144"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="214.63797"
|
||||
y="74.056625"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect12"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="156.16737"
|
||||
y="19.479122"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect133"
|
||||
width="12.416687"
|
||||
height="12.768898"
|
||||
x="214.63797"
|
||||
y="19.479122"
|
||||
ry="2.7397261" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect13"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="159.04572"
|
||||
y="77.016617"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#5a8639;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect145"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="217.51631"
|
||||
y="77.016617"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect14"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="159.12572"
|
||||
y="22.613567"
|
||||
ry="1.3447782" />
|
||||
<rect
|
||||
style="fill:#3b4f63;fill-opacity:1;stroke:none;stroke-width:0.409877;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect135"
|
||||
width="6.5"
|
||||
height="6.5"
|
||||
x="217.59631"
|
||||
y="22.613567"
|
||||
ry="1.3447782" />
|
||||
<path
|
||||
id="path149"
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:#5a8639;stroke-width:0.793999;stroke-opacity:1"
|
||||
inkscape:transform-center-y="-2.3624085"
|
||||
transform="matrix(1.0541644,0,0,1.0541644,-109.57743,15.67794)"
|
||||
d="m 250.53942,103.41605 3.48296,10.57748 11.13607,0.0439 a 1.5908266,1.5908266 71.999982 0 1 0.93386,2.87412 l -8.98348,6.58112 3.39951,10.60459 a 1.590828,1.590828 144.00001 0 1 -2.44488,1.77631 l -9.03506,-6.51012 -9.03507,6.51012 a 1.5908289,1.5908289 36.000002 0 1 -2.44488,-1.77631 l 3.39951,-10.60459 -8.98348,-6.58112 a 1.5908266,1.5908266 108.00002 0 1 0.93386,-2.87412 l 11.13607,-0.0439 3.48297,-10.57748 a 1.5908286,1.5908286 1.7041414e-5 0 1 3.02204,0 z"
|
||||
inkscape:path-effect="#path-effect151"
|
||||
inkscape:original-d="m 249.0284,98.827209 4.99398,15.166321 15.96725,0.0629 -12.8808,9.43621 4.87432,15.2052 -12.95475,-9.33442 -12.95476,9.33442 4.87432,-15.2052 -12.8808,-9.43621 15.96725,-0.0629 z"
|
||||
inkscape:transform-center-x="1.2977838e-05" />
|
||||
<path
|
||||
id="path146"
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:#3b4f63;stroke-width:0.793999;stroke-opacity:1"
|
||||
inkscape:transform-center-y="-2.3624085"
|
||||
transform="matrix(1.0541644,0,0,1.0541644,-110.60368,74.286918)"
|
||||
d="m 250.53942,103.41605 3.48296,10.57748 11.13607,0.0439 a 1.5908266,1.5908266 71.999982 0 1 0.93386,2.87412 l -8.98348,6.58112 3.39951,10.60459 a 1.590828,1.590828 144.00001 0 1 -2.44488,1.77631 l -9.03506,-6.51012 -9.03507,6.51012 a 1.5908289,1.5908289 36.000002 0 1 -2.44488,-1.77631 l 3.39951,-10.60459 -8.98348,-6.58112 a 1.5908266,1.5908266 108.00002 0 1 0.93386,-2.87412 l 11.13607,-0.0439 3.48297,-10.57748 a 1.5908286,1.5908286 1.7041414e-5 0 1 3.02204,0 z"
|
||||
inkscape:path-effect="#path-effect149"
|
||||
inkscape:original-d="m 249.0284,98.827209 4.99398,15.166321 15.96725,0.0629 -12.8808,9.43621 4.87432,15.2052 -12.95475,-9.33442 -12.95476,9.33442 4.87432,-15.2052 -12.8808,-9.43621 15.96725,-0.0629 z"
|
||||
inkscape:transform-center-x="1.2977838e-05" />
|
||||
<path
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path14"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="152.36029"
|
||||
sodipodi:cy="6.8746271"
|
||||
sodipodi:rx="10.772104"
|
||||
sodipodi:ry="10.772104"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 163.13239,6.8746271 a 10.772104,10.772104 0 0 1 -5.38605,9.3289159 10.772104,10.772104 0 0 1 -10.7721,0 10.772104,10.772104 0 0 1 -5.38605,-9.3289159 h 10.7721 z" />
|
||||
<path
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path152"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="210.83089"
|
||||
sodipodi:cy="6.8746271"
|
||||
sodipodi:rx="10.772104"
|
||||
sodipodi:ry="10.772104"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 221.60299,6.8746271 a 10.772104,10.772104 0 0 1 -5.38605,9.3289159 10.772104,10.772104 0 0 1 -10.77211,0 10.772104,10.772104 0 0 1 -5.38605,-9.3289159 h 10.77211 z" />
|
||||
<path
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path15"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="152.40482"
|
||||
sodipodi:cy="62.151119"
|
||||
sodipodi:rx="10.772104"
|
||||
sodipodi:ry="10.772104"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 163.17692,62.151119 a 10.772104,10.772104 0 0 1 -5.38605,9.328916 10.772104,10.772104 0 0 1 -10.77211,0 10.772104,10.772104 0 0 1 -5.38605,-9.328916 h 10.77211 z" />
|
||||
<path
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.793999;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path151"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="210.87541"
|
||||
sodipodi:cy="62.151119"
|
||||
sodipodi:rx="10.772104"
|
||||
sodipodi:ry="10.772104"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1415927"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 221.64752,62.151119 a 10.772104,10.772104 0 0 1 -5.38606,9.328916 10.772104,10.772104 0 0 1 -10.7721,0 10.772104,10.772104 0 0 1 -5.38605,-9.328916 h 10.7721 z" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse15"
|
||||
cx="133.69824"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse155"
|
||||
cx="192.16884"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse16"
|
||||
cx="133.69824"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse154"
|
||||
cx="192.16884"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse17"
|
||||
cx="171.05814"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#4f789a;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse156"
|
||||
cx="229.52873"
|
||||
cy="49.03196"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse18"
|
||||
cx="171.05814"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
<ellipse
|
||||
style="fill:#7fbe51;fill-opacity:1;stroke:none;stroke-width:0.321662;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path153"
|
||||
cx="229.52873"
|
||||
cy="104.57764"
|
||||
rx="1.9423375"
|
||||
ry="1.8339512" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 31 KiB |
BIN
assets/timer.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/unlocked.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
38
assets/wall.svg
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50mm"
|
||||
height="50mm"
|
||||
viewBox="0 0 50 50"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1">
|
||||
<linearGradient
|
||||
id="linearGradient7">
|
||||
<stop
|
||||
style="stop-color:#bcb776;stop-opacity:1;"
|
||||
offset="0.26068801"
|
||||
id="stop7" />
|
||||
<stop
|
||||
style="stop-color:#9a9147;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-64.814606,-5.801076)">
|
||||
<rect
|
||||
style="fill:#273843;fill-opacity:1;stroke:#202a35;stroke-width:1.05546;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect98"
|
||||
width="48.944538"
|
||||
height="48.944542"
|
||||
x="65.342339"
|
||||
y="6.3288054"
|
||||
ry="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 958 B |
43
constants.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# CONSTANTS
|
||||
FPS = 60
|
||||
SCALE_FACTOR = 1
|
||||
|
||||
# Tiles
|
||||
TILE_SIZE = 32
|
||||
|
||||
# SCREEN AND PANEL
|
||||
WIDTH = 1280
|
||||
HEIGHT = 720
|
||||
GAME_PANEL_W = 960
|
||||
GAME_PANEL_H = 640
|
||||
X_OFFSET = WIDTH/2 - GAME_PANEL_W / 2
|
||||
Y_OFFSET = HEIGHT/2 - GAME_PANEL_H / 2
|
||||
|
||||
PANEL_WIDTH = 120
|
||||
PANEL_HEIGHT = 120
|
||||
PANEL_T_HEIGHT = 50
|
||||
PANEL_T_WIDTH = 140
|
||||
|
||||
|
||||
# WALL_COLOR = (50, 50, 50)
|
||||
# FLOOR_COLOR = (200, 200, 200)
|
||||
# RED_DOOR = (200, 0, 0)
|
||||
# RED_PLATE = (100, 0, 0)
|
||||
# BLUE_ARRIVE = (0, 0, 100)
|
||||
# GREEN_ARRIVE = (0, 100, 0)
|
||||
# BG_COLOR = (255, 0, 255)
|
||||
|
||||
# BUTTONS
|
||||
MAX_BTN = 3
|
||||
BTN_WIDTH = 232
|
||||
BTN_HEIGHT = 82
|
||||
|
||||
# COLORS
|
||||
BLUE = (43, 69, 104)
|
||||
GREEN= (43, 104, 43)
|
||||
RED = (93, 38, 38)
|
||||
|
||||
LIGHT = (100, 100, 100)
|
||||
DARK = (64, 56, 43)
|
||||
DARK_TEXT = (62,51,34)
|
||||
WHITE = (255, 255, 255)
|
||||
112
db_utils.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
import sqlite3
|
||||
from pathlib import *
|
||||
import json
|
||||
|
||||
def init_db():
|
||||
conn = sqlite3.connect("progress.db")
|
||||
cursor = conn.cursor()
|
||||
|
||||
for path in Path("./levels").glob("*.json"):
|
||||
with open(path, "r") as file:
|
||||
level = json.load(file)
|
||||
|
||||
level_id = level["id"]
|
||||
|
||||
# Initialize progress on levels not already in the table
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT OR IGNORE INTO player_progress
|
||||
(id, unlocked, completed, timer)
|
||||
VALUES (?, 0, 0, 0)
|
||||
""",
|
||||
(level_id,)
|
||||
)
|
||||
# For end
|
||||
|
||||
# Set the unlocked property for the first level
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE player_progress
|
||||
SET unlocked = TRUE
|
||||
WHERE id = ?
|
||||
""",
|
||||
("001",)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def get_levels():
|
||||
levels = sorted(Path("./levels").glob("*.json"))
|
||||
return levels
|
||||
|
||||
def reset_db():
|
||||
conn = sqlite3.connect("progress.db")
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute(
|
||||
"""
|
||||
DELETE FROM player_progress
|
||||
"""
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def get_progress():
|
||||
conn = sqlite3.connect("progress.db")
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Set the completed property fand timer
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT unlocked, timer FROM player_progress
|
||||
ORDER BY id ASC
|
||||
""",
|
||||
)
|
||||
result = cursor.fetchall()
|
||||
|
||||
conn.close()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def save_progress(level_state):
|
||||
conn = sqlite3.connect("progress.db")
|
||||
cursor = conn.cursor()
|
||||
|
||||
level_id = level_state.level.id
|
||||
|
||||
# Set the completed property fand timer
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE player_progress
|
||||
SET completed = TRUE, timer = ?
|
||||
WHERE id = ?
|
||||
""",
|
||||
(level_state.final_time, level_id,)
|
||||
)
|
||||
|
||||
unlock_level_id = None
|
||||
next_level_number = level_state.level.level_number + 1
|
||||
|
||||
for path in Path("./levels").glob("*.json"):
|
||||
if int(path.name.split("_")[0]) == next_level_number:
|
||||
with open(path, "r") as file:
|
||||
level = json.load(file)
|
||||
unlock_level_id = level["id"]
|
||||
break
|
||||
|
||||
if unlock_level_id is not None:
|
||||
# Set the unlocked property for the next level
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE player_progress
|
||||
SET unlocked = TRUE
|
||||
WHERE id = ?
|
||||
""",
|
||||
(unlock_level_id,)
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
100
gamestate.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# libraries
|
||||
from datetime import timedelta
|
||||
|
||||
# project modules
|
||||
import db_utils as db
|
||||
import db_utils
|
||||
from new_gui import *
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Enum and Tables
|
||||
# -----------------------------------------------------
|
||||
class State(Enum):
|
||||
MENU = 0
|
||||
PLAY = 1
|
||||
PAUSE = 2
|
||||
SELECT = 3
|
||||
COMPLETE = 4
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Class GameState
|
||||
# - Represents the game state (playing, pause, menu...)
|
||||
# - creates and keeps the different views
|
||||
# ------------------------------------------------------
|
||||
class GameState:
|
||||
def __init__(self):
|
||||
self.running = True
|
||||
self.state = State.MENU
|
||||
self.level_state = None
|
||||
|
||||
# Game time keeping
|
||||
self.play_start = 0
|
||||
self.paused_time = 0
|
||||
self.pause_start = 0
|
||||
self.elapsed = 0
|
||||
|
||||
# Views
|
||||
self.start_menu = self.create_start_menu()
|
||||
self.pause_menu = self.create_pause_menu()
|
||||
self.select_menu = self.create_select_menu()
|
||||
# It will get created at the end of each level
|
||||
self.completed_menu = None
|
||||
|
||||
def update(self, ticks):
|
||||
# update elapsed playing time
|
||||
if self.state == State.PLAY:
|
||||
self.elapsed = ticks - self.play_start - self.paused_time
|
||||
|
||||
# If the current level has been completed. This block of code is executed ONCE with the last check of the if
|
||||
if self.level_state != None and self.level_state.completed == True and self.state != State.COMPLETE:
|
||||
# save total time inside the level state
|
||||
self.level_state.final_time = self.elapsed
|
||||
self.state = State.COMPLETE
|
||||
self.completed_menu = self.create_completed_menu()
|
||||
|
||||
self.save_progress()
|
||||
self.select_menu = self.create_select_menu()
|
||||
|
||||
def save_progress(self):
|
||||
# Save progress in db and unlock next level
|
||||
db.save_progress(self.level_state)
|
||||
|
||||
# Functions that create the views
|
||||
def create_pause_menu(self):
|
||||
menu = MenuPage(MenuType.PAUSE)
|
||||
menu.add_top_text("Don't worry, the clock isn't ticking!")
|
||||
menu.add_button("playing", ButtonTypes.RESUME)
|
||||
menu.add_button("select_level", ButtonTypes.MENU)
|
||||
return menu
|
||||
|
||||
def create_start_menu(self):
|
||||
menu = MenuPage(MenuType.START)
|
||||
menu.add_button("select_level", ButtonTypes.PLAY)
|
||||
menu.add_button("delete", ButtonTypes.DELETE)
|
||||
menu.add_button("quit_game", ButtonTypes.QUIT)
|
||||
return menu
|
||||
|
||||
def create_completed_menu(self):
|
||||
# Text with the time formatted
|
||||
timer = timedelta(milliseconds=self.level_state.final_time)
|
||||
text = f"Timer: {str(timer).split(".")[0]}"
|
||||
|
||||
menu = MenuPage(MenuType.COMPLETED)
|
||||
menu.add_top_text("Play the level again to beat your time!")
|
||||
menu.add_bottom_text(text)
|
||||
menu.add_button("retry", ButtonTypes.RETRY)
|
||||
menu.add_button("select_level", ButtonTypes.MENU)
|
||||
return menu
|
||||
|
||||
def create_select_menu(self):
|
||||
level_paths = db_utils.get_levels()
|
||||
progress = db_utils.get_progress()
|
||||
menu = Menu(MenuType.SELECT)
|
||||
# Adding buttons based on level files
|
||||
for info in zip(level_paths, progress):
|
||||
# print(f"Path: {info[0]}, Completato:{info[1][0]}, Tempo:{info[1][1]}")
|
||||
time_text = str(timedelta(milliseconds=info[1][1])).split(".")[0]
|
||||
text = f"{info[0].name.split('.')[0].split('_')[1]} - {time_text}"
|
||||
menu.add_entry(text, (info[0],info[1][0]), EntryState.UNLOCKED if int(info[1][0]) == 1 else EntryState.LOCKED)
|
||||
return menu
|
||||
|
||||
17
levels/00_tutorial.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "001",
|
||||
"map": [
|
||||
["#","#","#","#","#","#","#","#","#","#"],
|
||||
["#","G",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".","b",".",".","R",".",".",".","#"],
|
||||
["#",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".","#",".","g",".","#"],
|
||||
["#",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".","#",".",".",".","#"],
|
||||
["#","r",".",".",".","#",".",".","B","#"],
|
||||
["#","#","#","#","#","#","#","#","#","#"]
|
||||
]
|
||||
}
|
||||
25
levels/01_livello1.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"id": "002",
|
||||
"map":[
|
||||
["#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#"],
|
||||
["#","G",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".","b",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","R",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".","g",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".",".","#"],
|
||||
["#","r",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".",".","#",".",".","B","#"],
|
||||
["#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#","#"]
|
||||
]
|
||||
}
|
||||
4
levels/02_livello2.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"id": "003",
|
||||
"map": [[]]
|
||||
}
|
||||
4
levels/03_livello3.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"id": "004",
|
||||
"map": [[]]
|
||||
}
|
||||
4
levels/04_livello4.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"id": "005",
|
||||
"map": [[]]
|
||||
}
|
||||
365
levelstate.py
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
# libraries
|
||||
import pygame
|
||||
import numpy as np
|
||||
import json
|
||||
|
||||
# project modules
|
||||
from constants import *
|
||||
from player import *
|
||||
from new_gui import *
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Enum and Tables
|
||||
# -------------------------------------------------------------------------------
|
||||
class TileTypes(Enum):
|
||||
FLOOR = 0
|
||||
WALL = 1
|
||||
RED_PLATE = 2
|
||||
RED_DOOR = 3
|
||||
ORANGE_PLATE = 4
|
||||
ORANGE_DOOR = 5
|
||||
TEAL_PLATE = 6
|
||||
TEAL_DOOR = 7
|
||||
BLUE_ARRIVE = 8
|
||||
GREEN_ARRIVE = 9
|
||||
|
||||
TILE_FILES = {
|
||||
TileTypes.FLOOR: "assets/floor.svg",
|
||||
TileTypes.WALL : "assets/wall.svg",
|
||||
TileTypes.RED_PLATE : "assets/red_press.svg",
|
||||
TileTypes.RED_DOOR : "assets/red_door.svg",
|
||||
TileTypes.ORANGE_PLATE : "assets/orange_press.svg",
|
||||
TileTypes.ORANGE_DOOR : "assets/orange_door.svg",
|
||||
TileTypes.TEAL_PLATE : "assets/teal_press.svg",
|
||||
TileTypes.TEAL_DOOR : "assets/teal_door.svg",
|
||||
TileTypes.BLUE_ARRIVE : "assets/blue_arrive.svg",
|
||||
TileTypes.GREEN_ARRIVE : "assets/green_arrive.svg"
|
||||
}
|
||||
|
||||
class GamePanel(Enum):
|
||||
BLUE_PANE = 0
|
||||
BLUE_TEXT = 1
|
||||
GREEN_TEXT = 2
|
||||
GREEN_PANE = 3
|
||||
TIMER = 4
|
||||
|
||||
PANEL_FILES = {
|
||||
GamePanel.BLUE_PANE: "assets/blue_pane.png",
|
||||
GamePanel.BLUE_TEXT: "assets/blue_text.png",
|
||||
GamePanel.GREEN_PANE: "assets/green_pane.png",
|
||||
GamePanel.GREEN_TEXT: "assets/green_text.png",
|
||||
GamePanel.TIMER: "assets/timer.png"
|
||||
}
|
||||
|
||||
class Direction(Enum):
|
||||
HORIZ = 0
|
||||
VERT = 1
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Class Level
|
||||
# - represents the static data of the current level being played
|
||||
# -------------------------------------------------------------------------------
|
||||
class Level:
|
||||
def __init__(self, path):
|
||||
# Saving the order number of the level
|
||||
self.level_number = int(path.name.split("_")[0])
|
||||
|
||||
# Level data file loading
|
||||
with open(path, "r") as file:
|
||||
level_data = json.load(file)
|
||||
self.map = np.array(level_data["map"])
|
||||
self.id = level_data["id"]
|
||||
|
||||
# LOADING TILE IMAGES
|
||||
target_size = (TILE_SIZE, TILE_SIZE)
|
||||
self.floor_tile = self.load_tile(TileTypes.FLOOR ,target_size)
|
||||
self.wall_tile = self.load_tile(TileTypes.WALL ,target_size)
|
||||
|
||||
self.red_press = self.load_tile(TileTypes.RED_PLATE ,target_size)
|
||||
self.red_door = self.load_tile(TileTypes.RED_DOOR ,target_size)
|
||||
self.orange_press = self.load_tile(TileTypes.ORANGE_PLATE ,target_size)
|
||||
self.orange_door = self.load_tile(TileTypes.ORANGE_DOOR ,target_size)
|
||||
self.teal_press = self.load_tile(TileTypes.TEAL_PLATE ,target_size)
|
||||
self.teal_door = self.load_tile(TileTypes.TEAL_DOOR ,target_size)
|
||||
|
||||
self.blue_arrive = self.load_tile(TileTypes.BLUE_ARRIVE ,target_size)
|
||||
self.green_arrive = self.load_tile(TileTypes.GREEN_ARRIVE ,target_size)
|
||||
|
||||
self.doors, self.plates = self.load_objs()
|
||||
|
||||
# For now this method does this with the map, in the future they will be encoded differently in the json
|
||||
# maybe already in arrays to make everything easier
|
||||
def load_objs(self):
|
||||
doors = {}
|
||||
plates = {}
|
||||
for (row, col), character in np.ndenumerate(self.map):
|
||||
if character in ('R'):
|
||||
# Todo: choose type based on character
|
||||
doors[character] = Door(col, row, TileTypes.RED_DOOR)
|
||||
if character.lower() in plates:
|
||||
plates[character.lower()].set_door(doors[character])
|
||||
if character in ('r'):
|
||||
# Todo: choose type based on character
|
||||
plates[character] = PressurePlate(col, row, TileTypes.RED_PLATE)
|
||||
if character.upper() in doors:
|
||||
plates[character].set_door(doors[character.upper()])
|
||||
|
||||
|
||||
#for (row, col), character in np.ndenumerate(self.map):
|
||||
# if character == 'r':
|
||||
# plates.append(PressurePlate(col, row, TileTypes.RED_PLATE))
|
||||
|
||||
return doors, plates
|
||||
|
||||
|
||||
def load_tile(self, type, target_size):
|
||||
return pygame.transform.smoothscale(pygame.image.load(TILE_FILES.get(type, TILE_FILES[TileTypes.FLOOR])).convert_alpha(), target_size)
|
||||
|
||||
def draw(self, screen, pressing):
|
||||
for (row, col), character in np.ndenumerate(self.map):
|
||||
|
||||
# Convert grid coordinates to pixel coordinates
|
||||
x = col * TILE_SIZE + X_OFFSET
|
||||
y = row * TILE_SIZE + Y_OFFSET
|
||||
|
||||
# Create the rectangle boundary for the tile
|
||||
rect = pygame.Rect(x, y, TILE_SIZE, TILE_SIZE)
|
||||
|
||||
# Draw the appropriate tile color
|
||||
if character == '#':
|
||||
screen.blit(self.wall_tile, rect)
|
||||
# elif character == 'R' and pressing != "red":
|
||||
# screen.blit(self.red_door, rect)
|
||||
# elif character == 'r':
|
||||
# screen.blit(self.red_press, rect)
|
||||
elif character == 'B':
|
||||
screen.blit(self.blue_arrive, rect)
|
||||
elif character == 'G':
|
||||
screen.blit(self.green_arrive, rect)
|
||||
else:
|
||||
screen.blit(self.floor_tile, rect)
|
||||
|
||||
for element in list(self.doors.values()) + list(self.plates.values()):
|
||||
element.draw(screen)
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# Class LevelState
|
||||
# - represents the state of the current level being played
|
||||
# - it manages all the gameplay logic and mechanics
|
||||
# -------------------------------------------------------------------------------
|
||||
class LevelState:
|
||||
def __init__(self, level):
|
||||
self.level = level
|
||||
|
||||
# Players setup
|
||||
b_rows, b_cols = np.where(level.map == 'b')
|
||||
g_rows, g_cols = np.where(level.map == 'g')
|
||||
|
||||
blue_y, blue_x = b_rows[0], b_cols[0]
|
||||
green_y, green_x = g_rows[0], g_cols[0]
|
||||
self.players = [Player(blue_x, blue_y, True, PlayerTypes.BLUE), Player(green_x, green_y, False, PlayerTypes.GREEN)]
|
||||
self.curr_player_i = 0
|
||||
self.player = self.players[self.curr_player_i]
|
||||
|
||||
# Sprite group for ease
|
||||
self.all_sprites = pygame.sprite.Group()
|
||||
self.all_sprites.add(self.players)
|
||||
|
||||
# state variables
|
||||
self.pressing = "none"
|
||||
self.blue_arrive = False
|
||||
self.green_arrive = False
|
||||
|
||||
# Completion and final time
|
||||
self.completed = False
|
||||
self.final_time = 0
|
||||
|
||||
# GUI ELEMENTS
|
||||
self.blue_pane = self.load_gui(GamePanel.BLUE_PANE)
|
||||
self.green_pane = self.load_gui(GamePanel.GREEN_PANE)
|
||||
self.blue_text = self.load_gui(GamePanel.BLUE_TEXT)
|
||||
self.green_text = self.load_gui(GamePanel.GREEN_TEXT)
|
||||
self.timer = self.load_gui(GamePanel.TIMER)
|
||||
|
||||
def load_gui(self, element):
|
||||
return pygame.image.load(PANEL_FILES.get(element, None)).convert_alpha()
|
||||
|
||||
def change_player(self):
|
||||
self.player.active = False
|
||||
self.curr_player_i = 1 - self.curr_player_i
|
||||
self.player = self.players[self.curr_player_i]
|
||||
self.player.active = True
|
||||
|
||||
def try_move(self, dir, x, y, speed):
|
||||
if dir == Direction.HORIZ:
|
||||
next_x = x + speed
|
||||
if (self.level.map[y, next_x] == '#' or
|
||||
(self.level.map[y, next_x] == 'R' and self.pressing != "red") or
|
||||
(next_x == self.players[1-self.curr_player_i].x and y == self.players[1-self.curr_player_i].y)):
|
||||
return x
|
||||
|
||||
return next_x
|
||||
else:
|
||||
next_y = y + speed
|
||||
if (self.level.map[next_y, x] == '#' or
|
||||
(self.level.map[next_y, x] == 'R' and self.pressing != "red") or
|
||||
(next_y == self.players[1-self.curr_player_i].y and x == self.players[1-self.curr_player_i].x)):
|
||||
return y
|
||||
|
||||
return next_y
|
||||
|
||||
def update(self):
|
||||
# to facilitate usage
|
||||
p1 = self.players[0]
|
||||
p2 = self.players[1]
|
||||
|
||||
# check for pressure on plates
|
||||
# TODO: Add the other types of plates to press
|
||||
if (self.level.map[p1.y, p1.x] == "r" and p1.powers[p1.current_power_i] == Powers.PRESS.value) or \
|
||||
(self.level.map[p2.y, p2.x] == "r" and p2.powers[p2.current_power_i] == Powers.PRESS.value):
|
||||
self.pressing = "red"
|
||||
else:
|
||||
self.pressing = "none"
|
||||
|
||||
for plate in self.level.plates.values():
|
||||
if((p1.rect.x, p1.rect.y) == (plate.x, plate.y) and
|
||||
p1.powers[p1.current_power_i] == Powers.PRESS.value) or ((p2.rect.x, p2.rect.y) == (plate.x, plate.y) and
|
||||
p2.powers[p2.current_power_i] == Powers.PRESS.value):
|
||||
plate.set_pressed(True)
|
||||
else:
|
||||
plate.set_pressed(False)
|
||||
|
||||
# check for arrival
|
||||
self.blue_arrive = self.level.map[p1.y, p1.x] == "B"
|
||||
self.green_arrive = self.level.map[p2.y, p2.x] == "G"
|
||||
|
||||
# Check completed condition
|
||||
if(self.blue_arrive and self.green_arrive):
|
||||
self.completed = True
|
||||
|
||||
def draw(self, screen):
|
||||
self.level.draw(screen, self.pressing)
|
||||
|
||||
def draw_gui(self, screen, time, font):
|
||||
y = Y_OFFSET
|
||||
|
||||
# Blue pane, then blue text box with the player's power
|
||||
y = self._blit_panel(screen, self.blue_pane, y)
|
||||
y = self._blit_panel(screen, self.blue_text, y, self.players[0].current_power, BLUE, font)
|
||||
|
||||
# Green pane, then green text box with the player's power
|
||||
y = self._blit_panel(screen, self.green_pane, y)
|
||||
y = self._blit_panel(screen, self.green_text, y, self.players[1].current_power, GREEN, font)
|
||||
|
||||
# Timer box with the elapsed seconds
|
||||
self._blit_panel(screen, self.timer, y, str(time).split('.')[0], RED, font)
|
||||
|
||||
def _blit_panel(self, screen, image, y, text=None, color=None, font=None):
|
||||
x = (X_OFFSET - image.get_width()) / 2
|
||||
screen.blit(image, (x, y))
|
||||
|
||||
if text is not None:
|
||||
label = TextArea(text, color)
|
||||
label.place(x + image.get_width() / 2, y + image.get_height() / 2)
|
||||
label.draw(screen, None, font, anchor="center")
|
||||
|
||||
return y + image.get_height()
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Class MapElement
|
||||
# ---------------------------------------------------------------------
|
||||
# This is more of an abstract class that grants common method signature
|
||||
# and behaviour.
|
||||
# It inherits from Sprite so that I can add it to the group and
|
||||
# it already has the draw method implemented
|
||||
# ---------------------------------------------------------------------
|
||||
class MapElement(pygame.sprite.Sprite):
|
||||
def __init__(self, col, row, type):
|
||||
super().__init__()
|
||||
self.col = col
|
||||
self.row = row
|
||||
self.x = col * TILE_SIZE + X_OFFSET
|
||||
self.y = row * TILE_SIZE + Y_OFFSET
|
||||
self.image = self.load_image(type)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.topleft = (self.x, self.y)
|
||||
|
||||
def load_image(self, type):
|
||||
return pygame.transform.smoothscale(pygame.image.load(TILE_FILES.get(type, TILE_FILES[TileTypes.FLOOR])).convert_alpha(), (TILE_SIZE, TILE_SIZE))
|
||||
|
||||
def draw(self, screen):
|
||||
screen.blit(self.image, self.rect)
|
||||
# ----------------------------------------------------------------------
|
||||
# Class PressurePlate
|
||||
# ----------------------------------------------------------------------
|
||||
class PressurePlate(MapElement):
|
||||
def __init__(self, col, row, type):
|
||||
super().__init__(col, row, type)
|
||||
self.pressed = False
|
||||
self.door = None
|
||||
print("Plate created!")
|
||||
|
||||
# I should do the check if the value is boolean, but I do not want to
|
||||
# (all of my methods do not have such checks, which is a bit ugh)
|
||||
def set_door(self, door):
|
||||
self.door = door
|
||||
|
||||
def set_pressed(self, value):
|
||||
self.pressed = value
|
||||
if self.door is None:
|
||||
raise ValueError("Door is None")
|
||||
|
||||
self.door.set_open(self.pressed)
|
||||
|
||||
def is_pressed(self):
|
||||
return self.pressed
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Class Door
|
||||
# ----------------------------------------------------------------------
|
||||
class Door(MapElement):
|
||||
def __init__(self, col, row, type):
|
||||
super().__init__(col, row, type)
|
||||
self.open = False
|
||||
print("Door created")
|
||||
|
||||
def set_open(self, value):
|
||||
self.open = value
|
||||
|
||||
def is_open(self):
|
||||
return self.open
|
||||
|
||||
# I have to ovverride the sprite method, because I have to check if it is opened
|
||||
def draw(self, screen):
|
||||
if self.open == False:
|
||||
super().draw(screen)
|
||||
else:
|
||||
pass
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Class GrabbableObject
|
||||
# ----------------------------------------------------------------------
|
||||
# represents objects that can be grabbed and put in inventory
|
||||
# they will be necessary to press certain types of pressure plates
|
||||
# yet to be implemented
|
||||
# ----------------------------------------------------------------------
|
||||
class GrabbableObject(MapElement):
|
||||
def __init__(self, col, row, type):
|
||||
super().__init__(col, row, type)
|
||||
self.grabbed = False
|
||||
|
||||
def grab(self):
|
||||
self.grabbed = True
|
||||
|
||||
def release(self):
|
||||
self.grabbed = False
|
||||
|
||||
def is_grabbed(self):
|
||||
return self.grabbed
|
||||
|
||||
# I have to ovverride the sprite method, because I have to check if it is opened
|
||||
def draw(self, screen):
|
||||
if self.grabbed == False:
|
||||
super().draw(screen)
|
||||
else:
|
||||
pass
|
||||
201
main.py
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
from datetime import timedelta
|
||||
import pygame
|
||||
|
||||
# project modules
|
||||
from constants import *
|
||||
from levelstate import Level
|
||||
from levelstate import LevelState
|
||||
from new_gui import *
|
||||
import db_utils
|
||||
from gamestate import *
|
||||
from levelstate import Direction
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# Play state Loop
|
||||
# -----------------------------------------------------------------------------------
|
||||
def play(game_state, events):
|
||||
|
||||
# for ease of use
|
||||
levelstate = game_state.level_state
|
||||
player = levelstate.player
|
||||
|
||||
# Event polling
|
||||
for event in events:
|
||||
if event.type == pygame.QUIT:
|
||||
game_state.running = False
|
||||
|
||||
elif event.type == pygame.KEYDOWN:
|
||||
# Controls
|
||||
if event.key == pygame.K_LCTRL:
|
||||
player.change_power()
|
||||
if event.key == pygame.K_LSHIFT:
|
||||
levelstate.change_player()
|
||||
player = levelstate.player
|
||||
if event.key == pygame.K_ESCAPE:
|
||||
game_state.state = State.PAUSE
|
||||
game_state.pause_start = pygame.time.get_ticks()
|
||||
|
||||
# Movement
|
||||
if event.key == pygame.K_a:
|
||||
player.x = levelstate.try_move(Direction.HORIZ, player.x, player.y, -player.speed)
|
||||
elif event.key == pygame.K_d:
|
||||
player.x = levelstate.try_move(Direction.HORIZ, player.x, player.y, player.speed)
|
||||
elif event.key == pygame.K_w:
|
||||
player.y = levelstate.try_move(Direction.VERT, player.x, player.y, -player.speed)
|
||||
elif event.key == pygame.K_s:
|
||||
player.y = levelstate.try_move(Direction.VERT, player.x, player.y, player.speed)
|
||||
|
||||
# update level state
|
||||
levelstate.update()
|
||||
|
||||
# update sprites
|
||||
levelstate.all_sprites.update()
|
||||
|
||||
# bg
|
||||
levelstate.draw(screen)
|
||||
|
||||
# Timer Text
|
||||
time = timedelta(milliseconds=game_state.elapsed)
|
||||
levelstate.draw_gui(screen, time, small_font)
|
||||
|
||||
# rendering of all the sprites
|
||||
levelstate.all_sprites.draw(screen)
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# Pause state Loop
|
||||
# -----------------------------------------------------------------------------------
|
||||
def pause_menu(game_state, events, mouse):
|
||||
# getting menu object
|
||||
menu = game_state.pause_menu
|
||||
|
||||
# Display the menu
|
||||
menu.draw(screen, mouse, title_font, small_font)
|
||||
|
||||
# Event polling handled by the menu
|
||||
for event in events:
|
||||
value = menu.handle_event(event, mouse)
|
||||
|
||||
# Actions based on what has been done in the interaction with the menu
|
||||
if value == "playing":
|
||||
game_state.state = State.PLAY
|
||||
game_state.paused_time += pygame.time.get_ticks() - game_state.pause_start
|
||||
game_state.pause_start = None
|
||||
elif value == "select_level":
|
||||
game_state.level_state = None
|
||||
game_state.state = State.SELECT
|
||||
elif value == "quit_game":
|
||||
game_state.running = False
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# Menu state Loop
|
||||
# -----------------------------------------------------------------------------------
|
||||
def start_menu(game_state, events, mouse):
|
||||
menu = game_state.start_menu
|
||||
|
||||
menu.draw(screen, mouse, title_font, small_font)
|
||||
|
||||
for event in events:
|
||||
value = menu.handle_event(event, mouse)
|
||||
if value == "quit_game":
|
||||
game_state.running = False
|
||||
elif value == "select_level":
|
||||
game_state.state = State.SELECT
|
||||
elif value == "delete":
|
||||
db_utils.reset_db()
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# Select state Loop
|
||||
# -----------------------------------------------------------------------------------
|
||||
def select_level(game_state, events, mouse):
|
||||
menu = game_state.select_menu
|
||||
|
||||
menu.draw(screen, mouse, title_font, small_font)
|
||||
|
||||
# Event polling
|
||||
for event in events:
|
||||
value = menu.handle_event(event, mouse)
|
||||
if value == "quit_game":
|
||||
game_state.running = False
|
||||
elif value == "menu":
|
||||
game_state.state = State.MENU
|
||||
# The select level buttons have 2 values, the path and if the level is unlocked
|
||||
# This is way there is the check for a tuple
|
||||
elif value != None and isinstance(value, tuple):
|
||||
completed = int(value[1])
|
||||
level_path = value[0]
|
||||
if completed == 1:
|
||||
game_state.level_state = LevelState(Level(level_path))
|
||||
game_state.state = State.PLAY
|
||||
# Start timer
|
||||
game_state.play_start = pygame.time.get_ticks()
|
||||
game_state.paused_time = 0
|
||||
game_state.elapsed = 0
|
||||
break
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# Complete state Loop
|
||||
# -----------------------------------------------------------------------------------
|
||||
def completed_menu(game_state, events, mouse):
|
||||
menu = game_state.completed_menu
|
||||
|
||||
menu.draw(screen, mouse, title_font, small_font)
|
||||
for event in events:
|
||||
value = menu.handle_event(event, mouse)
|
||||
|
||||
if value == "quit_game":
|
||||
game_state.running = False
|
||||
elif value == "select_level":
|
||||
game_state.level_state = None
|
||||
game_state.state = State.SELECT
|
||||
elif value == "retry":
|
||||
game_state.state = State.PLAY
|
||||
game_state.level_state = LevelState(game_state.level_state.level)
|
||||
# Start timer
|
||||
game_state.play_start = pygame.time.get_ticks()
|
||||
game_state.paused_time = 0
|
||||
game_state.elapsed = 0
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------
|
||||
# PYGAME SETUP
|
||||
# -----------------------------------------------------------------------------------
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
# Graphic assets
|
||||
title_font = pygame.font.Font('assets/ARCO.ttf', 35)
|
||||
small_font = pygame.font.Font('assets/ARCO.ttf', 20)
|
||||
background = pygame.transform.scale_by(pygame.image.load('assets/background.png').convert_alpha(), SCALE_FACTOR)
|
||||
|
||||
# Db Init
|
||||
db_utils.init_db()
|
||||
|
||||
# GameState setup
|
||||
game_state = GameState()
|
||||
|
||||
# MAIN LOOP
|
||||
while game_state.running:
|
||||
screen.blit(background, (0, 0))
|
||||
events = pygame.event.get()
|
||||
mouse = pygame.mouse.get_pos()
|
||||
|
||||
if game_state.state == State.MENU:
|
||||
start_menu(game_state, events, mouse)
|
||||
elif game_state.state == State.PLAY:
|
||||
play(game_state, events)
|
||||
elif game_state.state == State.PAUSE:
|
||||
pause_menu(game_state, events, mouse)
|
||||
elif game_state.state == State.SELECT:
|
||||
select_level(game_state, events, mouse)
|
||||
elif game_state.state == State.COMPLETE:
|
||||
completed_menu(game_state, events, mouse)
|
||||
|
||||
# update game_state
|
||||
game_state.update(pygame.time.get_ticks())
|
||||
|
||||
pygame.display.flip()
|
||||
clock.tick(FPS)
|
||||
|
||||
pygame.quit()
|
||||
|
||||
307
new_gui.py
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
# libraries
|
||||
from enum import Enum
|
||||
from functools import lru_cache
|
||||
import pygame
|
||||
|
||||
# project modules
|
||||
from constants import *
|
||||
|
||||
# NOTE_1
|
||||
# Refactored using AI (Claude), did a great job, uses some obscure syntax
|
||||
# still much better than the original which was becoming unusable
|
||||
# I will use some of the stuff introduced by AI in this file to refactor all the other files
|
||||
|
||||
# NOTE_2
|
||||
# The .get() function takes 2 values, the first is the field of the dictionary, the second
|
||||
# is a default value to return if the key is not found
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Enum and tables
|
||||
# -------------------------------------------------------------
|
||||
|
||||
class ButtonTypes(Enum):
|
||||
# The value doubles as the asset prefix: assets/<value>_btn.png
|
||||
# and assets/<value>_dark_btn.png
|
||||
PLAY = "play"
|
||||
RESUME = "resume"
|
||||
MENU = "menu"
|
||||
DELETE = "delete"
|
||||
QUIT = "quit"
|
||||
RETRY = "retry"
|
||||
FW = "fw"
|
||||
BW = "bw"
|
||||
GO = "go"
|
||||
|
||||
|
||||
class MenuType(Enum):
|
||||
PAUSE = 0
|
||||
COMPLETED = 1
|
||||
START = 2
|
||||
SELECT = 3
|
||||
|
||||
|
||||
class EntryState(Enum):
|
||||
UNLOCKED = 0
|
||||
LOCKED = 1
|
||||
|
||||
|
||||
# Unscaled hitbox sizes (width, height); anything not listed uses the default
|
||||
DEFAULT_HITBOX = (232, 82) # Defaults to a normal button
|
||||
HITBOX_SIZES = {
|
||||
ButtonTypes.FW: (105, 82),
|
||||
ButtonTypes.BW: (105, 82),
|
||||
ButtonTypes.GO: (83, 63),
|
||||
}
|
||||
|
||||
CARD_FILES = {
|
||||
MenuType.PAUSE: "assets/paused_card.png",
|
||||
MenuType.COMPLETED: "assets/completed_card.png",
|
||||
MenuType.START: "assets/menu_card.png",
|
||||
MenuType.SELECT: "assets/select_card.png",
|
||||
}
|
||||
|
||||
ICON_FILES = {
|
||||
EntryState.LOCKED: "assets/locked.png",
|
||||
EntryState.UNLOCKED: "assets/unlocked.png",
|
||||
}
|
||||
|
||||
# Layout constants for SelectEntry
|
||||
ENTRY_WIDTH = 500
|
||||
ENTRY_PADDING = 20
|
||||
ENTRY_ICON_X = 800
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def load_image(path, scale=1):
|
||||
image = pygame.image.load(path).convert_alpha()
|
||||
if scale != 1:
|
||||
image = pygame.transform.scale_by(image, scale)
|
||||
return image
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Widgets
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
class Widget:
|
||||
# Anything a MenuPage can stack vertically.
|
||||
|
||||
# Note: this notation is called type hinting
|
||||
rect: pygame.Rect
|
||||
|
||||
def place(self, centerx, y):
|
||||
self.rect.centerx = centerx
|
||||
self.rect.y = y
|
||||
|
||||
# This are just the interface for the methods implemented in the various widgets
|
||||
def height(self, text_font):
|
||||
return self.rect.height
|
||||
|
||||
def draw(self, screen, mouse, text_font):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Button(Widget):
|
||||
def __init__(self, value, kind=ButtonTypes.PLAY):
|
||||
# value is a free-form field returned when the button is clicked
|
||||
self.value = value
|
||||
self.kind = kind
|
||||
|
||||
# f-strings from python 3.6 to embed variables
|
||||
prefix = f"assets/{kind.value}"
|
||||
self.image = load_image(f"{prefix}_btn.png", SCALE_FACTOR)
|
||||
self.dark_image = load_image(f"{prefix}_dark_btn.png", SCALE_FACTOR)
|
||||
|
||||
width, height = HITBOX_SIZES.get(kind, DEFAULT_HITBOX)
|
||||
self.rect = pygame.Rect(0, 0, int(width * SCALE_FACTOR), int(height * SCALE_FACTOR))
|
||||
|
||||
# text font is none because buttons have text in the image but the interface is the same for all widgets
|
||||
def height(self, text_font=None):
|
||||
return self.image.get_height() / 2
|
||||
|
||||
def clicked(self, mouse):
|
||||
return self.rect.collidepoint(mouse)
|
||||
|
||||
def draw(self, screen, mouse, text_font=None):
|
||||
image = self.dark_image if self.clicked(mouse) else self.image
|
||||
# The image is always centred on the hitbox, so nothing to keep in sync
|
||||
screen.blit(image, image.get_rect(center=self.rect.center))
|
||||
|
||||
|
||||
class TextArea(Widget):
|
||||
def __init__(self, text, color):
|
||||
self.text = text
|
||||
self.color = color
|
||||
self.rect = pygame.Rect(0, 0, 0, 0)
|
||||
|
||||
def height(self, text_font):
|
||||
return text_font.size(self.text)[1]
|
||||
|
||||
def draw(self, screen, mouse, text_font, anchor="midtop"):
|
||||
# The anchor can be any rect attribute like midtop, topleft etc
|
||||
surface = text_font.render(self.text, True, self.color)
|
||||
position = getattr(self.rect, anchor)
|
||||
screen.blit(surface, surface.get_rect(**{anchor: position}))
|
||||
|
||||
|
||||
class SelectEntry(Widget):
|
||||
# One row of the level-select menu: [go button] [label] ........ [lock icon]
|
||||
|
||||
def __init__(self, text, value, state):
|
||||
self.value = value
|
||||
self.btn = Button(value, ButtonTypes.GO)
|
||||
self.label = TextArea(text, DARK)
|
||||
self.icon = load_image(ICON_FILES[state])
|
||||
self.icon_rect = self.icon.get_rect()
|
||||
self.rect = pygame.Rect(0, 0, ENTRY_WIDTH, self.btn.rect.height)
|
||||
|
||||
def place(self, centerx, y):
|
||||
super().place(centerx, y)
|
||||
x = self.rect.x + ENTRY_PADDING
|
||||
self.btn.rect.topleft = (x, self.rect.y)
|
||||
self.label.rect.midleft = (x + self.btn.rect.width * 3, self.rect.centery)
|
||||
self.icon_rect.topleft = (ENTRY_ICON_X, self.rect.y)
|
||||
|
||||
def clicked(self, mouse):
|
||||
return self.btn.clicked(mouse)
|
||||
|
||||
def draw(self, screen, mouse, text_font):
|
||||
self.btn.draw(screen, mouse)
|
||||
self.label.draw(screen, mouse, text_font, anchor="center")
|
||||
screen.blit(self.icon, self.icon_rect)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Menu page
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
class MenuPage:
|
||||
"""One card with optional top text, buttons, entries and bottom text,
|
||||
stacked vertically and centred on screen."""
|
||||
|
||||
def __init__(self, kind):
|
||||
self.top_text_area = None
|
||||
self.bottom_text_area = None
|
||||
self.buttons = []
|
||||
self.entries = []
|
||||
self.total_height = 0 # set by draw(), read by Menu
|
||||
self.bg_image = load_image(CARD_FILES[kind], SCALE_FACTOR)
|
||||
|
||||
@property
|
||||
def is_full(self):
|
||||
return len(self.buttons) + len(self.entries) >= MAX_BTN
|
||||
|
||||
def add_button(self, value, kind):
|
||||
self.buttons.append(Button(value, kind))
|
||||
|
||||
def add_entry(self, text, value, state):
|
||||
self.entries.append(SelectEntry(text, value, state))
|
||||
|
||||
def add_top_text(self, text):
|
||||
self.top_text_area = TextArea(text, DARK)
|
||||
|
||||
def add_bottom_text(self, text):
|
||||
self.bottom_text_area = TextArea(text, DARK)
|
||||
|
||||
def _elements(self):
|
||||
elements = []
|
||||
if self.top_text_area:
|
||||
elements.append(self.top_text_area)
|
||||
elements.extend(self.buttons)
|
||||
elements.extend(self.entries)
|
||||
if self.bottom_text_area:
|
||||
elements.append(self.bottom_text_area)
|
||||
return elements
|
||||
|
||||
def draw(self, screen, mouse, btn_font, text_font):
|
||||
# btn_font is unused now; kept so existing calls don't break
|
||||
center_x, center_y = screen.get_rect().center
|
||||
screen.blit(self.bg_image, self.bg_image.get_rect(center=(center_x, center_y)))
|
||||
|
||||
elements = self._elements()
|
||||
spacing = BTN_HEIGHT * 0.5
|
||||
heights = [e.height(text_font) for e in elements]
|
||||
self.total_height = sum(heights) + spacing * max(len(elements) - 1, 0)
|
||||
|
||||
y = center_y - self.total_height / 2
|
||||
for element, height in zip(elements, heights):
|
||||
element.place(center_x, y)
|
||||
element.draw(screen, mouse, text_font)
|
||||
y += height + spacing
|
||||
|
||||
def handle_event(self, event, mouse):
|
||||
if event.type == pygame.QUIT:
|
||||
return "quit_game"
|
||||
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
for clickable in (*self.buttons, *self.entries):
|
||||
if clickable.clicked(mouse):
|
||||
return clickable.value
|
||||
return None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Multi-page menu
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
class Menu:
|
||||
"""Paged menu: new pages are created automatically when one is full.
|
||||
For now pages hold only buttons or entries, no top/bottom text."""
|
||||
|
||||
def __init__(self, menu_type):
|
||||
self.menu_type = menu_type
|
||||
self.pages = [MenuPage(menu_type)]
|
||||
self.current_page_i = 0
|
||||
|
||||
self.prev_btn = Button(None, ButtonTypes.BW)
|
||||
self.menu_btn = Button("menu", ButtonTypes.MENU)
|
||||
self.next_btn = Button(None, ButtonTypes.FW)
|
||||
self.nav_buttons = (self.prev_btn, self.menu_btn, self.next_btn)
|
||||
|
||||
@property
|
||||
def page(self):
|
||||
return self.pages[self.current_page_i]
|
||||
|
||||
def _page_with_room(self):
|
||||
if self.pages[-1].is_full:
|
||||
self.pages.append(MenuPage(self.menu_type))
|
||||
return self.pages[-1]
|
||||
|
||||
def add_button(self, value, kind):
|
||||
self._page_with_room().add_button(value, kind)
|
||||
|
||||
def add_entry(self, text, value, state):
|
||||
self._page_with_room().add_entry(text, value, state)
|
||||
|
||||
def draw(self, screen, mouse, btn_font, text_font):
|
||||
center_x, center_y = screen.get_rect().center
|
||||
self.page.draw(screen, mouse, btn_font, text_font)
|
||||
|
||||
spacing = BTN_HEIGHT * 0.5
|
||||
bottom_y = center_y + self.page.total_height / 2 + spacing
|
||||
|
||||
group_width = sum(b.rect.width for b in self.nav_buttons)
|
||||
step = group_width / 2.5
|
||||
|
||||
# Left / middle / right, spaced `step` apart around the centre
|
||||
for i, button in enumerate(self.nav_buttons):
|
||||
button.place(center_x + (i - 1) * step, bottom_y)
|
||||
button.draw(screen, mouse)
|
||||
|
||||
def handle_event(self, event, mouse):
|
||||
if event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if self.prev_btn.clicked(mouse):
|
||||
self.current_page_i = max(self.current_page_i - 1, 0)
|
||||
return None
|
||||
if self.next_btn.clicked(mouse):
|
||||
self.current_page_i = min(self.current_page_i + 1, len(self.pages) - 1)
|
||||
return None
|
||||
if self.menu_btn.clicked(mouse):
|
||||
return self.menu_btn.value
|
||||
|
||||
# Also handles pygame.QUIT and clicks on the page's own buttons
|
||||
return self.page.handle_event(event, mouse)
|
||||
66
player.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# libraries
|
||||
from enum import Enum
|
||||
import pygame
|
||||
|
||||
# project modules
|
||||
from constants import *
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Class Player
|
||||
# - represents the player object
|
||||
# ------------------------------------------------------------
|
||||
|
||||
class PlayerTypes(Enum):
|
||||
BLUE = "blue_robot"
|
||||
GREEN = "green_robot"
|
||||
|
||||
class Powers(Enum):
|
||||
PRESS = "press"
|
||||
GRAB = "grab"
|
||||
|
||||
class Player(pygame.sprite.Sprite):
|
||||
def __init__(self, x, y, active, type=PlayerTypes.BLUE):
|
||||
super().__init__()
|
||||
|
||||
# Attributes
|
||||
self.speed = 1
|
||||
self.width = 50
|
||||
self.height = 50
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.active = active
|
||||
|
||||
# Yet to see if useful
|
||||
self.direction = "up"
|
||||
|
||||
# Yet to find usage for grab
|
||||
self.powers = [Powers.PRESS.value, Powers.GRAB.value]
|
||||
self.current_power_i = 0
|
||||
self.current_power = self.powers[self.current_power_i]
|
||||
|
||||
# Sprite image
|
||||
self.active_sprite = pygame.image.load(f"assets/{type.value}.svg").convert_alpha()
|
||||
self.inactive_sprite = pygame.image.load(f"assets/{type.value}_inactive.svg").convert_alpha()
|
||||
self.image = pygame.transform.smoothscale(self.inactive_sprite, (TILE_SIZE, TILE_SIZE))
|
||||
|
||||
# Hitbox and position
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.topleft = (self.x*TILE_SIZE, self.y*TILE_SIZE)
|
||||
|
||||
def update(self):
|
||||
self.image = pygame.transform.smoothscale(self.inactive_sprite, (TILE_SIZE, TILE_SIZE))
|
||||
|
||||
if self.active:
|
||||
self.image = pygame.transform.smoothscale(self.active_sprite, (TILE_SIZE, TILE_SIZE))
|
||||
|
||||
# update rect position
|
||||
self.rect.x = self.x * TILE_SIZE + X_OFFSET
|
||||
self.rect.y = self.y * TILE_SIZE + Y_OFFSET
|
||||
|
||||
# Function to change current power
|
||||
def change_power(self):
|
||||
self.current_power_i += 1
|
||||
if self.current_power_i >= len(self.powers):
|
||||
self.current_power_i = 0
|
||||
|
||||
self.current_power = self.powers[self.current_power_i]
|
||||