step_08.py Diff#

step_07.py to step_08.py diff#
--- /home/docs/checkouts/readthedocs.org/user_builds/arcade-library/checkouts/development/doc/tutorials/raycasting/step_07.py
+++ /home/docs/checkouts/readthedocs.org/user_builds/arcade-library/checkouts/development/doc/tutorials/raycasting/step_08.py
@@ -1,4 +1,5 @@
 import random
+from pyglet.math import Vec2
 
 import arcade
 from arcade.experimental import Shadertoy
@@ -37,7 +38,15 @@
         self.bomb_list = arcade.SpriteList()
         self.physics_engine = None
 
+        # Create cameras used for scrolling
+        self.camera_sprites = arcade.camera.Camera2D()
+        self.camera_gui = arcade.camera.Camera2D()
+
         self.generate_sprites()
+
+        # Our sample GUI text
+        self.score_text = arcade.Text("Score: 0", 10, 10, arcade.color.WHITE, 24)
+
         self.background_color = arcade.color.ARMY_GREEN
 
     def load_shader(self):
@@ -92,7 +101,13 @@
         # Physics engine, so we don't run into walls
         self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
 
+        # Start centered on the player
+        self.scroll_to_player(1.0)
+
     def on_draw(self):
+        # Use our scrolled camera
+        self.camera_sprites.use()
+
         # Select the channel 0 frame buffer to draw on
         self.channel0.use()
         self.channel0.clear()
@@ -108,9 +123,17 @@
         self.use()
         # Clear to background color
         self.clear()
+
+        # Calculate the light position. We have to subtract the camera position
+        # from the player position to get screen-relative coordinates.
+        p = (self.player_sprite.position[0] - self.camera_sprites.left,
+             self.player_sprite.position[1] - self.camera_sprites.bottom)
+
+        # Set the uniform data
+        self.shadertoy.program['lightPosition'] = p
+        self.shadertoy.program['lightSize'] = 300
+
         # Run the shader and render to the window
-        self.shadertoy.program['lightPosition'] = self.player_sprite.position
-        self.shadertoy.program['lightSize'] = 300
         self.shadertoy.render()
 
         # Draw the walls
@@ -118,6 +141,11 @@
 
         # Draw the player
         self.player_list.draw()
+
+        # Switch to the un-scrolled camera to draw the GUI with
+        self.camera_gui.use()
+        # Draw our sample GUI text
+        self.score_text.draw()
 
     def on_key_press(self, key, modifiers):
         """Called whenever a key is pressed. """
@@ -145,9 +173,25 @@
         # Call update on all sprites (The sprites don't do much in this
         # example though.)
         self.physics_engine.update()
+        # Scroll the screen to the player
+        self.scroll_to_player()
+
+    def scroll_to_player(self, speed=CAMERA_SPEED):
+        """
+        Scroll the window to the player.
+
+        if CAMERA_SPEED is 1, the camera will immediately move to the desired position.
+        Anything between 0 and 1 will have the camera move to the location with a smoother
+        pan.
+        """
+
+        position = (self.player_sprite.center_x, self.player_sprite.center_y)
+        self.camera_sprites.position = arcade.math.lerp_2d(self.camera_sprites.position, position, CAMERA_SPEED)
 
     def on_resize(self, width: int, height: int):
         super().on_resize(width, height)
+        self.camera_sprites.match_screen(and_projection=True)
+        self.camera_gui.match_screen(and_projection=True)
         self.shadertoy.resize((width, height))