1

Here are my observations of the problem:

  • The asteroids game uses a drawn texture sprite for the glow ball weapons. This is done in the GlowBall class. Weapon 7 uses a drawn image
  • The drawn sprite is with bullet_list.draw() but the shader: for bullet in bullet_list: bullet.draw().
  • The sprite is being drawn correctly but the shader is not.
  • The shader seems to move with the ship but faster. almost like it is being drawn to a larger area.

What I tried:

  • Using the player position minus the camera position which is what I
    did to make a drawn image stay on the player - to draw a turret on
    the top of the ship.
  • Tried to make a second version of Shadertoy.py so that I can use the screen_rectangle instead of quad_2d_fs.
  • If I use the pymunk physics engine it can accelerate the shader but causes it to be drawn in the way described above. How can I use the camera with the shader class along with the pymunk physics engine to create plasma bullets and explosions?

These classes come from the arcade example: https://github.com/pythonarcade/asteroids I am using a margin scrolling from example: https://api.arcade.academy/en/latest/examples/sprite_move_scrolling_box.html#sprite-move-scrolling-box '''

class GlowBullet(arcade.Sprite):
    def __init__(self, image_file=None, scale=1.0, shadertoy=None, player_no=1):
        super().__init__(image_file, scale)
        self.type = None
        self.shadertoy = shadertoy
        self.player_no = player_no

    def draw(self):
        pass

class GlowBall(GlowBullet):
    def __init__(self, shadertoy, glowcolor, radius):
        super().__init__(shadertoy=shadertoy)
        self.type = None
        self.shadertoy = shadertoy
        self.glowcolor = glowcolor
        self.texture = arcade.make_circle_texture(radius * 2, glowcolor)
        self._points = self.texture.hit_box_points

    def draw(self):
        self.shadertoy.program['pos'] = self.position
        self.shadertoy.program['color'] = arcade.get_three_float_color(self.glowcolor)
        self.shadertoy.render()

''' ... In the GameView class:

'''

class GameView(arcade.View):
    def __init__(self):
        super().__init__()
        self.glowball_shadertoy = Shadertoy.create_from_file(self.window.get_size(), GLOW_BALL_IMAGE)

def player_blaster(self,x,y,blaster_filename):
    self.click_x = self.world_mouse_x 
    self.click_y = self.world_mouse_y
    r,diff_angle = self.cart_to_polar([self.player.center_x,self.player.center_y],[self.world_mouse_x,self.world_mouse_y])
    bullet_sprite = GlowBall(glowcolor=bullet_color,
                             radius=5,
                             shadertoy=self.glowball_shadertoy)
    glow_bullet = GlowBullet(glowcolor=(1000, 1000, 1000),radius=7,shadertoy=self.glowball_shadertoy)
    player_size = max(self.player.width, self.player.height) / 2
    bullet_size = max(bullet.width, bullet.height) / 2
    glow_bullet_size = bullet_size
    radius_start = player_size + bullet_size
    glow_radius_start = 0      
    glow_bullet_x,glow_bullet_y = self.polar_to_cart(glow_radius_start,diff_angle,[self.player.center_x-self.camera_gui.position[0],self.player.center_y-self.camera_gui.position[1]])  
    glow_bullet_x,glow_bullet_y = self.polar_to_cart(glow_radius_start,diff_angle,[self.player.center_x,self.player.center_y])
    glow_bullet.center_x=glow_bullet_x
    glow_bullet.center_y=glow_bullet_y
    glow_bullet.angle=math.degrees(diff_angle) - 90
    bullet.damage = self.player.damage_attack
    self.bullet_list.append(bullet)
    self.glow_bullet_list.append(glow_bullet)
    angle = math.pi/2
    bullet_force_x = PLASMA_FORCE_1 * math.cos(angle)
    bullet_force_y = PLASMA_FORCE_1 * math.sin(angle)       
    self.physics_engine.add_sprite(glow_bullet,
                            mass=0.01,
                            damping=1,
                            friction=0.01,
                            moment_of_intertia=100000,
                            elasticity=0.9)
    self.physics_engine.apply_force(glow_bullet, (bullet_force_x,bullet_force_y)) 

    def on_draw(self):
    """ Draw everything """
    self.clear()
    # This controlls the GLSL shader
    for bullet in self.glow_bullet_list:
        bullet.draw()
    # This draws the sprite
    self.glow_bullet_list.draw()

'''

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • I know Pymunk but Ive never used arcade so cant easily help. However, from the looks of it I think you can try their discord, at https://discord.gg/ZjGDqMp This is supposed to be the most active place to get help. – viblo Jul 17 '22 at 18:44
  • Yeah I ended up finding the discord. I have been chatting with some guys there about it. The problem seemed to be resolved in the example given with the ray-casting example. In the discord he shows the same behavior before it was fixed. I haven't been successful yet though. – Casey MrChiller Jul 19 '22 at 18:24

1 Answers1

0

Did you run it in a HiDPI environment?

If so, you should use shader class with proper framebuffer size. Not window.get_size()

Like,

shader = ShaderToy(window.get_framebuffer_size())

render_scale = window.get_framebuffer_size()[0] / window.size[0]

shader.program['pos'] = position * render_scale