Merge branch 'master' of ctpug.org.za:tabakrolletjie
authorSimon Cross <hodgestar@gmail.com>
Sat, 10 Sep 2016 21:04:06 +0000 (23:04 +0200)
committerSimon Cross <hodgestar@gmail.com>
Sat, 10 Sep 2016 21:04:06 +0000 (23:04 +0200)
data/images/48/circle.png [new file with mode: 0644]
data/images/48/square.png [new file with mode: 0644]
data/images/Makefile
sources/vector/circle.svg [new file with mode: 0644]
sources/vector/square.svg [new file with mode: 0644]
tabakrolletjie/scenes/day.py
tabakrolletjie/scenes/help.py
tabakrolletjie/scenes/night.py
tabakrolletjie/utils.py

diff --git a/data/images/48/circle.png b/data/images/48/circle.png
new file mode 100644 (file)
index 0000000..7ed598c
Binary files /dev/null and b/data/images/48/circle.png differ
diff --git a/data/images/48/square.png b/data/images/48/square.png
new file mode 100644 (file)
index 0000000..38dba77
Binary files /dev/null and b/data/images/48/square.png differ
index 3b92dcb38e310dea268327ec26e35bc9a77ea977..08ea9db61481fd2210cf23a7fce52cd72766e4ee 100644 (file)
@@ -7,10 +7,11 @@ MOULD=eyeballA eyeballB eyeballC eyelid
 LIGHT=spotlight lamp laser
 LIGHT_MASK=light_mask_2_1 light_mask_2_2 light_mask_3_1 light_mask_3_2 light_mask_3_3
 CONTROLS=night default_cursor exit pause play day
+BLANKS=circle square
 
 IMG16=$(MOULD_BODY)
 IMG32=$(MOULD_BODY) $(MOULD) $(LIGHT) $(SEED) $(LIGHT_MASK) $(CONTROLS)
-IMG48=$(LIGHT) $(TURNIP) $(LIGHT_MASK)
+IMG48=$(LIGHT) $(TURNIP) $(LIGHT_MASK) $(BLANKS)
 IMG64=$(MOULD_BODY)
 
 CURSORS=$(SEED) $(LIGHT)
diff --git a/sources/vector/circle.svg b/sources/vector/circle.svg
new file mode 100644 (file)
index 0000000..19cabeb
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="100mm"
+   height="100mm"
+   viewBox="0 0 354.33071 354.33071"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="circle.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="89.927834"
+     inkscape:cy="168.74492"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1264"
+     inkscape:window-height="720"
+     inkscape:window-x="102"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:object-nodes="true"
+     inkscape:snap-smooth-nodes="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4423"
+       units="mm"
+       spacingx="3.543307"
+       spacingy="3.543307" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-698.0315)">
+    <circle
+       style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path5236"
+       cx="177.16536"
+       cy="875.19684"
+       r="159.44882" />
+  </g>
+</svg>
diff --git a/sources/vector/square.svg b/sources/vector/square.svg
new file mode 100644 (file)
index 0000000..88176f4
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="100mm"
+   height="100mm"
+   viewBox="0 0 354.33071 354.33071"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="square.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="89.927834"
+     inkscape:cy="168.74492"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1264"
+     inkscape:window-height="720"
+     inkscape:window-x="102"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:object-nodes="true"
+     inkscape:snap-smooth-nodes="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4423"
+       units="mm"
+       spacingx="3.543307"
+       spacingy="3.543307" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-698.0315)">
+    <rect
+       style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect5276"
+       width="318.89764"
+       height="318.89764"
+       x="17.716536"
+       y="715.74805" />
+  </g>
+</svg>
index e2d1e19bcb6634b62366fb83efe1bad7fafbbb94..7f73ad288a17342946d91a928577220da0e86ddb 100644 (file)
@@ -53,6 +53,7 @@ class DayScene(BaseScene):
             self._draw_you_lose(gamestate)
         elif gamestate.harvested >= gamestate.turnip_target:
             self._draw_you_win(gamestate)
+        self._ending = False
 
     def _draw_you_lose(self, gamestate):
         overlay = pygame.surface.Surface(
@@ -128,8 +129,11 @@ class DayScene(BaseScene):
         gamestate.turnips = turnip_data
 
     def end_day(self, gamestate):
+        if self._ending:
+            return
         self._battery.apply_recharge()
         gamestate.update_lights(self._lights)
+        self._ending = True
         from .night import NightScene
         SceneChangeEvent.post(scene=NightScene())
 
@@ -226,12 +230,16 @@ class DayScene(BaseScene):
             self._lights.add_light(cfg)
 
     def event(self, ev, gamestate):
+        if self._ending:
+            return
         if self._game_over_text:
             if ev.type in (pgl.KEYDOWN, pgl.MOUSEBUTTONDOWN):
+                self._ending = True
                 from .menu import MenuScene
                 SceneChangeEvent.post(scene=MenuScene())
         if ev.type == pgl.KEYDOWN:
             if ev.key in (pgl.K_q, pgl.K_ESCAPE):
+                self._ending = True
                 from .menu import MenuScene
                 SceneChangeEvent.post(scene=MenuScene())
             elif ev.key == pgl.K_e:
@@ -251,6 +259,7 @@ class DayScene(BaseScene):
                         elif tool.name == 'start night':
                             self.end_day(gamestate)
                         elif tool.name == 'exit':
+                            self._ending = True
                             from .menu import MenuScene
                             SceneChangeEvent.post(scene=MenuScene())
                         else:
index c58fea548eb8cc1dbcf77f6d17770ca6c12c140d..46c176d0943fe5817c13e22d913e3cf740acfff4 100644 (file)
@@ -61,17 +61,35 @@ class HelpScene(BaseScene):
                 "This is a space turnip, the most valuable vegetable in the"
                 " universe. A crucial ingredient of longevity serum, space"
                 " navigator tonic and a pink sweet that everyone loves.")),
-            HelpItem(("64", "mouldA.png"), (
-                "This is Boyd the space mould. He loves turnips. You've"
-                " disinfected your ship a thousand times, but somehow he shows"
-                " up on every planet at night to devour your crop. He is"
-                " vulnerable to light, but beware -- he builds up a resistance"
-                " if you overuse the same colour.")),
+        ]
+
+        mould = HelpItem(("64", "mouldA.png"), (
+            "This is Boyd the space mould. He loves turnips. You've"
+            " disinfected your ship a thousand times, but somehow he shows"
+            " up on every planet at night to devour your crop. He is"
+            " vulnerable to light, but beware -- he builds up a resistance"
+            " if you overuse the same colour."))
+
+        mould._img.blit(
+            loader.load_image("32", "mouldB.png").convert_alpha(),
+            (30, 30), None)
+        mould._img.blit(
+            loader.load_image("32", "eyeballA.png").convert_alpha(),
+            (10, 10), None)
+        mould._img.blit(
+            loader.load_image("32", "eyelid.png").convert_alpha(),
+            (10, 10), None)
+
+        items.append(mould)
+
+        items.extend([
             HelpItem(("32", "seed.png"), (
                 "This is a turnip seed. You get a limited number of these at"
                 " the start of a level. You can plant them, and you can use"
                 " them to buy lights to protect your crop. Turnips which"
-                " survive to harvest yield more seeds.")),
+                " survive to harvest yield more seeds. Click on the icon that"
+                " looks like this to start planting seeds. It takes three nights"
+                " for a turnip to mature.")),
             HelpItem(("48", "lamp.png"), (
                 "This is a lamp. It comes in many colours, and has some other"
                 " varying properties. It is powered by your farm's battery"
@@ -95,18 +113,41 @@ class HelpScene(BaseScene):
                 " skip to the next day. Or you can keep playing with your lights."
                 " If you have no power left either, or you are completely"
                 " bankrupt, the night will end automatically.")),
-        ]
-
-        # Special mould assembly
-        items[1]._img.blit(
-            loader.load_image("32", "mouldB.png").convert_alpha(),
-            (30, 30), None)
-        items[1]._img.blit(
-            loader.load_image("32", "eyeballA.png").convert_alpha(),
-            (10, 10), None)
-        items[1]._img.blit(
-            loader.load_image("32", "eyelid.png").convert_alpha(),
-            (10, 10), None)
+            HelpItem(("32", "spotlight.png"), (
+                "Click on a light icon like this to get a menu of colour options"
+                " available on your level.")),
+            HelpItem(("32", "spotlight.png"), (
+                "Once you have selected a colour option, you will be able to"
+                " place the light."),
+                transform=Multiply(colour=COLOURS["magenta"])),
+            HelpItem(("32", "exit.png"), (
+                "Click this icon to quit the level in disgust and return to the"
+                " menu.")),
+        ])    
+
+        soil = HelpItem(("48", "square.png"), (
+            "This is soil. You can plant seeds in it and position lights on"
+            " it. Lights and plants can't overlap with each other."))
+        soil._img.blit(
+            loader.load_image("textures", "soil.png").convert_alpha(),
+            (0, 0), None, pgl.BLEND_RGBA_MULT)
+        items.append(soil)   
+
+        stone = HelpItem(("48", "square.png"), (
+            "This is a stone wall. It gets in your way. On the other hand, it"
+            " also gets in Boyd's way."))
+        stone._img.blit(
+            loader.load_image("textures", "stone.png").convert_alpha(),
+            (0, 0), None, pgl.BLEND_RGBA_MULT)
+        items.append(stone)  
+
+        shrub = HelpItem(("48", "circle.png"), (
+            "This is a shrub. It works exactly like a wall, except that it's"
+            " round."))
+        shrub._img.blit(
+            loader.load_image("textures", "shrub.png").convert_alpha(),
+            (0, 0), None, pgl.BLEND_RGBA_MULT)
+        items.append(shrub)
 
         return items
 
@@ -124,7 +165,7 @@ class HelpScene(BaseScene):
             height += max(
                 item._img_size, item.FONT.get_height() * len(item._text))
             height += 5
-            if height > SCREEN_SIZE[1]:
+            if height > SCREEN_SIZE[1] - 50:
                 height = 50
                 x_offset = SCREEN_SIZE[0] / 2
 
index 9459c0ed68668d6edb358879ca93917ab9c75a76..7813e32baab0ce118682dd04133a2d977d879adf 100644 (file)
@@ -47,6 +47,7 @@ class NightScene(BaseScene):
         self._paused = False
         self._eaten_tonight = 0
         self._night_over_text = []
+        self._ending = False
 
     def create_tools(self, gamestate):
         tools = []
@@ -105,11 +106,14 @@ class NightScene(BaseScene):
             surface.blit(text, text_pos, None)
 
     def event(self, ev, gamestate):
+        if self._ending:
+            return
         if ev.type == pgl.KEYDOWN:
             if not self._do_ticks:
                 # Any keypress exits
                 self._to_day(gamestate)
             if ev.key in (pgl.K_q, pgl.K_ESCAPE):
+                self._ending = True
                 from .menu import MenuScene
                 SceneChangeEvent.post(scene=MenuScene())
             elif ev.key == pgl.K_e and DEBUG:
@@ -129,6 +133,7 @@ class NightScene(BaseScene):
                         if tool.name == 'pause play':
                             self.toggle_pause()
                         elif tool.name == 'exit':
+                            self._ending = True
                             from .menu import MenuScene
                             SceneChangeEvent.post(scene=MenuScene())
                         elif tool.name == 'day':
@@ -143,7 +148,10 @@ class NightScene(BaseScene):
 
     def _to_day(self, gamestate):
         # End the night
+        if self._ending:
+            return
         gamestate.update_lights(self._lights)
+        self._ending = True
         from .day import DayScene
         SceneChangeEvent.post(scene=DayScene())
 
index 6f9e133cb999cd57b20dd64f65f251f4516415e3..19364c2b013c46279e94d6eed8b3282002e8a45d 100644 (file)
@@ -6,6 +6,7 @@ import pygame.surface
 import pygame.locals as pgl
 import os
 import sys
+import json
 
 from .constants import DEBUG
 from .loader import loader
@@ -92,3 +93,12 @@ def get_save_file_name():
 def save_file_exists():
     savefile = get_save_file_name()
     return os.path.isfile(savefile)
+
+
+def write_save_file(json_data):
+    save_dir = save_location()
+    if not os.path.exists(save_dir):
+        os.makedirs(save_dir)
+    savefile = get_save_file_name()
+    with open(savefile, 'wb') as f:
+        json.dump(json_data, f, indent=3)