def on_draw(self): """ Render the screen. """ # This command has to happen before we start drawing arcade.start_render() print() tests = [ ['identity', Matrix3x3(), (14, 14, 0)], ['rotate(30)', Matrix3x3().rotate(30), (227, 86, 0)], ['scale(0.8, 0.5)', Matrix3x3().scale(0.8, 0.5), (241, 155, 0)], ['translate(0.3, 0.1)', Matrix3x3().translate(0.3, 0.1), (192, 243, 0)], ['rotate(10).\nscale(0.33, 0.33)', Matrix3x3().rotate(10).scale(0.7, 0.7), (222, 252, 116)], ['scale(-1, 1)', Matrix3x3().scale(-1, 1), (241, 14, 0)], ['shear(0.3, 0.1)', Matrix3x3().shear(0.3, 0.1), (48, 25, 0)], [f'rotate({int(self.t) % 360})', Matrix3x3().rotate(self.t), (14, 14, 0)], ] for i, test_data in enumerate(tests): x = 80 + 180 * (i % 4) y = 420 - (i // 4) * 320 text, texture, desired_color = test_data arcade.draw_text(text, x, y - 20 - text.count('\n') * 10, arcade.color.WHITE, 10) self.xy_square.draw_transformed(x, y, 100, 100, 0, 255, texture) test_x = x + 5 test_y = y + 5 actual_color = arcade.get_pixel(test_x, test_y) assert actual_color[0] == desired_color[0] assert actual_color[1] == desired_color[1] assert actual_color[2] == desired_color[2]
def on_draw(self): arcade.start_render() for z in [300, 200]: opacity = 100 scale = 150 / z translate = scale / 500 self.background.draw_transformed( 0, 0, WIDTH, HEIGHT, 0, opacity, Matrix3x3().scale(scale, scale).translate(-self.camera_x * translate, 0)) if self.window.game_over: arcade.draw_text("Game Over", WIDTH/2, HEIGHT/2, arcade.color.WHITE, font_size=50, anchor_x="center") arcade.draw_text(f"High Score: {self.window.high_score}", WIDTH/2-40, HEIGHT-30, arcade.color.WHITE, 14) else: arcade.draw_text("Zen Tetris", WIDTH/2, HEIGHT/2, arcade.color.WHITE, font_size=50, anchor_x="center") arcade.draw_text("Push O (One player) or T (Two players) to play", WIDTH/2, HEIGHT/2 - 72, arcade.color.WHITE, font_size=16, anchor_x="center")
def on_draw(self): draw_time = timeit.default_timer() arcade.start_render() # Draw background texture self.update_counter += 1 if self.window.game_mode == 0: ratio = 60 # rotation speed slow else: ratio = 5 # rotation speed a little faster if self.update_counter % 10 == 0: self.angle += 0.1 self.background.draw_transformed( 0, 0, WIDTH, HEIGHT, 0, 255, Matrix3x3().rotate(self.angle)) # Display sprites for player in self.players: player.player_list.draw() player.wall_list.draw() player.block_list.draw() # Display scores arcade.draw_text(f"High Score: {self.window.high_score}", WIDTH/2-60, HEIGHT-30, arcade.color.WHITE, 14) if self.window.game_mode == 0: for player in self.players: arcade.draw_text(f"Score: {player.score}", 10, HEIGHT-30, arcade.color.WHITE, 14) arcade.draw_text(f"Level: {player.level}", WIDTH-70, HEIGHT-30, arcade.color.WHITE, 14) else: for player in self.players: arcade.draw_text(f"Level: {player.level}", player.left_edge+50, HEIGHT-30, arcade.color.WHITE, 14) arcade.draw_text(f"Score: {player.score}", player.left_edge+50, HEIGHT-50, arcade.color.WHITE, 14) # Display game over for player in self.players: if player.game_over: arcade.draw_text(f"Game Over", player.left_edge+25, HEIGHT/2+20, arcade.color.WHITE, 24) arcade.draw_text(f"ESC to quit", player.left_edge+50, HEIGHT/2-20, arcade.color.WHITE, 16) # Display performance info (debug mode) if self.window.debug is True: now_time = timeit.default_timer() loop_time = now_time - self.loop_time self.loop_time = now_time draw_time = now_time - draw_time arcade.draw_text( f"Loop time: {loop_time * 1000:.3f} " + f"(Update time: {self.update_time * 1000:.3f}, " + f"Draw time: {draw_time * 1000:.3f})", 60, 0, arcade.color.WHITE, 14)
def on_draw(self): """ Render the screen. """ # This command has to happen before we start drawing arcade.start_render() print() tests = [ ['identity', Matrix3x3(), (14, 14, 0)], ['rotate(30)', Matrix3x3().rotate(30), (230, 87, 0)], ['scale(0.8, 0.5)', Matrix3x3().scale(0.8, 0.5), (242, 158, 0)], [ 'translate(0.3, 0.1)', Matrix3x3().translate(0.3, 0.1), (194, 245, 0) ], [ 'rotate(10).\nscale(0.33, 0.33)', Matrix3x3().rotate(10).scale(0.7, 0.7), (252, 255, 244) ], ['scale(-1, 1)', Matrix3x3().scale(-1, 1), (243, 14, 0)], ['shear(0.3, 0.1)', Matrix3x3().shear(0.3, 0.1), (48, 26, 0)], [ f'rotate({int(self.t) % 360})', Matrix3x3().rotate(self.t), (14, 14, 0) ], ] for i, test_data in enumerate(tests): x = 80 + 180 * (i % 4) y = 420 - (i // 4) * 320 text, texture, desired_color = test_data arcade.draw_text(text, x, y - 20 - text.count('\n') * 10, arcade.color.WHITE, 10) self.xy_square.draw_transformed(x, y, 100, 100, 0, 255, texture) test_x = x + 5 test_y = y + 5 actual_color = arcade.get_pixel(test_x, test_y) # Mac, with its retina scaling, doesn't match other platforms. import sys if sys.platform != "darwin": # print(actual_color, desired_color) assert actual_color[0] == desired_color[0] assert actual_color[1] == desired_color[1] assert actual_color[2] == desired_color[2]
def on_draw(self): """ Render the screen. """ # This command has to happen before we start drawing arcade.start_render() for z in [300, 200, 150, 100]: opacity = int(math.exp(-z / 1000) * 255) angle = z scale = 150 / z translate = scale / 500 self.stars.draw_transformed( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, opacity, Matrix3x3().rotate(angle).scale(scale * ASPECT, scale).translate( -self.camera_x * translate, 0)) self.ship.draw() for i, pair in enumerate([ ['identity', Matrix3x3()], ['rotate(30)', Matrix3x3().rotate(30)], ['scale(0.8, 0.5)', Matrix3x3().scale(0.8, 0.5)], ['translate(0.3, 0.1)', Matrix3x3().translate(0.3, 0.1)], [ 'rotate(10).\nscale(0.33, 0.33)', Matrix3x3().rotate(10).scale(0.7, 0.7) ], ['scale(-1, 1)', Matrix3x3().scale(-1, 1)], ['shear(0.3, 0.1)', Matrix3x3().shear(0.3, 0.1)], [f'rotate({int(self.t) % 360})', Matrix3x3().rotate(self.t)], ]): x = 80 + 180 * (i % 4) y = 420 - (i // 4) * 320 arcade.draw_text(pair[0], x, y - 20 - pair[0].count('\n') * 10, arcade.color.WHITE, 10) self.xy_square.draw_transformed(x, y, 100, 100, 0, 255, pair[1])
def __init__(self, filename: str = None, scale: float = 1, image_x: float = 0, image_y: float = 0, image_width: float = 0, image_height: float = 0, center_x: float = 0, center_y: float = 0, repeat_count_x: int = 1, repeat_count_y: int = 1): """ Create a new sprite. Args: filename (str): Filename of an image that represents the sprite. scale (float): Scale the image up or down. Scale of 1.0 is none. image_x (float): X offset to sprite within sprite sheet. image_y (float): Y offset to sprite within sprite sheet. image_width (float): Width of the sprite image_height (float): Height of the sprite center_x (float): Location of the sprite center_y (float): Location of the sprite """ if image_width < 0: raise ValueError("Width of image can't be less than zero.") if image_height < 0: raise ValueError( "Height entered is less than zero. Height must be a positive float." ) if image_width == 0 and image_height != 0: raise ValueError("Width can't be zero.") if image_height == 0 and image_width != 0: raise ValueError("Height can't be zero.") self.sprite_lists: List[Any] = [] self._texture: Optional[Texture] if filename is not None: try: self._texture = load_texture(filename, image_x, image_y, image_width, image_height) except Exception as e: print(f"Unable to load {filename} {e}") self._texture = None if self._texture: self.textures = [self._texture] # Ignore the texture's scale and use ours self._width = self._texture.width * scale self._height = self._texture.height * scale else: self.textures = [] self._width = 0 self._height = 0 else: self.textures = [] self._texture = None self._width = 0 self._height = 0 self.cur_texture_index = 0 self._scale = scale self._position = (center_x, center_y) self._angle = 0.0 self.velocity = [0.0, 0.0] self.change_angle = 0.0 self.boundary_left = None self.boundary_right = None self.boundary_top = None self.boundary_bottom = None self.properties: Dict[str, Any] = {} self._alpha = 255 self._collision_radius: Optional[float] = None self._color: RGB = (255, 255, 255) self._points: Optional[List[List[float]]] = None if self._texture: self._points = self._texture.hit_box_points self._point_list_cache: Optional[List[List[float]]] = None self.force = [0, 0] self.guid: Optional[str] = None self.repeat_count_x = repeat_count_x self.repeat_count_y = repeat_count_y self._texture_transform = Matrix3x3() # Used if someone insists on doing a sprite.draw() self._sprite_list = None
def draw(self, **kwargs): """ Draw this list of sprites. :param filter: Optional parameter to set OpenGL filter, such as `gl.GL_NEAREST` to avoid smoothing. :param blend_function: Optional parameter to set the OpenGL blend function used for drawing the sprite list, such as 'arcade.Window.ctx.BLEND_ADDITIVE' or 'arcade.Window.ctx.BLEND_DEFAULT' """ if len(self.sprite_list) == 0: return # What percent of this sprite list moved? Used in guessing spatial hashing self._percent_sprites_moved = self._sprites_moved / len(self.sprite_list) * 100 self._sprites_moved = 0 # Make sure window context exists if self.ctx is None: self.ctx = get_window().ctx # Used in drawing optimization via OpenGL self.program = self.ctx.sprite_list_program_cull if self._vao1 is None: self._calculate_sprite_buffer() self.ctx.enable(self.ctx.BLEND) if "blend_function" in kwargs: self.ctx.blend_func = kwargs["blend_function"] else: self.ctx.blend_func = self.ctx.BLEND_DEFAULT self._texture.use(0) if "filter" in kwargs: self._texture.filter = self.ctx.NEAREST, self.ctx.NEAREST self.program['Texture'] = self.texture_id texture_transform = None if len(self.sprite_list) > 0: # always wrap texture transformations with translations # so that rotate and resize operations act on the texture # center by default texture_transform = Matrix3x3().translate(-0.5, -0.5).multiply(self.sprite_list[0].texture_transform.v).multiply(Matrix3x3().translate(0.5, 0.5).v) else: texture_transform = Matrix3x3() self.program['TextureTransform'] = texture_transform.v if not self.is_static: if self._sprite_pos_changed: self._sprite_pos_buf.orphan() self._sprite_pos_buf.write(self._sprite_pos_data) self._sprite_pos_changed = False if self._sprite_size_changed: self._sprite_size_buf.orphan() self._sprite_size_buf.write(self._sprite_size_data) self._sprite_size_changed = False if self._sprite_angle_changed: self._sprite_angle_buf.orphan() self._sprite_angle_buf.write(self._sprite_angle_data) self._sprite_angle_changed = False if self._sprite_color_changed: self._sprite_color_buf.orphan() self._sprite_color_buf.write(self._sprite_color_data) self._sprite_color_changed = False if self._sprite_sub_tex_changed: self._sprite_sub_tex_buf.orphan() self._sprite_sub_tex_buf.write(self._sprite_sub_tex_data) self._sprite_sub_tex_changed = False self._vao1.render(self.program, mode=self.ctx.POINTS, vertices=len(self.sprite_list))
def __init__(self, filename: str = None, scale: float = 1, image_x: float = 0, image_y: float = 0, image_width: float = 0, image_height: float = 0, center_x: float = 0, center_y: float = 0, repeat_count_x: int = 1, repeat_count_y: int = 1, flipped_horizontally: bool = False, flipped_vertically: bool = False, flipped_diagonally: bool = False, mirrored: bool = None, hit_box_algorithm: str = "Simple", hit_box_detail: float = 4.5): """ Create a new sprite. :param str filename: Filename of an image that represents the sprite. :param float scale: Scale the image up or down. Scale of 1.0 is none. :param float image_x: X offset to sprite within sprite sheet. :param float image_y: Y offset to sprite within sprite sheet. :param float image_width: Width of the sprite :param float image_height: Height of the sprite :param float center_x: Location of the sprite :param float center_y: Location of the sprite :param bool flipped_horizontally: Mirror the sprite image. Flip left/right across vertical axis. :param bool flipped_vertically: Flip the image up/down across the horizontal axis. :param bool flipped_diagonally: Transpose the image, flip it across the diagonal. :param mirrored: Deprecated. :param str hit_box_algorithm: One of 'None', 'Simple' or 'Detailed'. \ Defaults to 'Simple'. Use 'Simple' for the :data:`PhysicsEngineSimple`, \ :data:`PhysicsEnginePlatformer` \ and 'Detailed' for the :data:`PymunkPhysicsEngine`. .. figure:: images/hit_box_algorithm_none.png :width: 40% hit_box_algorithm = "None" .. figure:: images/hit_box_algorithm_simple.png :width: 55% hit_box_algorithm = "Simple" .. figure:: images/hit_box_algorithm_detailed.png :width: 75% hit_box_algorithm = "Detailed" :param float hit_box_detail: Float, defaults to 4.5. Used with 'Detailed' to hit box """ if image_width < 0: raise ValueError("Width of image can't be less than zero.") if image_height < 0: raise ValueError( "Height entered is less than zero. Height must be a positive float." ) if image_width == 0 and image_height != 0: raise ValueError("Width can't be zero.") if image_height == 0 and image_width != 0: raise ValueError("Height can't be zero.") if mirrored is not None: from warnings import warn warn( "In Sprite, the 'mirrored' parameter is deprecated. Use 'flipped_horizontally' instead.", DeprecationWarning) flipped_horizontally = mirrored if hit_box_algorithm != "Simple" and \ hit_box_algorithm != "Detailed" and \ hit_box_algorithm != "None": raise ValueError( "hit_box_algorithm must be 'Simple', 'Detailed', or 'None'.") self._hit_box_algorithm = hit_box_algorithm self._hit_box_detail = hit_box_detail self.sprite_lists: List[Any] = [] self.physics_engines: List[Any] = [] self._texture: Optional[Texture] self._points: Optional[PointList] = None self._hit_box_shape: Optional[ShapeElementList] = None if filename is not None: try: self._texture = load_texture( filename, image_x, image_y, image_width, image_height, flipped_horizontally=flipped_horizontally, flipped_vertically=flipped_vertically, flipped_diagonally=flipped_diagonally, hit_box_algorithm=hit_box_algorithm, hit_box_detail=hit_box_detail) except Exception as e: print(f"Unable to load {filename} {e}") self._texture = None if self._texture: self.textures = [self._texture] # Ignore the texture's scale and use ours self._width = self._texture.width * scale self._height = self._texture.height * scale else: self.textures = [] self._width = 0 self._height = 0 else: self.textures = [] self._texture = None self._width = 0 self._height = 0 self.cur_texture_index = 0 self._scale = scale self._position = (center_x, center_y) self._angle = 0.0 self.velocity = [0.0, 0.0] self.change_angle = 0.0 self.boundary_left = None self.boundary_right = None self.boundary_top = None self.boundary_bottom = None self.properties: Dict[str, Any] = {} self._alpha = 255 self._collision_radius: Optional[float] = None self._color: RGB = (255, 255, 255) if self._texture and not self._points: self._points = self._texture.hit_box_points self._point_list_cache: Optional[PointList] = None self.force = [0, 0] self.guid: Optional[str] = None self.repeat_count_x = repeat_count_x self.repeat_count_y = repeat_count_y self._texture_transform = Matrix3x3() # Used if someone insists on doing a sprite.draw() self._sprite_list = None self.pymunk = PyMunk()
def draw(self, **kwargs): """ Draw this list of sprites. :param filter: Optional parameter to set OpenGL filter, such as `gl.GL_NEAREST` to avoid smoothing. """ if self.program is None: # Used in drawing optimization via OpenGL self.program = shader.program(vertex_shader=_VERTEX_SHADER, fragment_shader=_FRAGMENT_SHADER) if len(self.sprite_list) == 0: return if self._vao1 is None: self._calculate_sprite_buffer() self._texture.use(0) gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if "filter" in kwargs: gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, kwargs["filter"]) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, kwargs["filter"]) # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST) # gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST) with self._vao1: self.program['Texture'] = self.texture_id self.program['Projection'] = get_projection().flatten() texture_transform = None if len(self.sprite_list) > 0: # always wrap texture transformations with translations # so that rotate and resize operations act on the texture # center by default texture_transform = Matrix3x3().translate(-0.5, -0.5).multiply( self.sprite_list[0].texture_transform.v).multiply( Matrix3x3().translate(0.5, 0.5).v) if texture_transform == None: texture_transform = Matrix3x3() self.program['TextureTransform'] = texture_transform.v if not self.is_static: if self._sprite_pos_changed: self._sprite_pos_buf.orphan() self._sprite_pos_buf.write(self._sprite_pos_data.tobytes()) self._sprite_pos_changed = False if self._sprite_size_changed: self._sprite_size_buf.orphan() self._sprite_size_buf.write( self._sprite_size_data.tobytes()) self._sprite_size_changed = False if self._sprite_angle_changed: self._sprite_angle_buf.orphan() self._sprite_angle_buf.write( self._sprite_angle_data.tobytes()) self._sprite_angle_changed = False if self._sprite_color_changed: self._sprite_color_buf.orphan() self._sprite_color_buf.write( self._sprite_color_data.tobytes()) self._sprite_color_changed = False if self._sprite_sub_tex_changed: self._sprite_sub_tex_buf.orphan() self._sprite_sub_tex_buf.write( self._sprite_sub_tex_data.tobytes()) self._sprite_sub_tex_changed = False self._vao1.render(gl.GL_TRIANGLE_STRIP, instances=len(self.sprite_list))