Skip to content

Commit

Permalink
Allow screen.fill() to fill with a gradient
Browse files Browse the repository at this point in the history
  • Loading branch information
lordmauve committed May 6, 2019
1 parent 97c989d commit daa4805
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 13 deletions.
5 changes: 4 additions & 1 deletion doc/builtins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ draw images to the screen ("blit" them).

Reset the screen to black.

.. method:: fill((red, green, blue))
.. method:: fill((red, green, blue), [gcolor=(r, g, b)])

Fill the screen with a solid color.

If ``gcolor`` is given then fill with a gradient, from ``color`` at the
top of the screen to ``gcolor`` at the bottom.

.. method:: blit(image, (left, top))

Draw the image to the screen at the given position.
Expand Down
6 changes: 6 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

1.3 - unreleased
----------------

* New: screen.fill() now takes ``gcolor``, creating a vertical-linear gradient


1.2 - 2018-02-24
----------------

Expand Down
4 changes: 0 additions & 4 deletions doc/ptext.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,6 @@ text's color will be ``color`` at the top and ``gcolor`` at the bottom.
Positioning of the gradient stops and orientation of the gradient are
hard coded and cannot be specified.

Requries ``pygame.surfarray`` module, which uses numpy or Numeric
library.

Alpha transparency
''''''''''''''''''
Expand All @@ -235,8 +233,6 @@ Keyword argument:
In order to maximize reuse of cached transparent surfaces, the value of
``alpha`` is rounded.

Requires ``pygame.surfarray`` module, which uses numpy or Numeric
library.

Anchored positioning
''''''''''''''''''''
Expand Down
17 changes: 15 additions & 2 deletions pgzero/screen.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import numpy as np
import pygame
import pygame.draw

from . import ptext
from .rect import RECT_CLASSES, ZRect
from . import loaders
Expand Down Expand Up @@ -80,9 +82,20 @@ def clear(self):
"""Clear the screen to black."""
self.fill((0, 0, 0))

def fill(self, color):
def fill(self, color, gcolor=None):
"""Fill the screen with a colour."""
self.surface.fill(make_color(color))
if gcolor:
start = make_color(color)
stop = make_color(gcolor)
pixs = pygame.surfarray.pixels3d(self.surface)
h = self.height

gradient = np.dstack(
[np.linspace(a, b, h) for a, b in zip(start, stop)][:3]
)
pixs[...] = gradient
else:
self.surface.fill(make_color(color))

def blit(self, image, pos):
"""Draw a sprite onto the screen.
Expand Down
Binary file added test/images/expected_gradient.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 27 additions & 6 deletions test/test_screen.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import unittest
import tempfile
from pathlib import Path

import numpy as np
import pygame
import pygame.image
import pygame.surfarray

from pgzero.screen import Screen
from pgzero.loaders import set_root, images
Expand All @@ -23,13 +28,21 @@ def setUp(self):
self.screen = Screen(self.surf)
self.screen.clear()

def assertImagesAlmostEqual(self, a, b):
"""Check that 2 images are equal besides 1 bit alpha blending rounding errors"""
zdata = zip(pygame.image.tostring(a, 'RGB'), pygame.image.tostring(b, 'RGB'))
def assertImagesAlmostEqual(self, computed, expected):
"""Check that 2 images are approximately equal."""
comp_surf = pygame.surfarray.array3d(computed)
exp_surf = pygame.surfarray.array3d(expected)

if np.allclose(comp_surf, exp_surf, atol=1):
return

for z in zdata:
if abs(z[0] - z[1]) > 1:
raise AssertionError("Images differ")
tmpdir = Path(tempfile.mkdtemp())
pygame.image.save(computed, str(tmpdir / 'computed.png'))
pygame.image.save(expected, str(tmpdir / 'expected.png'))

raise AssertionError(
"Images differ; saved comparison images to {}".format(tmpdir)
)

def test_blit_surf(self):
"""We can blit a surface to the screen."""
Expand All @@ -51,6 +64,14 @@ def test_bounds(self):
self.assertGreater(b.width, 0)
self.assertGreater(b.height, 0)

def test_fill_gradient(self):
"""We can fill the screen with a gradient."""
self.screen.fill('black', gcolor='blue')
self.assertImagesAlmostEqual(
self.screen.surface,
images.expected_gradient
)


if __name__ == '__main__':
unittest.main()

0 comments on commit daa4805

Please sign in to comment.