def draw_horizontal_stripes(surface, x1, x2, y1, y2): # Fill the entire surface with a black color. In contrast to # colorpalettes.py we use a Color() value here, just to demonstrate that # it really works. video.fill(surface, BLACK) # Create a 2D view that allows us to directly access each individual pixel # of the surface. The PixelView class is quite slow, since it uses an non- # optimised read-write access to each individual pixel and offset. It works # on every platform, though. pixelview = video.PixelView(surface) # Loop over the area bounds, considering each fourth line and every column # on the 2D view. The PixelView uses a y-x alignment to access pixels. # This mkeans that the first accessible dimension of the PixelView denotes # the horizontal lines of an image, and the second the vertical lines. for y in range(y1, y2, 4): for x in range(x1, x2): # Change the color of each individual pixel. We can assign any # color-like value here, since the assignment method of the # PixelView will implicitly check and convert the value to a # matching color for its target surface. pixelview[y][x] = WHITE # Explicitly delete the PixelView. Some surface types need to be locked # in order to access their pixels directly. The PixelView will do that # implicitly at creation time. Once we are done with all necessary # operations, we need to unlock the surface, which will be done # automatically at the time the PixelView is garbage-collected. del pixelview
def draw_vertical_stripes(surface, x1, x2, y1, y2): video.fill(surface, BLACK) pixelview = video.PixelView(surface) for x in range(x1, x2, 4): for y in range(y1, y2): pixelview[y][x] = WHITE del pixelview
def draw_palette(surface, palette): # Fill the entire surface with a black color. This is done by simply # passing a 0 value to the fill argument. We could also create a # Color(0, 0, 0) instance here, but this would be the same. video.fill(surface, 0) # Calculate the average width (roughly cut) to be used for each palette # value. When running the example, you will notice a black gap on the # right for some palettes. This s caused by the implicit cut behaviour # of the // operator. Since we can only operate pixel-wise, there are # no fractions to be used. width, height = surface.size rw = width // len(palette) # Create the area to be filled with the palette values. we always start # at the top-left corner, use the calculated width and the entire height # of the window surface. As you will see below, we then only advance # horizontically by the calculated width to draw stripes. # Play around with different height values and start offsets to see what # happens rect = [0, 0, rw, height] # Loop over all colors and fill a portion of the surface with them. As # above, we use fill() to fill the surface with the palette color, but now # we provide an area (the third argument) to avoid filling the whole # surface. Instead, the provided area makes sure, that we only fill a # certain part. for color in palette: video.fill(surface, color, rect) rect[0] += rw
def test_fill(self): # TODO: add exceptions and more bounding tests. rects = ((0, 0, 3, 2), (2, 3, 4, 2), (5, -1, 2, 2), (1, 7, 4, 8) ) factory = video.SpriteFactory(video.SOFTWARE) sprite = factory.create_sprite(size=(10, 10), bpp=32) view = video.PixelView(sprite) for rect in rects: video.fill(sprite, 0) colorval = video.prepare_color(0xAABBCCDD, sprite) video.fill(sprite, 0xAABBCCDD, rect) for y, row in enumerate(view): for x, col in enumerate(row): if y >= rect[1] and y < (rect[1] + rect[3]): if x >= rect[0] and x < (rect[0] + rect[2]): self.assertEqual(col, colorval, "color mismatch at (x, y)") else: self.assertEqual(col, 0, "color mismatch at (x, y)") else: self.assertEqual(col, 0, "color mismatch at (x, y)")
def test_pixels3d(self): factory = video.SpriteFactory(video.SOFTWARE) sprite = factory.create_sprite(size=(5, 10), bpp=32, masks=(0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF)) video.fill(sprite, 0xAABBCCDD, (1, 2, 3, 4)) nparray = video.pixels3d(sprite)
def create_scene4(manager, uifactory): print("Creating scene 4") scene = ExampleScene("Scene 4") button_back = uifactory.create_button(size=(100, 50)) button_back.position = 200, 200 video.fill(button_back, 0xFFFFFFFF) button_back.click += lambda btn, ev: manager.pop() scene.components.append(button_back) return scene
def start_mainmenu(scene): scene.components = [] button_scene1 = scene.uifactory.create_button(size=(100, 50)) button_scene1.position = 100, 100 video.fill(button_scene1, 0xFFFFFFFF) button_scene1.click += lambda btn, ev: \ switch_to(scene.manager, create_scene1(scene.manager, scene.uifactory)) scene.components.append(button_scene1) button_scene2 = scene.uifactory.create_button(size=(100, 50)) button_scene2.position = 100, 160 video.fill(button_scene2, 0xFFFFFFFF) button_scene2.click += lambda btn, ev: \ switch_to(scene.manager, create_scene2(scene.manager, scene.uifactory)) scene.components.append(button_scene2) button_scene3 = scene.uifactory.create_button(size=(100, 50)) button_scene3.position = 100, 220 video.fill(button_scene3, 0xFFFFFFFF) button_scene3.click += lambda btn, ev: \ switch_to(scene.manager, create_scene3(scene.manager, scene.uifactory)) scene.components.append(button_scene3) button_scene4 = scene.uifactory.create_button(size=(100, 50)) button_scene4.position = 100, 280 video.fill(button_scene4, 0xFFFFFFFF) button_scene4.click += lambda btn, ev: \ switch_to(scene.manager, create_scene4(scene.manager, scene.uifactory)) scene.components.append(button_scene4)
def run(): # You know those from the helloworld.py example. # Initialize the video subsystem, create a window and make it visible. video.init() window = video.Window("Pixel Access", size=(800, 600)) window.show() spritefactory = video.SpriteFactory(video.SOFTWARE) uifactory = video.UIFactory(spritefactory) # Since all gui elements are sprites, we can use the SpriteRenderer # class, we learned about in helloworld.py, to draw them on the # Window. renderer = spritefactory.create_sprite_renderer(window) # Create a new UIProcessor, which will handle the user input events # and pass them on to the relevant user interface elements. uiprocessor = video.UIProcessor() # Create a scene manager - this one will take care of managing the # different scenes. scenemanager = SceneManager() # Every time we switch to a different scene, reset the video window, so # we do not have any artifacts left on the screen. scenemanager.switched += lambda mgr: video.fill(renderer.surface, 0x0) # Create the initial scene. mainmenu = Scene("Main Menu") # We need the uifactory to create buttons for the different scenes. mainmenu.uifactory = uifactory # Bind the start and end events of the scene. started() will be invoked # every time the SceneManager starts the scene. ended() will be invoked, # if the scene ends, e.g. if a new scene is pushed to the manager. mainmenu.started += start_mainmenu mainmenu.ended += end_scene # Push the initial scene to the SceneManager. scenemanager.push(mainmenu) running = True while running: # Process the SceneManager. This takes care of updating the scene # states by checking, if a new scene has to be displayed or not. scenemanager.update() # The main event loop; we already learned about that in other examples. # Check for the events and pass them around. for event in video.get_events(): if event.type == sdlevents.SDL_QUIT: running = False break # Pass the SDL2 events to the UIProcessor, which takes care of # the user interface logic. uiprocessor.dispatch(scenemanager.current.components, event) # Render all components on all scenes. renderer.render(scenemanager.current.components) window.refresh() video.quit() return 0
def test_SoftwareSpriteRenderer_process(self): sf1= create_rgb_surface(5, 10, 32) sp1 = video.SoftwareSprite(sf1, True) sp1.depth = 0 video.fill(sp1, 0xFF0000) sf2 = create_rgb_surface(5, 10, 32) sp2 = video.SoftwareSprite(sf2, True) sp2.depth = 99 video.fill(sp2, 0x00FF00) sprites = [sp1, sp2] window = video.Window("Test", size=(20, 20)) renderer = video.SoftwareSpriteRenderer(window) renderer.process("fakeworld", sprites) view = video.PixelView(renderer.surface) # Only sp2 wins, since its depth is higher self.check_pixels(view, 20, 20, sp1, 0x00FF00, (0x0, )) self.check_pixels(view, 20, 20, sp2, 0x00FF00, (0x0, )) del view self.assertRaises(TypeError, renderer.process, None, None)
def test_SoftwareSpriteRenderer_render(self): sf1= create_rgb_surface(12, 7, 32) sp1 = video.SoftwareSprite(sf1, True) video.fill(sp1, 0xFF0000) sf2 = create_rgb_surface(3, 9, 32) sp2 = video.SoftwareSprite(sf2, True) video.fill(sp2, 0x00FF00) sprites = [sp1, sp2] window = video.Window("Test", size=(20, 20)) renderer = video.SoftwareSpriteRenderer(window) self.assertIsInstance(renderer, video.SpriteRenderer) self.assertRaises(AttributeError, renderer.render, None, None, None) self.assertRaises(AttributeError, renderer.render, [None, None], None, None) for x, y in ((0, 0), (3, 3), (20, 20), (1, 12), (5, 6)): sp1.position = x, y renderer.render(sp1) view = video.PixelView(renderer.surface) self.check_pixels(view, 20, 20, sp1, 0xFF0000, (0x0, )) del view video.fill(renderer.surface, 0x0) sp1.position = 0, 0 sp2.position = 14, 1 renderer.render(sprites) view = video.PixelView(renderer.surface) self.check_pixels(view, 20, 20, sp1, 0xFF0000, (0x0, 0x00FF00)) self.check_pixels(view, 20, 20, sp2, 0x00FF00, (0x0, 0xFF0000)) del view video.fill(renderer.surface, 0x0) renderer.render(sprites, 1, 2) view = video.PixelView(renderer.surface) self.check_pixels(view, 20, 20, sp1, 0xFF0000, (0x0, 0x00FF00), 1, 2) self.check_pixels(view, 20, 20, sp2, 0x00FF00, (0x0, 0xFF0000), 1, 2) del view
def render(self, components): video.fill(self.surface, BLACK) super(SoftwareRenderer, self).render(components)