Initial import
authorAntonio Ospite <ospite@studenti.unina.it>
Wed, 6 Mar 2013 11:07:05 +0000 (12:07 +0100)
committerAntonio Ospite <ospite@studenti.unina.it>
Wed, 6 Mar 2013 11:07:05 +0000 (12:07 +0100)
README.txt [new file with mode: 0644]
pygame-vertical-scrolling-map.py [new file with mode: 0755]
road.png [new file with mode: 0644]
road.svg [new file with mode: 0644]

diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..3c6a1b8
--- /dev/null
@@ -0,0 +1,14 @@
+An example of a vertical scrolling map with pygame
+
+There are some assumptions on the scrolling image for the seamless looping
+effect to work:
+  - The image height must be at least twice the height of the
+    screen/viewport.
+  - The image must have two identical regions, one at the top and one at
+    the bottom, of the same height as the screen/viewport.
+
+See the "Viewport" layer in the "road.svg" image.
+
+A png image ready to use can be generated with this command line:
+
+  inkscape --file=road.svg --export-area-page --export-width=800 --export-png=road.png 
diff --git a/pygame-vertical-scrolling-map.py b/pygame-vertical-scrolling-map.py
new file mode 100755 (executable)
index 0000000..132b44a
--- /dev/null
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+
+# An example of a vertical scrolling map with pygame
+#
+# Copyright (C) 2013  Antonio Ospite <ospite@studenti.unina.it>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Reference:
+# https://www.cs.ucsb.edu/~pconrad/cs5nm/topics/pygame/drawing/
+
+import pygame
+
+IMAGE_PATH = 'road.png'
+SCREEN_WIDTH = 800
+SCREEN_HEIGHT = 480
+
+
+class VerticalScrollingMap(pygame.Surface):
+    """
+    There are some assumptions on the scrolling image for the seamless looping
+    effect to work:
+      - The image height must be at least twice the height of the
+        screen/viewport.
+      - The image must have two identical regions, one at the top and one at
+        the bottom, of the same height as the screen/viewport.
+    """
+    def __init__(self, image, *args, **kwargs):
+        super(VerticalScrollingMap, self).__init__(*args, **kwargs)
+
+        self.viewport_width, self.viewport_height = self.get_size()
+
+        self.texture = pygame.image.load(image)
+        self.texture_widht, self.texture_height = self.texture.get_size()
+
+        self.offset = 0
+        self.y = 0
+
+        # Center along X
+        self.x = (self.viewport_width - self.texture_widht) / 2.0
+
+    def draw(self, screen):
+        self.y += self.offset
+
+        # NOTE, we assume that the texture has at least twice the height of the
+        # viewport
+        lastframe_limit = -(self.texture_height - self.viewport_height)
+
+        # Wrap around to cycle seamlessly
+        self.y %= lastframe_limit
+
+        screen.blit(self.texture, (self.x, self.y))
+
+    def set_offset(self, offset):
+        self.offset = offset
+
+    def inc_offset(self, amount=1):
+        self.offset += amount
+
+    def dec_offset(self, amount=1):
+        self.offset -= amount
+
+
+def main():
+    pygame.init()
+
+    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT),
+            pygame.HWSURFACE | pygame.DOUBLEBUF)
+    pygame.display.set_caption('Vertical Scrolling Map')
+    pygame.mouse.set_visible(0)
+
+    screen_size = screen.get_size()
+
+    bg_color = (0, 0, 0)
+    background = pygame.Surface(screen_size)
+    background.fill(bg_color)
+
+    screen.blit(background.convert(), (0, 0))
+
+    scrolling_map = VerticalScrollingMap(IMAGE_PATH, screen_size)
+
+    # If there is a joustick connected it will take precedence
+    # to set the scrolling offset over the key presses
+    try:
+        joystick = pygame.joystick.Joystick(0)
+        joystick.init()
+        axis = 1
+    except:
+        joystick = None
+
+    clock = pygame.time.Clock()
+
+    fps = 30
+    exit = False
+    while not exit:
+        msElapsed = clock.tick(fps)
+
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                exit = True
+                break
+
+        if joystick:
+            val = joystick.get_axis(axis)
+            scrolling_map.set_offset(int(val * 50))
+
+        key = pygame.key.get_pressed()
+        if key[pygame.K_ESCAPE]:
+            exit = True
+        if key[pygame.K_UP]:
+            scrolling_map.inc_offset()
+        if key[pygame.K_DOWN]:
+            scrolling_map.dec_offset()
+
+        if exit:
+            break
+
+        screen.blit(background.convert(), (0, 0))
+        scrolling_map.draw(screen)
+
+        pygame.display.update()
+
+    pygame.quit()
+
+if __name__ == '__main__':
+    main()
diff --git a/road.png b/road.png
new file mode 100644 (file)
index 0000000..48ae0c9
Binary files /dev/null and b/road.png differ
diff --git a/road.svg b/road.svg
new file mode 100644 (file)
index 0000000..130f15a
--- /dev/null
+++ b/road.svg
@@ -0,0 +1,146 @@
+<?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="5492.126"
+   height="56444.879"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.3.1 r9886"
+   sodipodi:docname="road.svg"
+   inkscape:export-filename="/home/ao2/WIP/pygame-experiments/road.png"
+   inkscape:export-xdpi="13.11"
+   inkscape:export-ydpi="13.11">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.01"
+     inkscape:cx="2746.063"
+     inkscape:cy="28222.441"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1152"
+     inkscape:window-height="756"
+     inkscape:window-x="0"
+     inkscape:window-y="29"
+     inkscape:window-maximized="1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="cm" />
+  <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:groupmode="layer"
+     id="layer3"
+     inkscape:label="Background"
+     style="display:inline"
+     transform="translate(0,37311.023)"
+     sodipodi:insensitive="true">
+    <path
+       transform="translate(-164.82684,18492.735)"
+       style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5.80000019;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 164.82684,-55803.758 5492.12596,0 0,56444.87909 -5492.12596,0 z"
+       id="rect4044"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+  <g
+     inkscape:label="Lane"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-164.82684,55803.758)"
+     style="display:inline">
+    <path
+       style="color:#000000;fill:#555753;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 164.82698,-55803.746 0.009,56444.86691 5492.11672,0 0,-56444.86691 z"
+       id="rect3094-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:354.33071899;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1062.99212598, 1062.99212598;stroke-dashoffset:2125.98365904"
+       d="m 341.9922,463.95706 -1e-5,-56090.55306"
+       id="path3971-2-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:#555753;stroke:#ffffff;stroke-width:354.33071899000009353;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1062.99212598000008256, 1062.99212598000008256;stroke-dashoffset:2125.98365904000002047;display:inline"
+       d="m 5479.7875,463.95555 0,-56090.55255"
+       id="path3971-2-7-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#ffffff;stroke-width:354.33099365;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:2125.98538316;display:inline"
+       d="m 2910.8898,463.95555 c 0,0 0,-2337.10635 0,-3505.65955 0,-1172.9171 1081.0261,-2144.5229 1100,-3305.6595 21.0522,-1288.3203 -928.9006,-2428.5779 -1100,-3705.6595 -199.4852,-1488.953 83.3323,-3003.496 100,-4505.66 9.2668,-835.168 0,-1670.439 0,-2505.659 0,-735.22 7.6483,-1470.48 0,-2205.66 -16.6676,-1602.146 -369.004,-3226.169 -100,-4805.659 191.5606,-1124.771 1169.9172,-2065.089 1200,-3205.66 35.0701,-1329.66 -910.0065,-2507.533 -1200,-3805.659 -271.7431,-1216.43 -416.4789,-2462.048 -500,-3705.66 -73.8364,-1099.41 -144.3288,-2213.266 0,-3305.659 235.3611,-1781.396 1579.0946,-3417.731 1400,-5205.66 -67.0289,-669.159 -846.253,-1135.302 -900,-1805.659 -89.4577,-1115.757 974.5796,-2086.611 1000,-3205.66 29.7871,-1311.278 -1000,-2494.043 -1000,-3805.659 0,-1212.78 0,-3505.66 0,-3505.66"
+       id="path3971-2-7-7-2"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csaaaaaaaaaaaaasc" />
+    <rect
+       style="color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:354.33099365;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991"
+       width="5492.126"
+       height="7.0866141"
+       x="164.82684"
+       y="-1010.0585"
+       inkscape:export-xdpi="13.11"
+       inkscape:export-ydpi="13.11" />
+    <rect
+       transform="translate(164.82684,-18492.735)"
+       style="display:inline;color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:354.33099364999998215;marker:none;visibility:visible;overflow:visible;enable-background:accumulate"
+       id="rect2991-2"
+       width="5492.126"
+       height="7.0866141"
+       x="-8.2812494e-06"
+       y="-35666.93"
+       inkscape:export-xdpi="13.11"
+       inkscape:export-ydpi="13.11" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="Viewport"
+     style="display:none"
+     transform="translate(0,37311.023)">
+    <path
+       transform="translate(-164.82684,18492.735)"
+       style="color:#000000;fill:#000000;fill-opacity:0.5078125;stroke:none;stroke-width:354.33071899;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 164.82684,-55803.758 5492.12596,0 0,3295.276 -5492.12596,0 z"
+       id="rect2997-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <rect
+       style="color:#000000;fill:#000000;fill-opacity:0.5078125;stroke:none;stroke-width:354.33071899;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2997"
+       width="5492.126"
+       height="3295.2756"
+       x="-2.2737368e-13"
+       y="15838.582" />
+  </g>
+</svg>