diff --git a/doc/tutorials/raycasting/example.glsl b/doc/tutorials/raycasting/example.glsl index 342462fbff..1757853dd8 100644 --- a/doc/tutorials/raycasting/example.glsl +++ b/doc/tutorials/raycasting/example.glsl @@ -1,4 +1,4 @@ -#define N 500 +#define N 150 float terrain(vec2 p) { diff --git a/doc/tutorials/raycasting/example.py b/doc/tutorials/raycasting/example.py index f6d7f0ebe5..57c6a7c353 100644 --- a/doc/tutorials/raycasting/example.py +++ b/doc/tutorials/raycasting/example.py @@ -1,4 +1,5 @@ import random +from pathlib import Path import arcade from arcade.experimental import Shadertoy @@ -18,6 +19,7 @@ PLAYING_FIELD_WIDTH = 1600 PLAYING_FIELD_HEIGHT = 1600 +CURRENT_DIR = Path(__file__).resolve().parent class MyGame(arcade.Window): @@ -31,7 +33,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -61,18 +68,14 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add player to spritelist self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list) def load_shader(self): - file = open("example.glsl") + file = open(CURRENT_DIR / "example.glsl") shader_sourcecode = file.read() size = self.width, self.height @@ -88,19 +91,20 @@ def load_shader(self): self.shadertoy.channel_1 = self.channel1.color_attachments[0] def on_draw(self): + # Render in the walls for lighting self.channel0.use() - # clear_color = 0, 0, 0, 0 - # self.channel0.clear(color=clear_color) + self.channel0.clear() self.wall_list.draw() self.channel1.use() - # self.channel1.clear(color=clear_color) - self.channel1.clear(color=arcade.color.ARMY_GREEN) + self.channel1.clear(color=arcade.color.AMAZON) self.bomb_list.draw() self.use() - # self.camera_sprites.use() - self.shadertoy.render(mouse_position=(self.player_sprite.center_x, self.player_sprite.center_y)) + self.clear() + # Do the shadow casting + self.shadertoy.render(mouse_position=self.player_sprite.position) + # Draw the player and walls on top self.wall_list.draw() self.player_list.draw() @@ -131,6 +135,23 @@ def on_update(self, delta_time): # example though.) self.physics_engine.update() + def on_resize(self, width: int, height: int): + self.shadertoy.resize((width, height)) + # Resize the channels + size = width, height + self.channel0 = self.shadertoy.ctx.framebuffer( + color_attachments=[self.shadertoy.ctx.texture(size, components=4)] + ) + self.shadertoy.channel_0 = self.channel0.color_attachments[0] + + self.channel1 = self.shadertoy.ctx.framebuffer( + color_attachments=[self.shadertoy.ctx.texture(size, components=4)] + ) + self.shadertoy.channel_1 = self.channel1.color_attachments[0] + + + return super().on_resize(width, height) + if __name__ == "__main__": MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) diff --git a/doc/tutorials/raycasting/index.rst b/doc/tutorials/raycasting/index.rst index 55c8c68e76..9f742f7902 100644 --- a/doc/tutorials/raycasting/index.rst +++ b/doc/tutorials/raycasting/index.rst @@ -91,7 +91,7 @@ output. How does this shader work? For each point in our output, this ``mainImage`` function runs and calculates our output color. For a window that is 800x600 pixels, this function runs -480,000 times for each frame. Modern GPUs can have anywhere between 500-5,000 "cores" +480,000 times for each frame. Modern GPUs can have anywhere between 500-5,000 "threads" that can calculate these points in parallel for faster processing. Our current coordinate we are calculating we've brought in as a parameter called ``fragCoord``. @@ -333,7 +333,9 @@ With an N of 10: :width: 40% We can use an N of 500 to get a good quality shadow. We might need more if -your barriers are small, and the light range is large. +your barriers are small, and the light range is large. Note that the effect +gets increasingly expensive the higher N is. Some tweaks are likely needed +to find the lowest N that still looks good. .. image:: n500.png :width: 40% diff --git a/doc/tutorials/raycasting/start.py b/doc/tutorials/raycasting/start.py index 6822d38a71..2b2995a8ed 100644 --- a/doc/tutorials/raycasting/start.py +++ b/doc/tutorials/raycasting/start.py @@ -23,7 +23,12 @@ def __init__(self, width, height, title): super().__init__(width, height, title, resizable=True) # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -33,7 +38,7 @@ def __init__(self, width, height, title): self.background_color = arcade.color.ARMY_GREEN def generate_sprites(self): - # -- Set up several columns of walls + # -- Set up several columns of walls (that will cast shadows) for x in range(0, PLAYING_FIELD_WIDTH, 128): for y in range(0, PLAYING_FIELD_HEIGHT, int(128 * SPRITE_SCALING)): # Randomly skip a box so the player can find a way through @@ -54,11 +59,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add player to spritelist self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls diff --git a/doc/tutorials/raycasting/step_01.py b/doc/tutorials/raycasting/step_01.py index 730b595a06..3be5c6f8cb 100644 --- a/doc/tutorials/raycasting/step_01.py +++ b/doc/tutorials/raycasting/step_01.py @@ -31,7 +31,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -82,11 +87,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add player sprite to sprite list self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls diff --git a/doc/tutorials/raycasting/step_03.py b/doc/tutorials/raycasting/step_03.py index 57ac7a2768..f0658d76ca 100644 --- a/doc/tutorials/raycasting/step_03.py +++ b/doc/tutorials/raycasting/step_03.py @@ -31,7 +31,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -82,11 +87,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add player sprite to sprite list self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls @@ -100,7 +101,7 @@ def on_draw(self): self.wall_list.draw() self.channel1.use() - self.channel1.clear() + self.channel1.clear(color=arcade.color.AMAZON) # Draw the bombs self.bomb_list.draw() diff --git a/doc/tutorials/raycasting/step_04.py b/doc/tutorials/raycasting/step_04.py index af6308934e..9a82398bc1 100644 --- a/doc/tutorials/raycasting/step_04.py +++ b/doc/tutorials/raycasting/step_04.py @@ -31,7 +31,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -100,7 +105,7 @@ def on_draw(self): self.wall_list.draw() self.channel1.use() - self.channel1.clear() + self.channel1.clear(color=arcade.color.AMAZON) # Draw the bombs self.bomb_list.draw() diff --git a/doc/tutorials/raycasting/step_05.py b/doc/tutorials/raycasting/step_05.py index dadfe7728f..8b154fa257 100644 --- a/doc/tutorials/raycasting/step_05.py +++ b/doc/tutorials/raycasting/step_05.py @@ -31,7 +31,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -83,11 +88,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add the player to the player list self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls @@ -101,7 +102,7 @@ def on_draw(self): self.wall_list.draw() self.channel1.use() - self.channel1.clear() + self.channel1.clear(color=arcade.color.AMAZON) # Draw the bombs self.bomb_list.draw() diff --git a/doc/tutorials/raycasting/step_06.py b/doc/tutorials/raycasting/step_06.py index e21631442c..1271e9baf3 100644 --- a/doc/tutorials/raycasting/step_06.py +++ b/doc/tutorials/raycasting/step_06.py @@ -31,7 +31,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -82,11 +87,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add the player to the player list self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls @@ -100,7 +101,7 @@ def on_draw(self): self.wall_list.draw() self.channel1.use() - self.channel1.clear() + self.channel1.clear(color=arcade.color.AMAZON) # Draw the bombs self.bomb_list.draw() diff --git a/doc/tutorials/raycasting/step_07.py b/doc/tutorials/raycasting/step_07.py index d889ec9d9d..6f5a4fa373 100644 --- a/doc/tutorials/raycasting/step_07.py +++ b/doc/tutorials/raycasting/step_07.py @@ -31,7 +31,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -82,11 +87,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add the player to the player list self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls @@ -100,7 +101,7 @@ def on_draw(self): self.wall_list.draw() self.channel1.use() - self.channel1.clear() + self.channel1.clear(color=arcade.color.AMAZON) # Draw the bombs self.bomb_list.draw() diff --git a/doc/tutorials/raycasting/step_08.py b/doc/tutorials/raycasting/step_08.py index 69d0fd6294..64f1329cd4 100644 --- a/doc/tutorials/raycasting/step_08.py +++ b/doc/tutorials/raycasting/step_08.py @@ -32,7 +32,12 @@ def __init__(self, width, height, title): self.load_shader() # Sprites and sprite lists - self.player_sprite = None + self.player_sprite = arcade.Sprite( + ":resources:images/animated_characters/female_person/femalePerson_idle.png", + scale=SPRITE_SCALING, + center_x=256, + center_y=512, + ) self.wall_list = arcade.SpriteList() self.player_list = arcade.SpriteList() self.bomb_list = arcade.SpriteList() @@ -91,11 +96,7 @@ def generate_sprites(self): placed = True self.bomb_list.append(bomb) - # Create the player - self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png", - scale=SPRITE_SCALING) - self.player_sprite.center_x = 256 - self.player_sprite.center_y = 512 + # Add the player to the player list self.player_list.append(self.player_sprite) # Physics engine, so we don't run into walls @@ -115,7 +116,7 @@ def on_draw(self): self.wall_list.draw() self.channel1.use() - self.channel1.clear() + self.channel1.clear(color=arcade.color.AMAZON) # Draw the bombs self.bomb_list.draw() diff --git a/doc/tutorials/shader_toy_particles/shadertoy_demo_1.py b/doc/tutorials/shader_toy_particles/shadertoy_demo_1.py index 01208993fb..ad7001ef2d 100644 --- a/doc/tutorials/shader_toy_particles/shadertoy_demo_1.py +++ b/doc/tutorials/shader_toy_particles/shadertoy_demo_1.py @@ -16,6 +16,7 @@ def __init__(self): def on_draw(self): self.clear() + self.ctx.enable_only(self.ctx.BLEND) # Set uniform data to send to the GLSL shader self.shadertoy.program['pos'] = self.mouse["x"], self.mouse["y"] diff --git a/doc/tutorials/views/01_views.py b/doc/tutorials/views/01_views.py index 477d039ca6..a1b12cdddc 100644 --- a/doc/tutorials/views/01_views.py +++ b/doc/tutorials/views/01_views.py @@ -25,6 +25,7 @@ def __init__(self): # Set up the player info self.player_sprite = None + self.score_text = arcade.Text("Score: 0", 10, 10, arcade.color.WHITE, 14) self.score = 0 # Don't show the mouse cursor @@ -73,7 +74,8 @@ def on_draw(self): # Put the text on the screen. output = f"Score: {self.score}" - arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14) + self.score_text.text = output + self.score_text.draw() def on_mouse_motion(self, x, y, dx, dy): """ Handle Mouse Motion """ diff --git a/doc/tutorials/views/02_views.py b/doc/tutorials/views/02_views.py index 838347ce9b..b189a8f81c 100644 --- a/doc/tutorials/views/02_views.py +++ b/doc/tutorials/views/02_views.py @@ -25,6 +25,7 @@ def __init__(self): # Set up the player info self.player_sprite = None + self.score_text = arcade.Text("Score: 0", 10, 10, arcade.color.WHITE, 14) self.score = 0 # Don't show the mouse cursor @@ -73,7 +74,8 @@ def on_draw(self): # Put the text on the screen. output = f"Score: {self.score}" - arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14) + self.score_text.text = output + self.score_text.draw() def on_mouse_motion(self, x, y, dx, dy): """ Handle Mouse Motion """ diff --git a/doc/tutorials/views/03_views.py b/doc/tutorials/views/03_views.py index 86e5948c89..96573e2a49 100644 --- a/doc/tutorials/views/03_views.py +++ b/doc/tutorials/views/03_views.py @@ -51,6 +51,7 @@ def __init__(self): # Set up the player info self.player_sprite = None + self.score_text = arcade.Text("Score: 0", 10, 10, arcade.color.WHITE, 14) self.score = 0 # Don't show the mouse cursor @@ -99,7 +100,9 @@ def on_draw(self): # Put the text on the screen. output = f"Score: {self.score}" - arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14) + self.score_text.text = output + self.score_text.draw() + def on_mouse_motion(self, x, y, dx, dy): """ Handle Mouse Motion """ diff --git a/doc/tutorials/views/04_views.py b/doc/tutorials/views/04_views.py index ddb0f15c4d..bea6f38dab 100644 --- a/doc/tutorials/views/04_views.py +++ b/doc/tutorials/views/04_views.py @@ -21,14 +21,28 @@ def on_show_view(self): # Reset the viewport, necessary if we have a scrolling game and we need # to reset the viewport back to the start so we can see what we draw. self.window.default_camera.use() + self.title_text = arcade.Text( + "Instructions Screen", + x=self.window.width / 2, + y=self.window.height / 2, + color=arcade.color.WHITE, + font_size=50, + anchor_x="center", + ) + self.instruction_text = arcade.Text( + "Click to advance", + x=self.window.width / 2, + y=self.window.height / 2-75, + color=arcade.color.WHITE, + font_size=20, + anchor_x="center", + ) def on_draw(self): """ Draw this view """ self.clear() - arcade.draw_text("Instructions Screen", self.window.width / 2, self.window.height / 2, - arcade.color.WHITE, font_size=50, anchor_x="center") - arcade.draw_text("Click to advance", self.window.width / 2, self.window.height / 2-75, - arcade.color.WHITE, font_size=20, anchor_x="center") + self.title_text.draw() + self.instruction_text.draw() def on_mouse_press(self, _x, _y, _button, _modifiers): """ If the user presses the mouse button, start the game. """ @@ -52,8 +66,10 @@ def __init__(self): def on_draw(self): """ Draw this view """ self.clear() - self.texture.draw_sized(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, - SCREEN_WIDTH, SCREEN_HEIGHT) + arcade.draw_texture_rect( + self.texture, + rect=arcade.LBWH(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), + ) def on_mouse_press(self, _x, _y, _button, _modifiers): """ If the user presses the mouse button, re-start the game. """ @@ -76,6 +92,7 @@ def __init__(self): # Set up the player info self.player_sprite = None + self.score_text = arcade.Text("Score: 0", 10, 10, arcade.color.WHITE, 14) self.score = 0 # Don't show the mouse cursor @@ -124,7 +141,8 @@ def on_draw(self): # Put the text on the screen. output = f"Score: {self.score}" - arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14) + self.score_text.text = output + self.score_text.draw() def on_mouse_motion(self, x, y, dx, dy): """ Handle Mouse Motion """