ggame module
ggame
The simple cross-platform sprite and game platform for Brython Server (Pygame, Tkinter to follow?).
Ggame stands for a couple of things: "good game" (of course!) and also "git game" or "github game" because it is designed to operate with Brython Server in concert with Github as a backend file store.
Ggame is not intended to be a full-featured gaming API, with every bell and whistle. Ggame is designed primarily as a tool for teaching computer programming, recognizing that the ability to create engaging and interactive games is a powerful motivator for many progamming students. Accordingly, any functional or performance enhancements that can be reasonably implemented by the user are left as an exercise.
Functionality Goals
The ggame library is intended to be trivially easy to use. For example:
from ggame import App, ImageAsset, Sprite
# Create a displayed object at 100,100 using an image asset
Sprite(ImageAsset("ggame/bunny.png"), (100,100))
# Create the app, with a 500x500 pixel stage
app = App(500,500)  
# Run the app
app.run()
Extensions
The ggame library has been extended with ggmath for geometry
exploration in a manner reminiscent of Geogebra, and ggrocket
for tools and classes to use with rocket and orbital simulations.
Overview
There are three major components to the ggame system: Assets, Sprites and the App.
Assets
Asset objects (i.e. ImageAsset, etc.) typically represent separate files that
are provided by the "art department". These might be background images, user interface
images, or images that represent objects in the game. In addition, SoundAsset 
is used to represent sound files (.wav or .mp3 format) that can be played in the 
game.
Ggame also extends the asset concept to include graphics that are generated dynamically at run-time, such as geometrical objects, e.g. rectangles, lines, etc.
Sprites
All of the visual aspects of the game are represented by instances of Sprite or
subclasses of it. 
App
Every ggame application must create a single instance of the App class (or 
a sub-class of it). Creating an instance of the App class will initiate 
creation of a pop-up window on your browser. Executing the app's run method will
begin the process of refreshing the visual assets on the screen. 
Events
No game is complete without a player and players produce events. Your code handles user
input by registering to receive keyboard and mouse events using listenKeyEvent and
listenMouseEvent methods.
Execution Environment
Ggame is designed to be executed in a web browser using Brython, Pixi.js and Buzz. The easiest way to do this is by executing from runpython, with source code residing on github.
To use Ggame in your own application, you may create a folder called
ggame in your project. Within ggame, copy the ggame.py, sysdeps.py and 
__init__.py files from the ggame project.
When using ggame from within runpython, the Github
ggame repository is automatically placed on the import search path.
Geometry
When referring to screen coordinates, note that the x-axis of the computer screen is horizontal with the zero position on the left hand side of the screen. The y-axis is vertical with the zero position at the top of the screen.
Increasing positive y-coordinates correspond to the downward direction on the computer screen. Note that this is different from the way you may have learned about x and y coordinates in math class!
"""
# ggame
The simple cross-platform sprite and game platform for Brython Server (Pygame, Tkinter to follow?).
Ggame stands for a couple of things: "good game" (of course!) and also "git game" or "github game" 
because it is designed to operate with [Brython Server](http://runpython.com) in concert with
Github as a backend file store.
Ggame is **not** intended to be a full-featured gaming API, with every bell and whistle. Ggame is
designed primarily as a tool for teaching computer programming, recognizing that the ability
to create engaging and interactive games is a powerful motivator for many progamming students.
Accordingly, any functional or performance enhancements that *can* be reasonably implemented 
by the user are left as an exercise. 
## Functionality Goals
The ggame library is intended to be trivially easy to use. For example:
    from ggame import App, ImageAsset, Sprite
  
    # Create a displayed object at 100,100 using an image asset
    Sprite(ImageAsset("ggame/bunny.png"), (100,100))
    # Create the app, with a 500x500 pixel stage
    app = App(500,500)  
    # Run the app
    app.run()
    
## Extensions
The `ggame` library has been extended with [ggmath](/ggame/ggmath.html) for geometry
exploration in a manner reminiscent of Geogebra, and [ggrocket](/ggame/ggrocket.html)
for tools and classes to use with rocket and orbital simulations.
## Overview
There are three major components to the `ggame` system: Assets, Sprites and the App.
### Assets
Asset objects (i.e. `ggame.ImageAsset`, etc.) typically represent separate files that
are provided by the "art department". These might be background images, user interface
images, or images that represent objects in the game. In addition, `ggame.SoundAsset` 
is used to represent sound files (`.wav` or `.mp3` format) that can be played in the 
game.
Ggame also extends the asset concept to include graphics that are generated dynamically
at run-time, such as geometrical objects, e.g. rectangles, lines, etc.
### Sprites
All of the visual aspects of the game are represented by instances of `ggame.Sprite` or
subclasses of it. 
### App
Every ggame application must create a single instance of the `ggame.App` class (or 
a sub-class of it). Creating an instance of the `ggame.App` class will initiate 
creation of a pop-up window on your browser. Executing the app's `run` method will
begin the process of refreshing the visual assets on the screen. 
### Events
No game is complete without a player and players produce events. Your code handles user
input by registering to receive keyboard and mouse events using `ggame.App.listenKeyEvent` and
`ggame.App.listenMouseEvent` methods.
## Execution Environment
Ggame is designed to be executed in a web browser using [Brython](http://brython.info/),
[Pixi.js](http://www.pixijs.com/) and [Buzz](http://buzz.jaysalvat.com/). The easiest
way to do this is by executing from [runpython](http://runpython.com), with source
code residing on [github](http://github.com).
To use Ggame in your own application, you may create a folder called
`ggame` in your project. Within `ggame`, copy the `ggame.py`, `sysdeps.py` and 
`__init__.py` files from the [ggame project](https://github.com/BrythonServer/ggame).
When using `ggame` from within [runpython](http://runpython.com), the Github
`ggame` repository is automatically placed on the import search path.
## Geometry
When referring to screen coordinates, note that the x-axis of the computer screen
is *horizontal* with the zero position on the left hand side of the screen. The 
y-axis is *vertical* with the zero position at the **top** of the screen.
Increasing positive y-coordinates correspond to the downward direction on the 
computer screen. Note that this is **different** from the way you may have learned
about x and y coordinates in math class!
"""
import math
try:
    from ggame.sysdeps import *
except:
    from sysdeps import *
class Frame(object):
    """
    Frame is a utility class for expressing the idea of a rectangular region.
    """
    
    def __init__(self, x, y, w, h):
        """
        Initialization for the `ggame.Frame` objects.
        `x` and `y` are coordinates of the upper left hand corner of the frame.
 
        `w` and `h` are the width and height of the frame rectangle.
        """
        self.GFX = GFX_Rectangle(x,y,w,h)
        """
        `GFX` is a reference to the underlying object provided by the system.
        """
        self.x = x
        """
        X-coordinate of the upper left hand corner of this `ggame.Frame`.
        """
        self.y = y
        """
        Y-coordinate of the upper left hand corner of this `ggame.Frame`.
        """
        self.w = w
        """
        Width of the `ggame.Frame`.
        """
        self.h = h
        """
        Height of the `ggame.Frame`.
        """
    
    @property
    def x(self):
        return self.GFX.x
    
    @x.setter
    def x(self, value):
        self.GFX.x = value
        
    @property
    def y(self):
        return self.GFX.y
    
    @y.setter
    def y(self, value):
        self.GFX.y = value
    
    @property
    def w(self):
        return self.GFX.width
    
    @w.setter
    def w(self, value):
        self.GFX.width = value
        
    @property
    def h(self):
        return self.GFX.height
        
    @h.setter
    def h(self, value):
        self.GFX.height = value
    
    @property
    def center(self):
        """
        `center` property computes a coordinate pair (tuple) for the 
        center of the frame.
        The `center` property, when set, redefines the `x` and `y` properties
        of the frame in order to make the center agree with the coordinates
        (tuple) assigned to it.
        """
        return (self.x + self.w//2, self.y + self.h//2)
    
    @center.setter
    def center(self, value):
        c = self.center
        self.x += value[0] - c[0]
        self.y += value[1] - c[1]
class _Asset(object):
    """
    Base class for all game asset objects.
    
    The `ggame.Asset` class is set up to understand the concept
    of multiple instances of an asset. This is currently only used for image-based
    assets.
    """
    def __init__(self):
        self.GFXlist = [None,]
        """A list of the underlying system objects used to represent this asset."""
    @property
    def GFX(self):
        """
        `GFX` property represents the underlying system object used to represent
        this asset. If this asset is composed of multiple assets, then the **first**
        asset is referenced by `GFX`.
        """
        return self.GFXlist[0]
        
    @GFX.setter
    def GFX(self, value):
        self.GFXlist[0] = value
        
    def __len__(self):
        return len(self.GFXlist)
        
    def __getitem__(self, key):
        return self.GFXlist[key]
        
    def __setitem__(self, key, value):
        self.GFXlist[key] = value
        
    def __iter__(self):
        class Iter():
            def __init__(self, image):
                self.obj = image
                self.n = len(image.GFXlist)
                self.i = 0
                
            def __iter__(self):
                return self
                
            def __next__(self):
                if self.i ==self.n:
                    raise StopIteration
                self.i += 1
                return self.obj.GFXlist[self.i]
        return Iter(self)
    def destroy(self):
        if hasattr(self, 'GFX'):
            try:
                for gfx in self.GFXlist:
                    try:
                        gfx.destroy(True)
                    except:
                        pass
            except:
                pass
        
        
class ImageAsset(_Asset):
    """
    The `ImageAsset` class connects ggame to a specific image **file**.
    """
    def __init__(self, url, frame=None, qty=1, direction='horizontal', margin=0):
        """
        All `ggame.ImageAsset` instances must specify a file name or url with
        the `url` parameter.
        If the desired sprite image exists in only a smaller sub-section of the 
        original image, then the are can be specified by providing the
        `frame` parameter, which must be a valid `ggame.Frame` object.
        If image file actually is a *collection* of images, such as a so-called
        *sprite sheet*, then the `ImageAsset` class supports defining a list
        of images, provided they exist in the original image as a **row**
        of evenly spaced images or a **column** of images. To specify this,
        provide the `qty` (quantity) of images in the row or column, the
        `direction` of the list ('horizontal' or 'vertical' are supported),
        and an optional `margin`, if there is a gap between successive 
        images. When used in this way, the `frame` parameter must define the
        area of the **first** image in the collection; all subsequent images
        in the list are assumed to be the same size.
        """
        super().__init__()
        self.url = url
        """
        A string that represents the path or url of the original file.
        """
        del self.GFXlist[0]
        self.width = self.height = 0
        self.append(url, frame, qty, direction, margin)
    def _subframe(self, texture, frame):
        return GFX_Texture(texture, frame.GFX)
        
    def append(self, url, frame=None, qty=1, direction='horizontal', margin=0):
        """
        Append a texture asset from a new image file (or url). This method
        allows you to build a collection of images into an asset (such as you
        might need for an animated sprite), but without using a single 
        sprite sheet image.
        The parameters for the `append` method are identical to those 
        supplied to the `ggame.ImageAsset` initialization method. 
        This method allows you to build up an asset that consists of 
        multiple rows or columns of images in a sprite sheet or sheets.
        """
        GFX = GFX_Texture_fromImage(url, False)
        dx = 0
        dy = 0
        for i in range(qty):
            if not frame is None:
                self.width = frame.w
                self.height = frame.h
                if direction == 'horizontal':
                    dx = frame.w + margin
                elif direction == 'vertical':
                    dy = frame.h + margin
                f = Frame(frame.x + dx * i, frame.y + dy * i, frame.w, frame.h)
                GFX = self._subframe(GFX, f)
            else:
                self.width = GFX.width
                self.height = GFX.height
            self.GFXlist.append(GFX)
class Color(object):
    """
    The `ggame.Color` class is used to represent colors and/or colors with
    transparency.
    """
    def __init__(self, color, alpha):
        """
        A `ggame.Color` instance must specify both a `color` as an integer
        in the conventional format (usually as a hexadecimal literal, e.g.
        0xffbb33 that represents the three color components, red, green 
        and blue), and a transparency value, or `alpha` as a floating
        point number in the range of 0.0 to 1.0 where 0.0 represents 
        completely transparent and 1.0 represents completely solid.
        Example: `red = Color(0xff0000, 1.0)`
        """
        self.color = color
        self.alpha = alpha
        
    def __eq__(self, other):
        return type(self) is type(other) and self.color == other.color and self.alpha == other.alpha
        
black = Color(0, 1.0)
"""
Default black color
"""
white = Color(0xffffff, 1.0)
"""
Default white color
"""
class LineStyle(object):
    """
    The `ggame.LineStyle` class is used to represent line style when
    drawing geometrical objects such as rectangles, ellipses, etc.
    """
    
    def __init__(self, width, color):
        """
        When creating a `ggame.LineStyle` instances you must specify 
        the `width` of the line in pixels and the `color` as a valid
        `ggame.Color` instance.
        Example: `line = LineStyle(3, Color(0x00ff00, 1.0))` will define
        a 3 pixel wide green line.
        """
        self.width = width
        self.color = color
    def __eq__(self, other):
        return type(self) is type(other) and self.width == other.width and self.color == other.color
blackline = LineStyle(1, black)
"""
Default thin black line
"""
whiteline = LineStyle(1, white)
"""
Default thin white line
"""
class _GraphicsAsset(_Asset):
    
    def __init__(self):
        super().__init__()
        GFX_Graphics.clear()
        
class _CurveAsset(_GraphicsAsset):
    def __init__(self, line):
        super().__init__()
        GFX_Graphics.lineStyle(line.width, line.color.color, line.color.alpha)
class _ShapeAsset(_CurveAsset):
    def __init__(self, line, fill):
        super().__init__(line)
        GFX_Graphics.beginFill(fill.color, fill.alpha)
    
class RectangleAsset(_ShapeAsset):
    """
    The `ggame.RectangleAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file.
    """
    def __init__(self, width, height, line=blackline, fill=black):
        """
        Creation of a `ggame.RectangleAsset` requires specification of the 
        rectangle `width` and `height` in pixels, the `line` (as a proper
        `ggame.LineStyle` instance) and fill properties (as a `ggame.Color`
        instance).
        """
        super().__init__(line, fill)
        self.width = width
        self.height = height
        self.GFX = GFX_Graphics.drawRect(0, 0, self.width, self.height).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
        
class CircleAsset(_ShapeAsset):
    """
    The `ggame.CircleAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file.
    """    
    def __init__(self, radius, line=blackline, fill=black):
        """
        Creation of a `ggame.CircleAsset` requires specification of the circle
        `radius` in pixels, the `line` (as a proper `ggame.LineStyle` instance)
        and fill properties (as a `ggame.Color` instance).
        """
        super().__init__(line, fill)
        self.radius = radius
        self.GFX = GFX_Graphics.drawCircle(0, 0, self.radius).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
        
class EllipseAsset(_ShapeAsset):
    """
    The `ggame.EllipseAsset` is a "virtual" asset that is created on the 
    fly without requiring creation of an image file.
    """
    def __init__(self, halfw, halfh, line=blackline, fill=black):
        """
        Creation of a `ggame.EllipseAsset` requires specification of the ellipse
        `halfw`, or semi-axis length in the horizontal direction (half of the
        ellipse width) and the `halfh`, or semi-axis length in the vertical direction.
        `line` (as `ggame.LineStyle` instance) and `fill` (as `ggame.Color` instance)
        must also be provided.
        """
        super().__init__(line, fill)
        self.halfw = halfw
        self.halfh = halfh
        self.GFX = GFX_Graphics.drawEllipse(0, 0, self.halfw, self.halfh).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
        
class PolygonAsset(_ShapeAsset):
    """
    The `ggame.PolygonAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file.
    """
    def __init__(self, path, line=blackline, fill=black):
        """
        Creation of a `ggame.PolygonAsset` requires specification of a 
        `path` consisting of a list of coordinate tuples. `line` and 
        `fill` arguments (instances of `ggame.LineStyle` and `ggame.Color`,
        respectively) must also be supplied. The final coordinate in the 
        list must be the same as the first.
        Example: `poly = PolygonAsset([(0,0), (50,50), (50,100), (0,0)], linesty, fcolor)`
        """
        super().__init__(line, fill)
        self.path = path
        jpath = []
        for point in self.path:
            jpath.extend(point)
        self.GFX = GFX_Graphics.drawPolygon(jpath).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
    
class LineAsset(_CurveAsset):
    """
    The `ggame.LineAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file. A `LineAsset` instance
    represents a single line segment.
    """
    def __init__(self, x, y, line=blackline):
        """
        Creation of a `ggame.LineAsset` requires specification of an `x` and
        `y` coordinate for the endpoint of the line. The starting point of the
        line is implied as coordinates (0,0). Note that when this asset is 
        used in a `ggame.Sprite` class, the sprite's `x` and `y` coordinates
        will control the location of the line segment on the screen.
        As the `ggame.LineAsset` does not cover a region, only a `ggame.LineStyle` 
        argument must be supplied (`line`).
        """
        super().__init__(line)
        self.deltaX = x
        """This attribute represents the `x` parameter supplied during instantiation."""
        self.deltaY = y
        """This attribute represents the `y` parameter supplied during instantiation."""
        GFX_Graphics.moveTo(0, 0)
        self.GFX = GFX_Graphics.lineTo(self.deltaX, self.deltaY).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
class TextAsset(_GraphicsAsset):
    """
    The `ggame.TextAsset` is a "virtual" asset that is created on the fly
    without requiring creation of an image file. A `TextAsset` instance
    represents a block of text, together with its styling (font, color, etc.).
    """
 
    def __init__(self, text, **kwargs):
        """
        The `ggame.TextAsset` must be created with a string as the `text` parameter.
        
        The remaining optional arguments must be supplied as keyword parameters. These
        parameters are described under the class attributes, below:
        """
        super().__init__()
        self.text = text
        self.style = kwargs.get('style', '20px Arial')
        """A string that specifies style, size and typeface (e.g. `'italic 20pt Helvetica'` or `'20px Arial'`)"""
        width = kwargs.get('width', 100)
        """Width of the text block on the screen, in pixels."""
        self.fill = kwargs.get('fill', Color(0, 1))
        """A valid `ggame.Color` instance that specifies the color and transparency of the text."""
        self.align = kwargs.get('align', 'left')
        """The alignment style of the text. One of: `'left'`, `'center'`, or `'right'`."""
        self.GFX = GFX_Text(self.text, 
            {'font': self.style,
                'fill' : self.fill.color,
                'align' : self.align,
                'wordWrap' : True,
                'wordWrapWidth' : width,
                })
        """The `GFX` property represents the underlying system object."""
        self.GFX.alpha = self.fill.alpha
        self.GFX.visible = False
        
    def _clone(self):
        return type(self)(self.text,
            style = self.style,
            width = self.width,
            fill = self.fill,
            align = self.align)
    
    @property
    def width(self):
        return self.GFX.width
        
    @property
    def height(self):
        return self.GFX.height
class Sprite(object):
    """
    The `ggame.Sprite` class combines the idea of a visual/graphical asset, a
    position on the screen, and *behavior*. Although the `ggame.Sprite` can be
    used as-is, it is generally subclassed to give it the desired behavior.
    When subclassing the `ggame.Sprite` class, you may customize the initialization
    code to use a specific asset. A 'step' or 'poll' method may be added
    for handling per-frame actions (e.g. checking for collisions). Step or poll
    functions are not automatically called by the `ggame.App` class, but you
    may subclass the `ggame.App` class in order to do this.
    Furthermore, you may wish to define event callback methods in your customized
    sprite class. With customized creation, event handling, and periodic processing
    you can achieve fully autonomous behavior for your class. 
    """
 
    _rectCollision = "rect"
    _circCollision = "circ"
    
    def __init__(self, asset, pos=(0,0), edgedef=None):
        """
        The `ggame.Sprite` must be created with an existing graphical `asset`.
        
        An optional `pos` or position may be provided, which specifies the 
        starting (x,y) coordinates of the sprite on the screen. By default,
        the position of a sprite defines the location of its upper-left hand
        corner. This behavior can be modified by customizing the `center` of
        the sprite.
        
        An optional `edgedef` or edge definition may be provided, which
        specifies an asset that will be used to define the boundaries of
        the sprite for the purpose of collision detection. If no `edgedef` 
        asset is given, the Sprite asset is used, which will be a rectangular
        asset in the case of an image texture. This option is typically used
        to define a visible image outline for a texture-based sprite that has
        a transparent texture image background.
        
        Example: player = Sprite(ImageAsset("player.png", (100,100), CircleAsset(50))
        
        This creates a sprite using the `player.png` image, positioned with its
        upper left corner at coordinates (100,100) and with a 50 pixel radius 
        circular collision border. 
        """
        self._index = 0
        if type(asset) == ImageAsset:
            self.asset = asset
            try:
                #self.GFX = GFX_Sprite()
                self.GFX = GFX_Sprite(asset.GFX) # GFX is PIXI Sprite
            except:
                self.GFX = None
        elif type(asset) in [RectangleAsset, 
            CircleAsset, 
            EllipseAsset, 
            PolygonAsset,
            LineAsset,
            ]:
            self.asset = asset
            self.GFX = GFX_Sprite(asset.GFX.generateTexture())
            #self.GFX = asset.GFX.clone() # GFX is PIXI Graphics (from Sprite)
            #self.GFX.visible = True
        elif type(asset) in [TextAsset]:
            self.asset = asset._clone()
            self.GFX = self.asset.GFX # GFX is PIXI Text (from Sprite)
            self.GFX.visible = True
        if not edgedef:
            self.edgedef = asset
        else:
            self.edgedef = edgedef
        self.xmin = self.xmax = self.ymin = self.ymax = 0
        self.position = pos
        """Tuple indicates the position of the sprite on the screen."""
        self._extentsdirty = True
        """Boolean indicates if extents must be calculated before collision test"""
        self._createBaseVertices()
        self._setExtents()
        """Initialize the extents (xmax, xmin, etc.) for collision detection"""
        App._add(self)
        
    def _createBaseVertices(self):
        """
        Create sprite-relative list of vertex coordinates for boundary
        """
        self._basevertices = []
        assettype = type(self.edgedef)
        if assettype in [RectangleAsset, ImageAsset, TextAsset]:
            self._basevertices = [(0,0), 
                (0,self.edgedef.height), 
                (self.edgedef.width,self.edgedef.height),
                (self.edgedef.width,0)]
        elif assettype is PolygonAsset:
            self._basevertices = self.edgedef.path[:-1]
        elif assettype is LineAsset:
            self._basevertices = [(0,0), 
                (self.edgedef.deltaX, self.edgedef.deltaY)]
        elif assettype is EllipseAsset:
            w = self.edgedef.halfw * 2
            h = self.edgedef.halfh * 2
            self._basevertices = [(0,0), (0,h), (w,h), (w,0)]
    def _xformVertices(self):
        """
        Create window-relative list of vertex coordinates for boundary
        """
        # find center as sprite-relative points (note sprite may be scaled)
        x = self.width * self.fxcenter / self.scale
        y = self.height * self.fycenter / self.scale
        if self.scale != 1.0:
            sc = self.scale
            # center-relative, scaled coordinates
            crsc = [((xp-x)*sc,(yp-y)*sc) for xp,yp in self._basevertices]
        else:
            crsc = [(xp-x,yp-y) for xp,yp in self._basevertices]
            
        # absolute, rotated coordinates
        c = math.cos(self.rotation)
        s = math.sin(self.rotation)
        self._absolutevertices = [(self.x + x*c + y*s, self.y + -x*s + y*c) 
                                    for x,y in crsc]
    def _setExtents(self):
        """
        update min/max x and y based on position, center, width, height
        """
        if self._extentsdirty:
            if type(self.asset) is CircleAsset:
                th = math.atan2(
                    self.fycenter - 0.5, 0.5 - self.fxcenter) + self.rotation
                D = self.width
                L = math.sqrt(math.pow(self.fxcenter - 0.5, 2) + 
                    math.pow(self.fycenter - 0.5, 2)) * D
                self.xmin = self.x + int(L*math.cos(th)) - D//2
                self.ymin = self.y - int(L*math.sin(th)) - D//2
                self.xmax = self.xmin + D
                self.ymax = self.ymin + D
            else:
                # Build vertex list
                self._xformVertices()
                x, y = zip(*self._absolutevertices)
                self.xmin = min(x)
                self.xmax = max(x)
                self.ymin = min(y)
                self.ymax = max(y)
            self._extentsdirty = False
    def firstImage(self):
        """
        Select and display the *first* image used by this sprite.
        """
        self.GFX.texture = self.asset[0]
    
    def lastImage(self):
        """
        Select and display the *last* image used by this sprite.
        """
        self.GFX.texture = self.asset[-1]
    
    def nextImage(self, wrap = False):
        """
        Select and display the *next* image used by this sprite.
        If the current image is already the *last* image, then
        the image is not advanced.
        If the optional `wrap` parameter is set to `True`, then calling
        `ggame.Sprite.nextImage` on the last image will cause the *first*
        image to be loaded.
        """
        self._index += 1
        if self._index >= len(self.asset):
            if wrap:
                self._index = 0
            else:
                self._index = len(self.asset)-1
        self.GFX.texture = self.asset[self._index]
    
    def prevImage(self, wrap = False):
        """
        Select and display the *previous* image used by this sprite.
        If the current image is already the *first* image, then
        the image is not changed.
        If the optional `wrap` parameter is set to `True`, then calling
        `ggame.Sprite.prevImage` on the first image will cause the *last*
        image to be loaded.
        """
        self._index -= 1
        if self._index < 0:
            if wrap:
                self._index = len(self.asset)-1
            else:
                self._index = 0
        self.GFX.texture = self.asset[self._index]
    
    def setImage(self, index=0):
        """
        Select the image to display by giving its `index`, where an index
        of zero represents the *first* image in the asset.
        This is equivalent to setting the `ggame.Sprite.index` property
        directly.
        """
        self.index = index
    def rectangularCollisionModel(self):
        """
        Obsolete. No op.
        """
        pass
    
    def circularCollisionModel(self):
        """
        Obsolete. No op.
        """
        pass
    
    
    @property
    def index(self):
        """This is an integer index in to the list of images available for this sprite."""
        return self._index
        
    @index.setter
    def index(self, value):
        self._index = value
        try:
            self.GFX.texture = self.asset[self._index]
        except:
            self._index = 0
            self.GFX.texture = self.asset[self._index]
    @property
    def width(self):
        """
        This is an integer representing the display width of the sprite.
        Assigning a value to the width will scale the image horizontally.
        """
        return self.GFX.width
        
    @width.setter
    def width(self, value):
        self.GFX.width = value
        self._extentsdirty = True
    
    @property
    def height(self):
        """
        This is an integer representing the display height of the sprite.
        Assigning a value to the height will scale the image vertically.
        """
        return self.GFX.height
    
    @height.setter
    def height(self, value):
        self.GFX.height = value
        self._extentsdirty = True
        
    @property
    def x(self):
        """
        This represents the x-coordinate of the sprite on the screen. Assigning
        a value to this attribute will move the sprite horizontally.
        """
        return self.GFX.position.x
        
    @x.setter
    def x(self, value):
        deltax = value - self.GFX.position.x
        self.xmax += deltax
        self.xmin += deltax
        """Adjust extents directly with low overhead"""
        self.GFX.position.x = value
    @property
    def y(self):
        """
        This represents the y-coordinate of the sprite on the screen. Assigning
        a value to this attribute will move the sprite vertically.
        """
        return self.GFX.position.y
        
    @y.setter
    def y(self, value):
        deltay = value - self.GFX.position.y
        self.ymax += deltay
        self.ymin += deltay
        """Adjust extents directly with low overhead"""
        self.GFX.position.y = value
    @property
    def position(self):
        """
        This represents the (x,y) coordinates of the sprite on the screen. Assigning
        a value to this attribute will move the sprite to the new coordinates.
        """
        return (self.GFX.position.x, self.GFX.position.y)
        
    @position.setter
    def position(self, value):
        self.x, self.y = value
    @property
    def fxcenter(self):
        """
        This represents the horizontal position of the sprite "center", as a floating
        point number between 0.0 and 1.0. A value of 0.0 means that the x-coordinate
        of the sprite refers to its left hand edge. A value of 1.0 refers to its 
        right hand edge. Any value in between may be specified. Values may be assigned
        to this attribute. 
        """
        try:
            return self.GFX.anchor.x
            self._extentsdirty = True
        except:
            return 0.0
        
    @fxcenter.setter
    def fxcenter(self, value):
        """
        Float: 0-1
        """
        try:
            self.GFX.anchor.x = value
            self._extentsdirty = True
        except:
            pass
        
    @property
    def fycenter(self):
        """
        This represents the vertical position of the sprite "center", as a floating
        point number between 0.0 and 1.0. A value of 0.0 means that the x-coordinate
        of the sprite refers to its top edge. A value of 1.0 refers to its 
        bottom edge. Any value in between may be specified. Values may be assigned
        to this attribute. 
        """
        try:
            return self.GFX.anchor.y
        except:
            return 0.0
        
    @fycenter.setter
    def fycenter(self, value):
        """
        Float: 0-1
        """
        try:
            self.GFX.anchor.y = value
            self._extentsdirty = True
        except:
            pass
    
    @property
    def center(self):
        """
        This attribute represents the horizontal and vertical position of the 
        sprite "center" as a tuple of floating point numbers. See the 
        descriptions for `ggame.Sprite.fxcenter` and `ggame.Sprite.fycenter` for 
        more details.
        """
        try:
            return (self.GFX.anchor.x, self.GFX.anchor.y)
        except:
            return (0.0, 0.0)
        
    @center.setter
    def center(self, value):
        try:
            self.GFX.anchor.x = value[0]
            self.GFX.anchor.y = value[1]
            self._extentsdirty = True
        except:
            pass
    
    @property
    def visible(self):
        """
        This boolean attribute may be used to change the visibility of the sprite. Setting
        `ggame.Sprite.visible` to `False` will prevent the sprite from rendering on the 
        screen.
        """
        return self.GFX.visible
    
    @visible.setter
    def visible(self, value):
        self.GFX.visible = value
    @property
    def scale(self):
        """
        This attribute may be used to change the size of the sprite ('scale' it) on the 
        screen. Value may be a floating point number. A value of 1.0 means that the sprite
        image will keep its original size. A value of 2.0 would double it, etc.
        """
        try:
            return self.GFX.scale.x
        except AttributeError:
            return 1.0
        
    @scale.setter
    def scale(self, value):
        self.GFX.scale.x = value
        self.GFX.scale.y = value
        self._extentsdirty = True
    @property
    def rotation(self):
        """
        This attribute may be used to change the rotation of the sprite on the screen.
        Value may be a floating point number. A value of 0.0 means no rotation. A value 
        of 1.0 means  a rotation of 1 radian in a counter-clockwise direction. One radian
        is 180/pi or approximately 57.3 degrees.
        """
        try:
            return -self.GFX.rotation
        except AttributeError:
            return 0.0
        
    @rotation.setter
    def rotation(self, value):
        self.GFX.rotation = -value
        if value:
            self._extentsdirty = True
    @classmethod
    def collidingCircleWithPoly(cls, circ, poly):
        return True
    
    def collidingPolyWithPoly(self, obj):
        return True
    def collidingWith(self, obj):
        """
        Return a boolean True if this sprite is currently overlapping the sprite 
        referenced by `obj`. Returns False if checking for collision with 
        itself. Returns False if extents of object make it impossible for
        collision to occur. Returns True if sprite's `edgedef` parameter overlaps
        with other sprite's `edgedef` parameter, taking into consideration both
        sprites' center, rotation and scale settings.
        """
        if self is obj:
            return False
        else:
            self._setExtents()
            obj._setExtents()
            # Gross check for overlap will usually rule out a collision
            if (self.xmin > obj.xmax
                or self.xmax < obj.xmin
                or self.ymin > obj.ymax
                or self.ymax < obj.ymin):
                return False
            # Otherwise, perform a careful overlap determination
            elif type(self.asset) is CircleAsset:
                if type(obj.asset) is CircleAsset:
                    # two circles .. check distance between
                    sx = (self.xmin + self.xmax) / 2
                    sy = (self.ymin + self.ymax) / 2
                    ox = (obj.xmin + obj.xmax) / 2
                    oy = (obj.ymin + obj.ymax) / 2
                    d = math.sqrt((sx-ox)**2 + (sy-oy)**2)
                    return d <= self.width/2 + obj.width/2
                else:
                    return self.collidingCircleWithPoly(self, obj)
            else:
                if type(obj.asset) is CircleAsset:
                    return self.collidingCircleWithPoly(obj, self)
                else:
                    return self.collidingPolyWithPoly(obj)
                
                
    def collidingWithSprites(self, sclass = None):
        """
        Return a list of sprite objects identified by the `sclass` parameter
        that are currently colliding with (that is, with which the `ggame.Sprite.collidingWith`
        method returns True) this sprite. If `sclass` is set to `None` (default), then
        all other sprites are checked for collision, otherwise, only sprites whose
        class matches `sclass` are checked.
        """
        if sclass is None:
            slist = App.spritelist
        else:
            slist = App.getSpritesbyClass(sclass)
        return list(filter(self.collidingWith, slist))
    def destroy(self):
        """
        Call the `ggame.Sprite.destroy` method to prevent the sprite from being displayed,
        or checked in collision detection. If you only want to prevent a sprite from being
        displayed, set the `ggame.Sprite.visible` attribute to `False`.
        """
        App._remove(self)
        self.GFX.destroy()
class SoundAsset(object):
    """
    Class representing a single sound asset (sound file, such as .mp3 or .wav).
    """    
    def __init__(self, url):
        """
        Create a `ggame.SoundAsset` instance by passing in the URL or file name
        of the desired sound. Sound file formats may include `.wav` or `.mp3`, subject
        to browser compatibility. 
        """
        self.url = url
        """
        A string containing the url or name of the asset file.
        """
        
class Sound(object):
    """
    The `ggame.Sound` class represents a sound, with methods for controlling
    when and how the sound is played in the application.
    """
    def __init__(self, asset):
        """
        Pass a valid `ggame.SoundAsset` instance when creating a `ggame.Sound` object.
        """
        self.asset = asset
        """
        A reference to the `ggame.SoundAsset` instance.
        """
        self.SND = SND_Sound(self.asset.url)
        """
        A reference to the underlying sound object provided by the system.
        """
        self.SND.load()
        
    def play(self):
        """
        Play the sound once.
        """
        self.stop()
        self.SND.play()
    def loop(self):
        """
        Play the sound continuously, looping forever.
        """
        self.stop()
        self.SND.loop()
        self.SND.play()
        
    def stop(self):
        """
        Stop playing the sound.
        """
        self.SND.stop()
        
    @property
    def volume(self):
        """
        The `ggame.Sound.volume` property is a number ranging from 0-100, that 
        represents the volume or intensity of the sound when it is playing.
        """
        return self.SND.getVolume()
        
    @volume.setter
    def volume(self, value):
        self.SND.setVolume(value)
    
class _Event(object):
    def __init__(self, hwevent):
        self.hwevent = hwevent
        """The underlying system event object."""
        self.type = hwevent.type
        """String representing the type of received event."""
        self.consumed = False
        """
        Set the `consumed` member of the event to prevent the event
        from being received by any more handler methods.
        """
        
class MouseEvent(_Event):
    """
    The `ggame.MouseEvent` class encapsulates information regarding a user mouse
    action that is being reported by the system.
    """    
    mousemove = "mousemove"
    """Constant identifying a `mousemove` event."""
    mousedown = "mousedown"
    """Constant identifying a `mousedown` event."""
    mouseup = "mouseup"
    """Constant identifying a `mouseup` event."""
    click = "click"
    """Constant identifying a button `click` event."""
    dblclick = "dblclick"
    """Constant identifying a button `dblclick` event."""
    mousewheel = "wheel"
    """Constant identifying a mouse `wheel` scroll event."""
    
    def __init__(self, hwevent):
        """
        The event is initialized by the system, with a `hwevent` input parameter.
        """
        super().__init__(hwevent)
        self.wheelDelta = 0
        """Integer representing up/down motion of the scroll wheel."""
        if self.type == self.mousewheel:
            self.wheelDelta = hwevent.deltaY
        else:
            self.wheelDelta = 0
        rect = App._win._renderer.view.getBoundingClientRect()
        xscale = App._win.width/rect.width
        yscale = App._win.height/rect.height
        self.x = (hwevent.clientX - rect.left) * xscale
        """The window x-coordinate of the mouse pointer when the event occurred."""
        self.y = (hwevent.clientY - rect.top) * yscale
        """The window y-coordinate of the mouse pointer when the event occurred."""
class KeyEvent(_Event):
    """
    The `ggame.KeyEvent` class encapsulates information regarding a user keyboard
    action that is being reported by the system.
    """    
    no_location = 0
    """Constant indicating no specific location for the key event."""
    right_location = 2
    """Constant indicating the key event was on the right hand side of the keyboard."""
    left_location = 1
    """Constant indicating the key event was on the left hand side of the keyboard."""
    keydown = "keydown"
    """Constant indicating the key was pressed down."""
    keyup = "keyup"
    """Constant indicating the key was released."""
    keypress = "keypress"
    """Constant indicating the combination of keydown, followed by keyup."""
    keys = {8: 'backspace',
        9: 'tab',
        13: 'enter',
        16: 'shift',
        17: 'ctrl',
        18: 'alt',
        19: 'pause/break',
        20: 'caps lock',
        27: 'escape',
        32: 'space',
        33: 'page up',
        34: 'page down',
        35: 'end',
        36: 'home',
        37: 'left arrow',
        38: 'up arrow',
        39: 'right arrow',
        40: 'down arrow',
        45: 'insert',
        46: 'delete',
        48: '0',
        49: '1',
        50: '2',
        51: '3',
        52: '4',
        53: '5',
        54: '6',
        55: '7',
        56: '8',
        57: '9',
        65: 'a',
        66: 'b',
        67: 'c',
        68: 'd',
        69: 'e',
        70: 'f',
        71: 'g',
        72: 'h',
        73: 'i',
        74: 'j',
        75: 'k',
        76: 'l',
        77: 'm',
        78: 'n',
        79: 'o',
        80: 'p',
        81: 'q',
        82: 'r',
        83: 's',
        84: 't',
        85: 'u',
        86: 'v',
        87: 'w',
        88: 'x',
        89: 'y',
        90: 'z',
        91: 'left window key',
        92: 'right window key',
        93: 'select key',
        96: 'numpad 0',
        97: 'numpad 1',
        98: 'numpad 2',
        99: 'numpad 3',
        100: 'numpad 4',
        101: 'numpad 5',
        102: 'numpad 6',
        103: 'numpad 7',
        104: 'numpad 8',
        105: 'numpad 9',
        106: 'multiply',
        107: 'add',
        109: 'subtract',
        110: 'decimal point',
        111: 'divide',
        112: 'f1',
        113: 'f2',
        114: 'f3',
        115: 'f4',
        116: 'f5',
        117: 'f6',
        118: 'f7',
        119: 'f8',
        120: 'f9',
        121: 'f10',
        122: 'f11',
        123: 'f12',
        144: 'num lock',
        145: 'scroll lock',
        186: 'semicolon',
        187: 'equal sign',
        188: 'comma',
        189: 'dash',
        190: 'period',
        191: 'forward slash',
        192: 'grave accent',
        219: 'open bracket',
        220: 'back slash',
        221: 'close bracket',
        222: 'single quote'}    
    """Dictionary mapping key code integers to textual key description."""
    
    def __init__(self, hwevent):
        """
        The event is initialized by the system, with a `hwevent` input parameter.
        """
        super().__init__(hwevent)
        self.keynum = hwevent.keyCode
        """The `keynum` attribute identifies a keycode (number)."""
        self.key = self.keys[hwevent.keyCode]
        """The `key` attribute identifes the key in text form (e.g. 'back slash')."""
class App(object):
    """
    The `ggame.App` class is a (typically subclassed) class that encapsulates
    handling of the display system, and processing user events. The `ggame.App` 
    class also manages lists of all `ggame.Sprite` instances in the application.
    When subclassing `ggame.App` you may elect to instantiate most of your
    sprite objects in the initialization section.
    Processing that must occur on a per-frame basis may be included by overriding
    the `ggame.App.step` method. This is also an appropriate location to call
    similar 'step' methods for your various customized sprite classes.
    Once your application class has been instantiated, begin the frame drawing
    process by calling its `ggame.App.run` method.
    NOTE: Only **one** instance of an `ggame.App` class or subclass may be 
    instantiated at a time.
    """
    spritelist = []
    """List of all sprites currently active in the application."""
    _eventdict = {}
    _spritesdict = {}
    _spritesadded = False
    _win = None
    def __init__(self, *args):
        """
        The `ggame.App` class is called either by specifying the desired app window size
        in pixels, as two parameters (e.g. `myapp = App(640,480)`), or by providing
        no size parameters at all (e.g. `myapp = App()`), in which case, the full browser
        window size is used.
        """
        if App._win == None and (len(args) == 0 or len(args) == 2):
            x = y = 0
            if len(args) == 2:
                x = args[0]
                y = args[1]
            App._win = GFX_Window(x, y, type(self)._destroy)
            self.width = App._win.width
            self.height = App._win.height
            # Add existing sprites to the window
            if not App._spritesadded and len(App.spritelist) > 0:
                App._spritesadded = True
                for sprite in App.spritelist:
                    App._win.add(sprite.GFX)
            App._win.bind(KeyEvent.keydown, self._keyEvent)
            App._win.bind(KeyEvent.keyup, self._keyEvent)
            App._win.bind(KeyEvent.keypress, self._keyEvent)
            App._win.bind(MouseEvent.mousewheel, self._mouseEvent)
            App._win.bind(MouseEvent.mousemove, self._mouseEvent)
            App._win.bind(MouseEvent.mousedown, self._mouseEvent)
            App._win.bind(MouseEvent.mouseup, self._mouseEvent)
            App._win.bind(MouseEvent.click, self._mouseEvent)
            App._win.bind(MouseEvent.dblclick, self._mouseEvent)
        
    def _routeEvent(self, event, evtlist):
        for callback in reversed(evtlist):
            if not event.consumed:
                callback(event)
        
    def _keyEvent(self, hwevent):
        evtlist = App._eventdict.get(
            (hwevent.type, KeyEvent.keys.get(hwevent.keyCode,0)), [])
        evtlist.extend(App._eventdict.get((hwevent.type, '*'), []))
        if len(evtlist) > 0:
            evt = KeyEvent(hwevent)
            self._routeEvent(evt, evtlist)
        return False
    def _mouseEvent(self, hwevent):
        evtlist = App._eventdict.get(hwevent.type, [])
        if len(evtlist) > 0:
            evt = MouseEvent(hwevent)
            self._routeEvent(evt, evtlist)
        return False
    @classmethod
    def _add(cls, obj):
        if App._win != None:
            App._win.add(obj.GFX)
        App.spritelist.append(obj)
        if type(obj) not in App._spritesdict:
            App._spritesdict[type(obj)] = []
        App._spritesdict[type(obj)].append(obj)
    @classmethod
    def _remove(cls, obj):
        if App._win != None:
            App._win.remove(obj.GFX)
        App.spritelist.remove(obj)
        App._spritesdict[type(obj)].remove(obj)
        
    def _animate(self, dummy):
        if self.userfunc:
            self.userfunc()
        else:
            self.step()
        App._win.animate(self._animate)
    @classmethod
    def _destroy(cls, *args):
        """
        This will close the display window/tab, remove all references to 
        sprites and place the `App` class in a state in which a new 
        application could be instantiated.
        """ 
        if App._win:
            App._win.unbind(KeyEvent.keydown)
            App._win.unbind(KeyEvent.keyup)
            App._win.unbind(KeyEvent.keypress)
            App._win.unbind(MouseEvent.mousewheel)
            App._win.unbind(MouseEvent.mousemove)
            App._win.unbind(MouseEvent.mousedown)
            App._win.unbind(MouseEvent.mouseup)
            App._win.unbind(MouseEvent.click)
            App._win.unbind(MouseEvent.dblclick)
            App._win.destroy()
        App._win = None
        for s in list(App.spritelist):
            s.destroy()
        App.spritelist = []
        App._spritesdict = {}
        App._eventdict = {}
        App._spritesadded = False
    @classmethod
    def listenKeyEvent(cls, eventtype, key, callback):
        """
        Register to receive keyboard events. The `eventtype` parameter is a 
        string that indicates what type of key event to receive (value is one
        of: `'keydown'`, `'keyup'` or `'keypress'`). The `key` parameter is a 
        string indicating which key (e.g. `'space'`, `'left arrow'`, etc.) to 
        receive events for. The `callback` parameter is a reference to a 
        function or method that will be called with the `ggame.KeyEvent` object
        when the event occurs.
        See the source for `ggame.KeyEvent.keys` for a list of key names
        to use with the `key` paramter.
        """
        evtlist = App._eventdict.get((eventtype, key), [])
        if not callback in evtlist:
            evtlist.append(callback)
        App._eventdict[(eventtype, key)] = evtlist
    @classmethod
    def listenMouseEvent(cls, eventtype, callback):
        """
        Register to receive mouse events. The `eventtype` parameter is
        a string that indicates what type of mouse event to receive (
        value is one of: `'mousemove'`, `'mousedown'`, `'mouseup'`, `'click'`, 
        `'dblclick'` or `'mousewheel'`). The `callback` parameter is a 
        reference to a function or method that will be called with the 
        `ggame.MouseEvent` object when the event occurs.
        """
        evtlist = App._eventdict.get(eventtype, [])
        if not callback in evtlist:
            evtlist.append(callback)
        App._eventdict[eventtype] = evtlist
    @classmethod
    def unlistenKeyEvent(cls, eventtype, key, callback):
        """
        Use this method to remove a registration to receive a particular
        keyboard event. Arguments must exactly match those used when
        registering for the event.
        """
        App._eventdict[(eventtype,key)].remove(callback)
    @classmethod
    def unlistenMouseEvent(cls, eventtype, callback):
        """
        Use this method to remove a registration to receive a particular
        mouse event. Arguments must exactly match those used when
        registering for the event.
        """
        App._eventdict[eventtype].remove(callback)
    @classmethod
    def getSpritesbyClass(cls, sclass):
        """
        Returns a list of all active sprites of a given class.
        """
        return App._spritesdict.get(sclass, [])
    
    def step(self):
        """
        The `ggame.App.step` method is called once per animation frame. Override
        this method in your own subclass of `ggame.App` to perform periodic 
        calculations, such as checking for sprite collisions, or calling
        'step' functions in your own customized sprite classes.
        The base class `ggame.App.step` method is empty and is intended to be overriden.
        """
        pass
    
    def run(self, userfunc = None):
        """
        Calling the `ggame.App.run` method begins the animation process whereby the 
        `ggame.App.step` method is called once per animation frame. Set `userfunc`
        to any function which shall be called once per animation frame.
        """
        self.userfunc = userfunc
        App._win.animate(self._animate)
        
if __name__ == '__main__':
    
    def test(event):
        print("BOOM")
        x = input("Enter something")
        print(x)
    def testm(event):
        print('squeek!')
    xcenter = 0.0
    xstep = 0.01
    scale = 0.5
    red = Color(0xff0000, 1.0)
    blue = Color(0x0000ff, 1.0)
    line = LineStyle(0, red)
    poly = PolygonAsset([(0,0),(50,75),(100,60),(90,150),(45,100),(0,0)], line, red)
    circ = CircleAsset(75, line, red)
    circ2 = CircleAsset(55, line, blue)
    bun = ImageAsset('bunny.png')
    bun.center = (0.5,0.5)
    rect = RectangleAsset(30,150)
    ell = EllipseAsset(10,3)
    spr = Sprite(bun, (200,300))
    spr2 = Sprite(poly, (375, 255))
    # TRYING to get the extents to initialize!!
    spr2._extentsdirty = True
    spr2._setExtents()
    spr2.rotation = 0.000
    # /\ this does it
    h1 = Sprite(LineAsset(500,0))
    h2 = Sprite(LineAsset(500,0))
    v1 = Sprite(LineAsset(0,500))
    v2 = Sprite(LineAsset(0,500))
    hh1 = Sprite(LineAsset(500,0))
    hh2 = Sprite(LineAsset(500,0))
    vv1 = Sprite(LineAsset(0,500))
    vv2 = Sprite(LineAsset(0,500))
    def step():
        global spr
        global spr2
        global xcenter
        global xstep
        global h1
        global h2
        global v1
        global v2
        global hh1
        global hh2
        global vv1
        global vv2
        global scale
        
        scale = scale + xstep
        spr.fxcenter = xcenter
        spr.fycenter = xcenter
        xcenter = xcenter + xstep
        if xcenter >= 1.0 or xcenter <= 0.0:
            xstep = xstep * -1
        spr.rotation = spr.rotation + 10*xstep
        spr.scale = scale
        spr.x += 1
        spr._setExtents()
        h1.y = spr.ymin
        h2.y = spr.ymax
        v1.x = spr.xmin
        v2.x = spr.xmax
        spr2._setExtents()
        hh1.y = spr2.ymin
        hh2.y = spr2.ymax
        vv1.x = spr2.xmin
        vv2.x = spr2.xmax
        if spr.collidingWith(spr2):
            print("BANG")
    app = App()
    app.listenKeyEvent('keydown', 'e', test)
    app.listenMouseEvent('mousedown', testm)
    app.run(step)
Module variables
var black
Default black color
var blackline
Default thin black line
var white
Default white color
var whiteline
Default thin white line
Classes
class App
The App class is a (typically subclassed) class that encapsulates
handling of the display system, and processing user events. The App 
class also manages lists of all Sprite instances in the application.
When subclassing App you may elect to instantiate most of your
sprite objects in the initialization section.
Processing that must occur on a per-frame basis may be included by overriding
the step method. This is also an appropriate location to call
similar 'step' methods for your various customized sprite classes.
Once your application class has been instantiated, begin the frame drawing
process by calling its run method.
NOTE: Only one instance of an App class or subclass may be 
instantiated at a time.
class App(object):
    """
    The `ggame.App` class is a (typically subclassed) class that encapsulates
    handling of the display system, and processing user events. The `ggame.App` 
    class also manages lists of all `ggame.Sprite` instances in the application.
    When subclassing `ggame.App` you may elect to instantiate most of your
    sprite objects in the initialization section.
    Processing that must occur on a per-frame basis may be included by overriding
    the `ggame.App.step` method. This is also an appropriate location to call
    similar 'step' methods for your various customized sprite classes.
    Once your application class has been instantiated, begin the frame drawing
    process by calling its `ggame.App.run` method.
    NOTE: Only **one** instance of an `ggame.App` class or subclass may be 
    instantiated at a time.
    """
    spritelist = []
    """List of all sprites currently active in the application."""
    _eventdict = {}
    _spritesdict = {}
    _spritesadded = False
    _win = None
    def __init__(self, *args):
        """
        The `ggame.App` class is called either by specifying the desired app window size
        in pixels, as two parameters (e.g. `myapp = App(640,480)`), or by providing
        no size parameters at all (e.g. `myapp = App()`), in which case, the full browser
        window size is used.
        """
        if App._win == None and (len(args) == 0 or len(args) == 2):
            x = y = 0
            if len(args) == 2:
                x = args[0]
                y = args[1]
            App._win = GFX_Window(x, y, type(self)._destroy)
            self.width = App._win.width
            self.height = App._win.height
            # Add existing sprites to the window
            if not App._spritesadded and len(App.spritelist) > 0:
                App._spritesadded = True
                for sprite in App.spritelist:
                    App._win.add(sprite.GFX)
            App._win.bind(KeyEvent.keydown, self._keyEvent)
            App._win.bind(KeyEvent.keyup, self._keyEvent)
            App._win.bind(KeyEvent.keypress, self._keyEvent)
            App._win.bind(MouseEvent.mousewheel, self._mouseEvent)
            App._win.bind(MouseEvent.mousemove, self._mouseEvent)
            App._win.bind(MouseEvent.mousedown, self._mouseEvent)
            App._win.bind(MouseEvent.mouseup, self._mouseEvent)
            App._win.bind(MouseEvent.click, self._mouseEvent)
            App._win.bind(MouseEvent.dblclick, self._mouseEvent)
        
    def _routeEvent(self, event, evtlist):
        for callback in reversed(evtlist):
            if not event.consumed:
                callback(event)
        
    def _keyEvent(self, hwevent):
        evtlist = App._eventdict.get(
            (hwevent.type, KeyEvent.keys.get(hwevent.keyCode,0)), [])
        evtlist.extend(App._eventdict.get((hwevent.type, '*'), []))
        if len(evtlist) > 0:
            evt = KeyEvent(hwevent)
            self._routeEvent(evt, evtlist)
        return False
    def _mouseEvent(self, hwevent):
        evtlist = App._eventdict.get(hwevent.type, [])
        if len(evtlist) > 0:
            evt = MouseEvent(hwevent)
            self._routeEvent(evt, evtlist)
        return False
    @classmethod
    def _add(cls, obj):
        if App._win != None:
            App._win.add(obj.GFX)
        App.spritelist.append(obj)
        if type(obj) not in App._spritesdict:
            App._spritesdict[type(obj)] = []
        App._spritesdict[type(obj)].append(obj)
    @classmethod
    def _remove(cls, obj):
        if App._win != None:
            App._win.remove(obj.GFX)
        App.spritelist.remove(obj)
        App._spritesdict[type(obj)].remove(obj)
        
    def _animate(self, dummy):
        if self.userfunc:
            self.userfunc()
        else:
            self.step()
        App._win.animate(self._animate)
    @classmethod
    def _destroy(cls, *args):
        """
        This will close the display window/tab, remove all references to 
        sprites and place the `App` class in a state in which a new 
        application could be instantiated.
        """ 
        if App._win:
            App._win.unbind(KeyEvent.keydown)
            App._win.unbind(KeyEvent.keyup)
            App._win.unbind(KeyEvent.keypress)
            App._win.unbind(MouseEvent.mousewheel)
            App._win.unbind(MouseEvent.mousemove)
            App._win.unbind(MouseEvent.mousedown)
            App._win.unbind(MouseEvent.mouseup)
            App._win.unbind(MouseEvent.click)
            App._win.unbind(MouseEvent.dblclick)
            App._win.destroy()
        App._win = None
        for s in list(App.spritelist):
            s.destroy()
        App.spritelist = []
        App._spritesdict = {}
        App._eventdict = {}
        App._spritesadded = False
    @classmethod
    def listenKeyEvent(cls, eventtype, key, callback):
        """
        Register to receive keyboard events. The `eventtype` parameter is a 
        string that indicates what type of key event to receive (value is one
        of: `'keydown'`, `'keyup'` or `'keypress'`). The `key` parameter is a 
        string indicating which key (e.g. `'space'`, `'left arrow'`, etc.) to 
        receive events for. The `callback` parameter is a reference to a 
        function or method that will be called with the `ggame.KeyEvent` object
        when the event occurs.
        See the source for `ggame.KeyEvent.keys` for a list of key names
        to use with the `key` paramter.
        """
        evtlist = App._eventdict.get((eventtype, key), [])
        if not callback in evtlist:
            evtlist.append(callback)
        App._eventdict[(eventtype, key)] = evtlist
    @classmethod
    def listenMouseEvent(cls, eventtype, callback):
        """
        Register to receive mouse events. The `eventtype` parameter is
        a string that indicates what type of mouse event to receive (
        value is one of: `'mousemove'`, `'mousedown'`, `'mouseup'`, `'click'`, 
        `'dblclick'` or `'mousewheel'`). The `callback` parameter is a 
        reference to a function or method that will be called with the 
        `ggame.MouseEvent` object when the event occurs.
        """
        evtlist = App._eventdict.get(eventtype, [])
        if not callback in evtlist:
            evtlist.append(callback)
        App._eventdict[eventtype] = evtlist
    @classmethod
    def unlistenKeyEvent(cls, eventtype, key, callback):
        """
        Use this method to remove a registration to receive a particular
        keyboard event. Arguments must exactly match those used when
        registering for the event.
        """
        App._eventdict[(eventtype,key)].remove(callback)
    @classmethod
    def unlistenMouseEvent(cls, eventtype, callback):
        """
        Use this method to remove a registration to receive a particular
        mouse event. Arguments must exactly match those used when
        registering for the event.
        """
        App._eventdict[eventtype].remove(callback)
    @classmethod
    def getSpritesbyClass(cls, sclass):
        """
        Returns a list of all active sprites of a given class.
        """
        return App._spritesdict.get(sclass, [])
    
    def step(self):
        """
        The `ggame.App.step` method is called once per animation frame. Override
        this method in your own subclass of `ggame.App` to perform periodic 
        calculations, such as checking for sprite collisions, or calling
        'step' functions in your own customized sprite classes.
        The base class `ggame.App.step` method is empty and is intended to be overriden.
        """
        pass
    
    def run(self, userfunc = None):
        """
        Calling the `ggame.App.run` method begins the animation process whereby the 
        `ggame.App.step` method is called once per animation frame. Set `userfunc`
        to any function which shall be called once per animation frame.
        """
        self.userfunc = userfunc
        App._win.animate(self._animate)
Ancestors (in MRO)
- App
- builtins.object
Class variables
var spritelist
List of all sprites currently active in the application.
Static methods
def __init__(
self, *args)
The App class is called either by specifying the desired app window size
in pixels, as two parameters (e.g. myapp = App(640,480)), or by providing
no size parameters at all (e.g. myapp = App()), in which case, the full browser
window size is used.
def __init__(self, *args):
    """
    The `ggame.App` class is called either by specifying the desired app window size
    in pixels, as two parameters (e.g. `myapp = App(640,480)`), or by providing
    no size parameters at all (e.g. `myapp = App()`), in which case, the full browser
    window size is used.
    """
    if App._win == None and (len(args) == 0 or len(args) == 2):
        x = y = 0
        if len(args) == 2:
            x = args[0]
            y = args[1]
        App._win = GFX_Window(x, y, type(self)._destroy)
        self.width = App._win.width
        self.height = App._win.height
        # Add existing sprites to the window
        if not App._spritesadded and len(App.spritelist) > 0:
            App._spritesadded = True
            for sprite in App.spritelist:
                App._win.add(sprite.GFX)
        App._win.bind(KeyEvent.keydown, self._keyEvent)
        App._win.bind(KeyEvent.keyup, self._keyEvent)
        App._win.bind(KeyEvent.keypress, self._keyEvent)
        App._win.bind(MouseEvent.mousewheel, self._mouseEvent)
        App._win.bind(MouseEvent.mousemove, self._mouseEvent)
        App._win.bind(MouseEvent.mousedown, self._mouseEvent)
        App._win.bind(MouseEvent.mouseup, self._mouseEvent)
        App._win.bind(MouseEvent.click, self._mouseEvent)
        App._win.bind(MouseEvent.dblclick, self._mouseEvent)
def run(
self, userfunc=None)
Calling the run method begins the animation process whereby the 
step method is called once per animation frame. Set userfunc
to any function which shall be called once per animation frame.
def run(self, userfunc = None):
    """
    Calling the `ggame.App.run` method begins the animation process whereby the 
    `ggame.App.step` method is called once per animation frame. Set `userfunc`
    to any function which shall be called once per animation frame.
    """
    self.userfunc = userfunc
    App._win.animate(self._animate)
def step(
self)
The step method is called once per animation frame. Override
this method in your own subclass of App to perform periodic 
calculations, such as checking for sprite collisions, or calling
'step' functions in your own customized sprite classes.
The base class step method is empty and is intended to be overriden.
def step(self):
    """
    The `ggame.App.step` method is called once per animation frame. Override
    this method in your own subclass of `ggame.App` to perform periodic 
    calculations, such as checking for sprite collisions, or calling
    'step' functions in your own customized sprite classes.
    The base class `ggame.App.step` method is empty and is intended to be overriden.
    """
    pass
Methods
def getSpritesbyClass(
cls, sclass)
Returns a list of all active sprites of a given class.
@classmethod
def getSpritesbyClass(cls, sclass):
    """
    Returns a list of all active sprites of a given class.
    """
    return App._spritesdict.get(sclass, [])
def listenKeyEvent(
cls, eventtype, key, callback)
Register to receive keyboard events. The eventtype parameter is a 
string that indicates what type of key event to receive (value is one
of: 'keydown', 'keyup' or 'keypress'). The key parameter is a 
string indicating which key (e.g. 'space', 'left arrow', etc.) to 
receive events for. The callback parameter is a reference to a 
function or method that will be called with the KeyEvent object
when the event occurs.
See the source for keys for a list of key names
to use with the key paramter.
@classmethod
def listenKeyEvent(cls, eventtype, key, callback):
    """
    Register to receive keyboard events. The `eventtype` parameter is a 
    string that indicates what type of key event to receive (value is one
    of: `'keydown'`, `'keyup'` or `'keypress'`). The `key` parameter is a 
    string indicating which key (e.g. `'space'`, `'left arrow'`, etc.) to 
    receive events for. The `callback` parameter is a reference to a 
    function or method that will be called with the `ggame.KeyEvent` object
    when the event occurs.
    See the source for `ggame.KeyEvent.keys` for a list of key names
    to use with the `key` paramter.
    """
    evtlist = App._eventdict.get((eventtype, key), [])
    if not callback in evtlist:
        evtlist.append(callback)
    App._eventdict[(eventtype, key)] = evtlist
def listenMouseEvent(
cls, eventtype, callback)
Register to receive mouse events. The eventtype parameter is
a string that indicates what type of mouse event to receive (
value is one of: 'mousemove', 'mousedown', 'mouseup', 'click', 
'dblclick' or 'mousewheel'). The callback parameter is a 
reference to a function or method that will be called with the 
MouseEvent object when the event occurs.
@classmethod
def listenMouseEvent(cls, eventtype, callback):
    """
    Register to receive mouse events. The `eventtype` parameter is
    a string that indicates what type of mouse event to receive (
    value is one of: `'mousemove'`, `'mousedown'`, `'mouseup'`, `'click'`, 
    `'dblclick'` or `'mousewheel'`). The `callback` parameter is a 
    reference to a function or method that will be called with the 
    `ggame.MouseEvent` object when the event occurs.
    """
    evtlist = App._eventdict.get(eventtype, [])
    if not callback in evtlist:
        evtlist.append(callback)
    App._eventdict[eventtype] = evtlist
def unlistenKeyEvent(
cls, eventtype, key, callback)
Use this method to remove a registration to receive a particular keyboard event. Arguments must exactly match those used when registering for the event.
@classmethod
def unlistenKeyEvent(cls, eventtype, key, callback):
    """
    Use this method to remove a registration to receive a particular
    keyboard event. Arguments must exactly match those used when
    registering for the event.
    """
    App._eventdict[(eventtype,key)].remove(callback)
def unlistenMouseEvent(
cls, eventtype, callback)
Use this method to remove a registration to receive a particular mouse event. Arguments must exactly match those used when registering for the event.
@classmethod
def unlistenMouseEvent(cls, eventtype, callback):
    """
    Use this method to remove a registration to receive a particular
    mouse event. Arguments must exactly match those used when
    registering for the event.
    """
    App._eventdict[eventtype].remove(callback)
class CircleAsset
The CircleAsset is a "virtual" asset that is created on the
fly without requiring creation of an image file.
class CircleAsset(_ShapeAsset):
    """
    The `ggame.CircleAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file.
    """    
    def __init__(self, radius, line=blackline, fill=black):
        """
        Creation of a `ggame.CircleAsset` requires specification of the circle
        `radius` in pixels, the `line` (as a proper `ggame.LineStyle` instance)
        and fill properties (as a `ggame.Color` instance).
        """
        super().__init__(line, fill)
        self.radius = radius
        self.GFX = GFX_Graphics.drawCircle(0, 0, self.radius).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
Ancestors (in MRO)
- CircleAsset
- __pdoc_file_module__._ShapeAsset
- __pdoc_file_module__._CurveAsset
- __pdoc_file_module__._GraphicsAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, radius, line=<__pdoc_file_module__.LineStyle object at 0x7f8eacdd9eb8>, fill=<__pdoc_file_module__.Color object at 0x7f8eacdd9d30>)
Creation of a CircleAsset requires specification of the circle
radius in pixels, the line (as a proper LineStyle instance)
and fill properties (as a Color instance).
def __init__(self, radius, line=blackline, fill=black):
    """
    Creation of a `ggame.CircleAsset` requires specification of the circle
    `radius` in pixels, the `line` (as a proper `ggame.LineStyle` instance)
    and fill properties (as a `ggame.Color` instance).
    """
    super().__init__(line, fill)
    self.radius = radius
    self.GFX = GFX_Graphics.drawCircle(0, 0, self.radius).clone()
    """The `GFX` property represents the underlying system object."""
    self.GFX.visible = False
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
The GFX property represents the underlying system object.
var radius
class Color
The Color class is used to represent colors and/or colors with
transparency.
class Color(object):
    """
    The `ggame.Color` class is used to represent colors and/or colors with
    transparency.
    """
    def __init__(self, color, alpha):
        """
        A `ggame.Color` instance must specify both a `color` as an integer
        in the conventional format (usually as a hexadecimal literal, e.g.
        0xffbb33 that represents the three color components, red, green 
        and blue), and a transparency value, or `alpha` as a floating
        point number in the range of 0.0 to 1.0 where 0.0 represents 
        completely transparent and 1.0 represents completely solid.
        Example: `red = Color(0xff0000, 1.0)`
        """
        self.color = color
        self.alpha = alpha
        
    def __eq__(self, other):
        return type(self) is type(other) and self.color == other.color and self.alpha == other.alpha
Ancestors (in MRO)
- Color
- builtins.object
Static methods
def __init__(
self, color, alpha)
A Color instance must specify both a color as an integer
in the conventional format (usually as a hexadecimal literal, e.g.
0xffbb33 that represents the three color components, red, green 
and blue), and a transparency value, or alpha as a floating
point number in the range of 0.0 to 1.0 where 0.0 represents 
completely transparent and 1.0 represents completely solid.
Example: red = Color(0xff0000, 1.0)
def __init__(self, color, alpha):
    """
    A `ggame.Color` instance must specify both a `color` as an integer
    in the conventional format (usually as a hexadecimal literal, e.g.
    0xffbb33 that represents the three color components, red, green 
    and blue), and a transparency value, or `alpha` as a floating
    point number in the range of 0.0 to 1.0 where 0.0 represents 
    completely transparent and 1.0 represents completely solid.
    Example: `red = Color(0xff0000, 1.0)`
    """
    self.color = color
    self.alpha = alpha
Instance variables
var alpha
var color
class EllipseAsset
The EllipseAsset is a "virtual" asset that is created on the 
fly without requiring creation of an image file.
class EllipseAsset(_ShapeAsset):
    """
    The `ggame.EllipseAsset` is a "virtual" asset that is created on the 
    fly without requiring creation of an image file.
    """
    def __init__(self, halfw, halfh, line=blackline, fill=black):
        """
        Creation of a `ggame.EllipseAsset` requires specification of the ellipse
        `halfw`, or semi-axis length in the horizontal direction (half of the
        ellipse width) and the `halfh`, or semi-axis length in the vertical direction.
        `line` (as `ggame.LineStyle` instance) and `fill` (as `ggame.Color` instance)
        must also be provided.
        """
        super().__init__(line, fill)
        self.halfw = halfw
        self.halfh = halfh
        self.GFX = GFX_Graphics.drawEllipse(0, 0, self.halfw, self.halfh).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
Ancestors (in MRO)
- EllipseAsset
- __pdoc_file_module__._ShapeAsset
- __pdoc_file_module__._CurveAsset
- __pdoc_file_module__._GraphicsAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, halfw, halfh, line=<__pdoc_file_module__.LineStyle object at 0x7f8eacdd9eb8>, fill=<__pdoc_file_module__.Color object at 0x7f8eacdd9d30>)
Creation of a EllipseAsset requires specification of the ellipse
halfw, or semi-axis length in the horizontal direction (half of the
ellipse width) and the halfh, or semi-axis length in the vertical direction.
line (as LineStyle instance) and fill (as Color instance)
must also be provided.
def __init__(self, halfw, halfh, line=blackline, fill=black):
    """
    Creation of a `ggame.EllipseAsset` requires specification of the ellipse
    `halfw`, or semi-axis length in the horizontal direction (half of the
    ellipse width) and the `halfh`, or semi-axis length in the vertical direction.
    `line` (as `ggame.LineStyle` instance) and `fill` (as `ggame.Color` instance)
    must also be provided.
    """
    super().__init__(line, fill)
    self.halfw = halfw
    self.halfh = halfh
    self.GFX = GFX_Graphics.drawEllipse(0, 0, self.halfw, self.halfh).clone()
    """The `GFX` property represents the underlying system object."""
    self.GFX.visible = False
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
The GFX property represents the underlying system object.
var halfh
var halfw
class Frame
Frame is a utility class for expressing the idea of a rectangular region.
class Frame(object):
    """
    Frame is a utility class for expressing the idea of a rectangular region.
    """
    
    def __init__(self, x, y, w, h):
        """
        Initialization for the `ggame.Frame` objects.
        `x` and `y` are coordinates of the upper left hand corner of the frame.
 
        `w` and `h` are the width and height of the frame rectangle.
        """
        self.GFX = GFX_Rectangle(x,y,w,h)
        """
        `GFX` is a reference to the underlying object provided by the system.
        """
        self.x = x
        """
        X-coordinate of the upper left hand corner of this `ggame.Frame`.
        """
        self.y = y
        """
        Y-coordinate of the upper left hand corner of this `ggame.Frame`.
        """
        self.w = w
        """
        Width of the `ggame.Frame`.
        """
        self.h = h
        """
        Height of the `ggame.Frame`.
        """
    
    @property
    def x(self):
        return self.GFX.x
    
    @x.setter
    def x(self, value):
        self.GFX.x = value
        
    @property
    def y(self):
        return self.GFX.y
    
    @y.setter
    def y(self, value):
        self.GFX.y = value
    
    @property
    def w(self):
        return self.GFX.width
    
    @w.setter
    def w(self, value):
        self.GFX.width = value
        
    @property
    def h(self):
        return self.GFX.height
        
    @h.setter
    def h(self, value):
        self.GFX.height = value
    
    @property
    def center(self):
        """
        `center` property computes a coordinate pair (tuple) for the 
        center of the frame.
        The `center` property, when set, redefines the `x` and `y` properties
        of the frame in order to make the center agree with the coordinates
        (tuple) assigned to it.
        """
        return (self.x + self.w//2, self.y + self.h//2)
    
    @center.setter
    def center(self, value):
        c = self.center
        self.x += value[0] - c[0]
        self.y += value[1] - c[1]
Ancestors (in MRO)
- Frame
- builtins.object
Static methods
def __init__(
self, x, y, w, h)
Initialization for the Frame objects.
x and y are coordinates of the upper left hand corner of the frame.
w and h are the width and height of the frame rectangle.
def __init__(self, x, y, w, h):
    """
    Initialization for the `ggame.Frame` objects.
    `x` and `y` are coordinates of the upper left hand corner of the frame.
    `w` and `h` are the width and height of the frame rectangle.
    """
    self.GFX = GFX_Rectangle(x,y,w,h)
    """
    `GFX` is a reference to the underlying object provided by the system.
    """
    self.x = x
    """
    X-coordinate of the upper left hand corner of this `ggame.Frame`.
    """
    self.y = y
    """
    Y-coordinate of the upper left hand corner of this `ggame.Frame`.
    """
    self.w = w
    """
    Width of the `ggame.Frame`.
    """
    self.h = h
    """
    Height of the `ggame.Frame`.
    """
Instance variables
var GFX
GFX is a reference to the underlying object provided by the system.
var center
center property computes a coordinate pair (tuple) for the 
center of the frame.
The center property, when set, redefines the x and y properties
of the frame in order to make the center agree with the coordinates
(tuple) assigned to it.
class ImageAsset
The ImageAsset class connects ggame to a specific image file.
class ImageAsset(_Asset):
    """
    The `ImageAsset` class connects ggame to a specific image **file**.
    """
    def __init__(self, url, frame=None, qty=1, direction='horizontal', margin=0):
        """
        All `ggame.ImageAsset` instances must specify a file name or url with
        the `url` parameter.
        If the desired sprite image exists in only a smaller sub-section of the 
        original image, then the are can be specified by providing the
        `frame` parameter, which must be a valid `ggame.Frame` object.
        If image file actually is a *collection* of images, such as a so-called
        *sprite sheet*, then the `ImageAsset` class supports defining a list
        of images, provided they exist in the original image as a **row**
        of evenly spaced images or a **column** of images. To specify this,
        provide the `qty` (quantity) of images in the row or column, the
        `direction` of the list ('horizontal' or 'vertical' are supported),
        and an optional `margin`, if there is a gap between successive 
        images. When used in this way, the `frame` parameter must define the
        area of the **first** image in the collection; all subsequent images
        in the list are assumed to be the same size.
        """
        super().__init__()
        self.url = url
        """
        A string that represents the path or url of the original file.
        """
        del self.GFXlist[0]
        self.width = self.height = 0
        self.append(url, frame, qty, direction, margin)
    def _subframe(self, texture, frame):
        return GFX_Texture(texture, frame.GFX)
        
    def append(self, url, frame=None, qty=1, direction='horizontal', margin=0):
        """
        Append a texture asset from a new image file (or url). This method
        allows you to build a collection of images into an asset (such as you
        might need for an animated sprite), but without using a single 
        sprite sheet image.
        The parameters for the `append` method are identical to those 
        supplied to the `ggame.ImageAsset` initialization method. 
        This method allows you to build up an asset that consists of 
        multiple rows or columns of images in a sprite sheet or sheets.
        """
        GFX = GFX_Texture_fromImage(url, False)
        dx = 0
        dy = 0
        for i in range(qty):
            if not frame is None:
                self.width = frame.w
                self.height = frame.h
                if direction == 'horizontal':
                    dx = frame.w + margin
                elif direction == 'vertical':
                    dy = frame.h + margin
                f = Frame(frame.x + dx * i, frame.y + dy * i, frame.w, frame.h)
                GFX = self._subframe(GFX, f)
            else:
                self.width = GFX.width
                self.height = GFX.height
            self.GFXlist.append(GFX)
Ancestors (in MRO)
- ImageAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, url, frame=None, qty=1, direction='horizontal', margin=0)
All ImageAsset instances must specify a file name or url with
the url parameter.
If the desired sprite image exists in only a smaller sub-section of the 
original image, then the are can be specified by providing the
frame parameter, which must be a valid Frame object.
If image file actually is a collection of images, such as a so-called
sprite sheet, then the ImageAsset class supports defining a list
of images, provided they exist in the original image as a row
of evenly spaced images or a column of images. To specify this,
provide the qty (quantity) of images in the row or column, the
direction of the list ('horizontal' or 'vertical' are supported),
and an optional margin, if there is a gap between successive 
images. When used in this way, the frame parameter must define the
area of the first image in the collection; all subsequent images
in the list are assumed to be the same size.
def __init__(self, url, frame=None, qty=1, direction='horizontal', margin=0):
    """
    All `ggame.ImageAsset` instances must specify a file name or url with
    the `url` parameter.
    If the desired sprite image exists in only a smaller sub-section of the 
    original image, then the are can be specified by providing the
    `frame` parameter, which must be a valid `ggame.Frame` object.
    If image file actually is a *collection* of images, such as a so-called
    *sprite sheet*, then the `ImageAsset` class supports defining a list
    of images, provided they exist in the original image as a **row**
    of evenly spaced images or a **column** of images. To specify this,
    provide the `qty` (quantity) of images in the row or column, the
    `direction` of the list ('horizontal' or 'vertical' are supported),
    and an optional `margin`, if there is a gap between successive 
    images. When used in this way, the `frame` parameter must define the
    area of the **first** image in the collection; all subsequent images
    in the list are assumed to be the same size.
    """
    super().__init__()
    self.url = url
    """
    A string that represents the path or url of the original file.
    """
    del self.GFXlist[0]
    self.width = self.height = 0
    self.append(url, frame, qty, direction, margin)
def append(
self, url, frame=None, qty=1, direction='horizontal', margin=0)
Append a texture asset from a new image file (or url). This method allows you to build a collection of images into an asset (such as you might need for an animated sprite), but without using a single sprite sheet image.
The parameters for the append method are identical to those 
supplied to the ImageAsset initialization method. 
This method allows you to build up an asset that consists of multiple rows or columns of images in a sprite sheet or sheets.
def append(self, url, frame=None, qty=1, direction='horizontal', margin=0):
    """
    Append a texture asset from a new image file (or url). This method
    allows you to build a collection of images into an asset (such as you
    might need for an animated sprite), but without using a single 
    sprite sheet image.
    The parameters for the `append` method are identical to those 
    supplied to the `ggame.ImageAsset` initialization method. 
    This method allows you to build up an asset that consists of 
    multiple rows or columns of images in a sprite sheet or sheets.
    """
    GFX = GFX_Texture_fromImage(url, False)
    dx = 0
    dy = 0
    for i in range(qty):
        if not frame is None:
            self.width = frame.w
            self.height = frame.h
            if direction == 'horizontal':
                dx = frame.w + margin
            elif direction == 'vertical':
                dy = frame.h + margin
            f = Frame(frame.x + dx * i, frame.y + dy * i, frame.w, frame.h)
            GFX = self._subframe(GFX, f)
        else:
            self.width = GFX.width
            self.height = GFX.height
        self.GFXlist.append(GFX)
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
GFX property represents the underlying system object used to represent
this asset. If this asset is composed of multiple assets, then the first
asset is referenced by GFX.
var url
A string that represents the path or url of the original file.
class KeyEvent
The KeyEvent class encapsulates information regarding a user keyboard
action that is being reported by the system.
class KeyEvent(_Event):
    """
    The `ggame.KeyEvent` class encapsulates information regarding a user keyboard
    action that is being reported by the system.
    """    
    no_location = 0
    """Constant indicating no specific location for the key event."""
    right_location = 2
    """Constant indicating the key event was on the right hand side of the keyboard."""
    left_location = 1
    """Constant indicating the key event was on the left hand side of the keyboard."""
    keydown = "keydown"
    """Constant indicating the key was pressed down."""
    keyup = "keyup"
    """Constant indicating the key was released."""
    keypress = "keypress"
    """Constant indicating the combination of keydown, followed by keyup."""
    keys = {8: 'backspace',
        9: 'tab',
        13: 'enter',
        16: 'shift',
        17: 'ctrl',
        18: 'alt',
        19: 'pause/break',
        20: 'caps lock',
        27: 'escape',
        32: 'space',
        33: 'page up',
        34: 'page down',
        35: 'end',
        36: 'home',
        37: 'left arrow',
        38: 'up arrow',
        39: 'right arrow',
        40: 'down arrow',
        45: 'insert',
        46: 'delete',
        48: '0',
        49: '1',
        50: '2',
        51: '3',
        52: '4',
        53: '5',
        54: '6',
        55: '7',
        56: '8',
        57: '9',
        65: 'a',
        66: 'b',
        67: 'c',
        68: 'd',
        69: 'e',
        70: 'f',
        71: 'g',
        72: 'h',
        73: 'i',
        74: 'j',
        75: 'k',
        76: 'l',
        77: 'm',
        78: 'n',
        79: 'o',
        80: 'p',
        81: 'q',
        82: 'r',
        83: 's',
        84: 't',
        85: 'u',
        86: 'v',
        87: 'w',
        88: 'x',
        89: 'y',
        90: 'z',
        91: 'left window key',
        92: 'right window key',
        93: 'select key',
        96: 'numpad 0',
        97: 'numpad 1',
        98: 'numpad 2',
        99: 'numpad 3',
        100: 'numpad 4',
        101: 'numpad 5',
        102: 'numpad 6',
        103: 'numpad 7',
        104: 'numpad 8',
        105: 'numpad 9',
        106: 'multiply',
        107: 'add',
        109: 'subtract',
        110: 'decimal point',
        111: 'divide',
        112: 'f1',
        113: 'f2',
        114: 'f3',
        115: 'f4',
        116: 'f5',
        117: 'f6',
        118: 'f7',
        119: 'f8',
        120: 'f9',
        121: 'f10',
        122: 'f11',
        123: 'f12',
        144: 'num lock',
        145: 'scroll lock',
        186: 'semicolon',
        187: 'equal sign',
        188: 'comma',
        189: 'dash',
        190: 'period',
        191: 'forward slash',
        192: 'grave accent',
        219: 'open bracket',
        220: 'back slash',
        221: 'close bracket',
        222: 'single quote'}    
    """Dictionary mapping key code integers to textual key description."""
    
    def __init__(self, hwevent):
        """
        The event is initialized by the system, with a `hwevent` input parameter.
        """
        super().__init__(hwevent)
        self.keynum = hwevent.keyCode
        """The `keynum` attribute identifies a keycode (number)."""
        self.key = self.keys[hwevent.keyCode]
        """The `key` attribute identifes the key in text form (e.g. 'back slash')."""
Ancestors (in MRO)
- KeyEvent
- __pdoc_file_module__._Event
- builtins.object
Class variables
var keydown
Constant indicating the key was pressed down.
var keypress
Constant indicating the combination of keydown, followed by keyup.
var keys
Dictionary mapping key code integers to textual key description.
var keyup
Constant indicating the key was released.
var left_location
Constant indicating the key event was on the left hand side of the keyboard.
var no_location
Constant indicating no specific location for the key event.
var right_location
Constant indicating the key event was on the right hand side of the keyboard.
Static methods
def __init__(
self, hwevent)
The event is initialized by the system, with a hwevent input parameter.
def __init__(self, hwevent):
    """
    The event is initialized by the system, with a `hwevent` input parameter.
    """
    super().__init__(hwevent)
    self.keynum = hwevent.keyCode
    """The `keynum` attribute identifies a keycode (number)."""
    self.key = self.keys[hwevent.keyCode]
    """The `key` attribute identifes the key in text form (e.g. 'back slash')."""
Instance variables
var key
The key attribute identifes the key in text form (e.g. 'back slash').
var keynum
The keynum attribute identifies a keycode (number).
class LineAsset
The LineAsset is a "virtual" asset that is created on the
fly without requiring creation of an image file. A LineAsset instance
represents a single line segment.
class LineAsset(_CurveAsset):
    """
    The `ggame.LineAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file. A `LineAsset` instance
    represents a single line segment.
    """
    def __init__(self, x, y, line=blackline):
        """
        Creation of a `ggame.LineAsset` requires specification of an `x` and
        `y` coordinate for the endpoint of the line. The starting point of the
        line is implied as coordinates (0,0). Note that when this asset is 
        used in a `ggame.Sprite` class, the sprite's `x` and `y` coordinates
        will control the location of the line segment on the screen.
        As the `ggame.LineAsset` does not cover a region, only a `ggame.LineStyle` 
        argument must be supplied (`line`).
        """
        super().__init__(line)
        self.deltaX = x
        """This attribute represents the `x` parameter supplied during instantiation."""
        self.deltaY = y
        """This attribute represents the `y` parameter supplied during instantiation."""
        GFX_Graphics.moveTo(0, 0)
        self.GFX = GFX_Graphics.lineTo(self.deltaX, self.deltaY).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
Ancestors (in MRO)
- LineAsset
- __pdoc_file_module__._CurveAsset
- __pdoc_file_module__._GraphicsAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, x, y, line=<__pdoc_file_module__.LineStyle object at 0x7f8eacdd9eb8>)
Creation of a LineAsset requires specification of an x and
y coordinate for the endpoint of the line. The starting point of the
line is implied as coordinates (0,0). Note that when this asset is 
used in a Sprite class, the sprite's x and y coordinates
will control the location of the line segment on the screen.
As the LineAsset does not cover a region, only a LineStyle 
argument must be supplied (line).
def __init__(self, x, y, line=blackline):
    """
    Creation of a `ggame.LineAsset` requires specification of an `x` and
    `y` coordinate for the endpoint of the line. The starting point of the
    line is implied as coordinates (0,0). Note that when this asset is 
    used in a `ggame.Sprite` class, the sprite's `x` and `y` coordinates
    will control the location of the line segment on the screen.
    As the `ggame.LineAsset` does not cover a region, only a `ggame.LineStyle` 
    argument must be supplied (`line`).
    """
    super().__init__(line)
    self.deltaX = x
    """This attribute represents the `x` parameter supplied during instantiation."""
    self.deltaY = y
    """This attribute represents the `y` parameter supplied during instantiation."""
    GFX_Graphics.moveTo(0, 0)
    self.GFX = GFX_Graphics.lineTo(self.deltaX, self.deltaY).clone()
    """The `GFX` property represents the underlying system object."""
    self.GFX.visible = False
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
The GFX property represents the underlying system object.
var deltaX
This attribute represents the x parameter supplied during instantiation.
var deltaY
This attribute represents the y parameter supplied during instantiation.
class LineStyle
The LineStyle class is used to represent line style when
drawing geometrical objects such as rectangles, ellipses, etc.
class LineStyle(object):
    """
    The `ggame.LineStyle` class is used to represent line style when
    drawing geometrical objects such as rectangles, ellipses, etc.
    """
    
    def __init__(self, width, color):
        """
        When creating a `ggame.LineStyle` instances you must specify 
        the `width` of the line in pixels and the `color` as a valid
        `ggame.Color` instance.
        Example: `line = LineStyle(3, Color(0x00ff00, 1.0))` will define
        a 3 pixel wide green line.
        """
        self.width = width
        self.color = color
    def __eq__(self, other):
        return type(self) is type(other) and self.width == other.width and self.color == other.color
Ancestors (in MRO)
- LineStyle
- builtins.object
Static methods
def __init__(
self, width, color)
When creating a LineStyle instances you must specify 
the width of the line in pixels and the color as a valid
Color instance.
Example: line = LineStyle(3, Color(0x00ff00, 1.0)) will define
a 3 pixel wide green line.
def __init__(self, width, color):
    """
    When creating a `ggame.LineStyle` instances you must specify 
    the `width` of the line in pixels and the `color` as a valid
    `ggame.Color` instance.
    Example: `line = LineStyle(3, Color(0x00ff00, 1.0))` will define
    a 3 pixel wide green line.
    """
    self.width = width
    self.color = color
Instance variables
var color
var width
class MouseEvent
The MouseEvent class encapsulates information regarding a user mouse
action that is being reported by the system.
class MouseEvent(_Event):
    """
    The `ggame.MouseEvent` class encapsulates information regarding a user mouse
    action that is being reported by the system.
    """    
    mousemove = "mousemove"
    """Constant identifying a `mousemove` event."""
    mousedown = "mousedown"
    """Constant identifying a `mousedown` event."""
    mouseup = "mouseup"
    """Constant identifying a `mouseup` event."""
    click = "click"
    """Constant identifying a button `click` event."""
    dblclick = "dblclick"
    """Constant identifying a button `dblclick` event."""
    mousewheel = "wheel"
    """Constant identifying a mouse `wheel` scroll event."""
    
    def __init__(self, hwevent):
        """
        The event is initialized by the system, with a `hwevent` input parameter.
        """
        super().__init__(hwevent)
        self.wheelDelta = 0
        """Integer representing up/down motion of the scroll wheel."""
        if self.type == self.mousewheel:
            self.wheelDelta = hwevent.deltaY
        else:
            self.wheelDelta = 0
        rect = App._win._renderer.view.getBoundingClientRect()
        xscale = App._win.width/rect.width
        yscale = App._win.height/rect.height
        self.x = (hwevent.clientX - rect.left) * xscale
        """The window x-coordinate of the mouse pointer when the event occurred."""
        self.y = (hwevent.clientY - rect.top) * yscale
        """The window y-coordinate of the mouse pointer when the event occurred."""
Ancestors (in MRO)
- MouseEvent
- __pdoc_file_module__._Event
- builtins.object
Class variables
var click
Constant identifying a button click event.
var dblclick
Constant identifying a button dblclick event.
var mousedown
Constant identifying a mousedown event.
var mousemove
Constant identifying a mousemove event.
var mouseup
Constant identifying a mouseup event.
var mousewheel
Constant identifying a mouse wheel scroll event.
Static methods
def __init__(
self, hwevent)
The event is initialized by the system, with a hwevent input parameter.
def __init__(self, hwevent):
    """
    The event is initialized by the system, with a `hwevent` input parameter.
    """
    super().__init__(hwevent)
    self.wheelDelta = 0
    """Integer representing up/down motion of the scroll wheel."""
    if self.type == self.mousewheel:
        self.wheelDelta = hwevent.deltaY
    else:
        self.wheelDelta = 0
    rect = App._win._renderer.view.getBoundingClientRect()
    xscale = App._win.width/rect.width
    yscale = App._win.height/rect.height
    self.x = (hwevent.clientX - rect.left) * xscale
    """The window x-coordinate of the mouse pointer when the event occurred."""
    self.y = (hwevent.clientY - rect.top) * yscale
    """The window y-coordinate of the mouse pointer when the event occurred."""
Instance variables
var wheelDelta
Integer representing up/down motion of the scroll wheel.
var x
The window x-coordinate of the mouse pointer when the event occurred.
var y
The window y-coordinate of the mouse pointer when the event occurred.
class PolygonAsset
The PolygonAsset is a "virtual" asset that is created on the
fly without requiring creation of an image file.
class PolygonAsset(_ShapeAsset):
    """
    The `ggame.PolygonAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file.
    """
    def __init__(self, path, line=blackline, fill=black):
        """
        Creation of a `ggame.PolygonAsset` requires specification of a 
        `path` consisting of a list of coordinate tuples. `line` and 
        `fill` arguments (instances of `ggame.LineStyle` and `ggame.Color`,
        respectively) must also be supplied. The final coordinate in the 
        list must be the same as the first.
        Example: `poly = PolygonAsset([(0,0), (50,50), (50,100), (0,0)], linesty, fcolor)`
        """
        super().__init__(line, fill)
        self.path = path
        jpath = []
        for point in self.path:
            jpath.extend(point)
        self.GFX = GFX_Graphics.drawPolygon(jpath).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
Ancestors (in MRO)
- PolygonAsset
- __pdoc_file_module__._ShapeAsset
- __pdoc_file_module__._CurveAsset
- __pdoc_file_module__._GraphicsAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, path, line=<__pdoc_file_module__.LineStyle object at 0x7f8eacdd9eb8>, fill=<__pdoc_file_module__.Color object at 0x7f8eacdd9d30>)
Creation of a PolygonAsset requires specification of a 
path consisting of a list of coordinate tuples. line and 
fill arguments (instances of LineStyle and Color,
respectively) must also be supplied. The final coordinate in the 
list must be the same as the first.
Example: poly = PolygonAsset([(0,0), (50,50), (50,100), (0,0)], linesty, fcolor)
def __init__(self, path, line=blackline, fill=black):
    """
    Creation of a `ggame.PolygonAsset` requires specification of a 
    `path` consisting of a list of coordinate tuples. `line` and 
    `fill` arguments (instances of `ggame.LineStyle` and `ggame.Color`,
    respectively) must also be supplied. The final coordinate in the 
    list must be the same as the first.
    Example: `poly = PolygonAsset([(0,0), (50,50), (50,100), (0,0)], linesty, fcolor)`
    """
    super().__init__(line, fill)
    self.path = path
    jpath = []
    for point in self.path:
        jpath.extend(point)
    self.GFX = GFX_Graphics.drawPolygon(jpath).clone()
    """The `GFX` property represents the underlying system object."""
    self.GFX.visible = False
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
The GFX property represents the underlying system object.
var path
class RectangleAsset
The RectangleAsset is a "virtual" asset that is created on the
fly without requiring creation of an image file.
class RectangleAsset(_ShapeAsset):
    """
    The `ggame.RectangleAsset` is a "virtual" asset that is created on the
    fly without requiring creation of an image file.
    """
    def __init__(self, width, height, line=blackline, fill=black):
        """
        Creation of a `ggame.RectangleAsset` requires specification of the 
        rectangle `width` and `height` in pixels, the `line` (as a proper
        `ggame.LineStyle` instance) and fill properties (as a `ggame.Color`
        instance).
        """
        super().__init__(line, fill)
        self.width = width
        self.height = height
        self.GFX = GFX_Graphics.drawRect(0, 0, self.width, self.height).clone()
        """The `GFX` property represents the underlying system object."""
        self.GFX.visible = False
Ancestors (in MRO)
- RectangleAsset
- __pdoc_file_module__._ShapeAsset
- __pdoc_file_module__._CurveAsset
- __pdoc_file_module__._GraphicsAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, width, height, line=<__pdoc_file_module__.LineStyle object at 0x7f8eacdd9eb8>, fill=<__pdoc_file_module__.Color object at 0x7f8eacdd9d30>)
Creation of a RectangleAsset requires specification of the 
rectangle width and height in pixels, the line (as a proper
LineStyle instance) and fill properties (as a Color
instance).
def __init__(self, width, height, line=blackline, fill=black):
    """
    Creation of a `ggame.RectangleAsset` requires specification of the 
    rectangle `width` and `height` in pixels, the `line` (as a proper
    `ggame.LineStyle` instance) and fill properties (as a `ggame.Color`
    instance).
    """
    super().__init__(line, fill)
    self.width = width
    self.height = height
    self.GFX = GFX_Graphics.drawRect(0, 0, self.width, self.height).clone()
    """The `GFX` property represents the underlying system object."""
    self.GFX.visible = False
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
The GFX property represents the underlying system object.
var height
var width
class Sound
The Sound class represents a sound, with methods for controlling
when and how the sound is played in the application.
class Sound(object):
    """
    The `ggame.Sound` class represents a sound, with methods for controlling
    when and how the sound is played in the application.
    """
    def __init__(self, asset):
        """
        Pass a valid `ggame.SoundAsset` instance when creating a `ggame.Sound` object.
        """
        self.asset = asset
        """
        A reference to the `ggame.SoundAsset` instance.
        """
        self.SND = SND_Sound(self.asset.url)
        """
        A reference to the underlying sound object provided by the system.
        """
        self.SND.load()
        
    def play(self):
        """
        Play the sound once.
        """
        self.stop()
        self.SND.play()
    def loop(self):
        """
        Play the sound continuously, looping forever.
        """
        self.stop()
        self.SND.loop()
        self.SND.play()
        
    def stop(self):
        """
        Stop playing the sound.
        """
        self.SND.stop()
        
    @property
    def volume(self):
        """
        The `ggame.Sound.volume` property is a number ranging from 0-100, that 
        represents the volume or intensity of the sound when it is playing.
        """
        return self.SND.getVolume()
        
    @volume.setter
    def volume(self, value):
        self.SND.setVolume(value)
Ancestors (in MRO)
- Sound
- builtins.object
Static methods
def __init__(
self, asset)
Pass a valid SoundAsset instance when creating a Sound object.
def __init__(self, asset):
    """
    Pass a valid `ggame.SoundAsset` instance when creating a `ggame.Sound` object.
    """
    self.asset = asset
    """
    A reference to the `ggame.SoundAsset` instance.
    """
    self.SND = SND_Sound(self.asset.url)
    """
    A reference to the underlying sound object provided by the system.
    """
    self.SND.load()
def loop(
self)
Play the sound continuously, looping forever.
def loop(self):
    """
    Play the sound continuously, looping forever.
    """
    self.stop()
    self.SND.loop()
    self.SND.play()
def play(
self)
Play the sound once.
def play(self):
    """
    Play the sound once.
    """
    self.stop()
    self.SND.play()
def stop(
self)
Stop playing the sound.
def stop(self):
    """
    Stop playing the sound.
    """
    self.SND.stop()
Instance variables
var SND
A reference to the underlying sound object provided by the system.
var volume
The volume property is a number ranging from 0-100, that 
represents the volume or intensity of the sound when it is playing.
class SoundAsset
Class representing a single sound asset (sound file, such as .mp3 or .wav).
class SoundAsset(object):
    """
    Class representing a single sound asset (sound file, such as .mp3 or .wav).
    """    
    def __init__(self, url):
        """
        Create a `ggame.SoundAsset` instance by passing in the URL or file name
        of the desired sound. Sound file formats may include `.wav` or `.mp3`, subject
        to browser compatibility. 
        """
        self.url = url
        """
        A string containing the url or name of the asset file.
        """
Ancestors (in MRO)
- SoundAsset
- builtins.object
Static methods
def __init__(
self, url)
Create a SoundAsset instance by passing in the URL or file name
of the desired sound. Sound file formats may include .wav or .mp3, subject
to browser compatibility.
def __init__(self, url):
    """
    Create a `ggame.SoundAsset` instance by passing in the URL or file name
    of the desired sound. Sound file formats may include `.wav` or `.mp3`, subject
    to browser compatibility. 
    """
    self.url = url
    """
    A string containing the url or name of the asset file.
    """
Instance variables
var url
A string containing the url or name of the asset file.
class Sprite
The Sprite class combines the idea of a visual/graphical asset, a
position on the screen, and behavior. Although the Sprite can be
used as-is, it is generally subclassed to give it the desired behavior.
When subclassing the Sprite class, you may customize the initialization
code to use a specific asset. A 'step' or 'poll' method may be added
for handling per-frame actions (e.g. checking for collisions). Step or poll
functions are not automatically called by the App class, but you
may subclass the App class in order to do this.
Furthermore, you may wish to define event callback methods in your customized sprite class. With customized creation, event handling, and periodic processing you can achieve fully autonomous behavior for your class.
class Sprite(object):
    """
    The `ggame.Sprite` class combines the idea of a visual/graphical asset, a
    position on the screen, and *behavior*. Although the `ggame.Sprite` can be
    used as-is, it is generally subclassed to give it the desired behavior.
    When subclassing the `ggame.Sprite` class, you may customize the initialization
    code to use a specific asset. A 'step' or 'poll' method may be added
    for handling per-frame actions (e.g. checking for collisions). Step or poll
    functions are not automatically called by the `ggame.App` class, but you
    may subclass the `ggame.App` class in order to do this.
    Furthermore, you may wish to define event callback methods in your customized
    sprite class. With customized creation, event handling, and periodic processing
    you can achieve fully autonomous behavior for your class. 
    """
 
    _rectCollision = "rect"
    _circCollision = "circ"
    
    def __init__(self, asset, pos=(0,0), edgedef=None):
        """
        The `ggame.Sprite` must be created with an existing graphical `asset`.
        
        An optional `pos` or position may be provided, which specifies the 
        starting (x,y) coordinates of the sprite on the screen. By default,
        the position of a sprite defines the location of its upper-left hand
        corner. This behavior can be modified by customizing the `center` of
        the sprite.
        
        An optional `edgedef` or edge definition may be provided, which
        specifies an asset that will be used to define the boundaries of
        the sprite for the purpose of collision detection. If no `edgedef` 
        asset is given, the Sprite asset is used, which will be a rectangular
        asset in the case of an image texture. This option is typically used
        to define a visible image outline for a texture-based sprite that has
        a transparent texture image background.
        
        Example: player = Sprite(ImageAsset("player.png", (100,100), CircleAsset(50))
        
        This creates a sprite using the `player.png` image, positioned with its
        upper left corner at coordinates (100,100) and with a 50 pixel radius 
        circular collision border. 
        """
        self._index = 0
        if type(asset) == ImageAsset:
            self.asset = asset
            try:
                #self.GFX = GFX_Sprite()
                self.GFX = GFX_Sprite(asset.GFX) # GFX is PIXI Sprite
            except:
                self.GFX = None
        elif type(asset) in [RectangleAsset, 
            CircleAsset, 
            EllipseAsset, 
            PolygonAsset,
            LineAsset,
            ]:
            self.asset = asset
            self.GFX = GFX_Sprite(asset.GFX.generateTexture())
            #self.GFX = asset.GFX.clone() # GFX is PIXI Graphics (from Sprite)
            #self.GFX.visible = True
        elif type(asset) in [TextAsset]:
            self.asset = asset._clone()
            self.GFX = self.asset.GFX # GFX is PIXI Text (from Sprite)
            self.GFX.visible = True
        if not edgedef:
            self.edgedef = asset
        else:
            self.edgedef = edgedef
        self.xmin = self.xmax = self.ymin = self.ymax = 0
        self.position = pos
        """Tuple indicates the position of the sprite on the screen."""
        self._extentsdirty = True
        """Boolean indicates if extents must be calculated before collision test"""
        self._createBaseVertices()
        self._setExtents()
        """Initialize the extents (xmax, xmin, etc.) for collision detection"""
        App._add(self)
        
    def _createBaseVertices(self):
        """
        Create sprite-relative list of vertex coordinates for boundary
        """
        self._basevertices = []
        assettype = type(self.edgedef)
        if assettype in [RectangleAsset, ImageAsset, TextAsset]:
            self._basevertices = [(0,0), 
                (0,self.edgedef.height), 
                (self.edgedef.width,self.edgedef.height),
                (self.edgedef.width,0)]
        elif assettype is PolygonAsset:
            self._basevertices = self.edgedef.path[:-1]
        elif assettype is LineAsset:
            self._basevertices = [(0,0), 
                (self.edgedef.deltaX, self.edgedef.deltaY)]
        elif assettype is EllipseAsset:
            w = self.edgedef.halfw * 2
            h = self.edgedef.halfh * 2
            self._basevertices = [(0,0), (0,h), (w,h), (w,0)]
    def _xformVertices(self):
        """
        Create window-relative list of vertex coordinates for boundary
        """
        # find center as sprite-relative points (note sprite may be scaled)
        x = self.width * self.fxcenter / self.scale
        y = self.height * self.fycenter / self.scale
        if self.scale != 1.0:
            sc = self.scale
            # center-relative, scaled coordinates
            crsc = [((xp-x)*sc,(yp-y)*sc) for xp,yp in self._basevertices]
        else:
            crsc = [(xp-x,yp-y) for xp,yp in self._basevertices]
            
        # absolute, rotated coordinates
        c = math.cos(self.rotation)
        s = math.sin(self.rotation)
        self._absolutevertices = [(self.x + x*c + y*s, self.y + -x*s + y*c) 
                                    for x,y in crsc]
    def _setExtents(self):
        """
        update min/max x and y based on position, center, width, height
        """
        if self._extentsdirty:
            if type(self.asset) is CircleAsset:
                th = math.atan2(
                    self.fycenter - 0.5, 0.5 - self.fxcenter) + self.rotation
                D = self.width
                L = math.sqrt(math.pow(self.fxcenter - 0.5, 2) + 
                    math.pow(self.fycenter - 0.5, 2)) * D
                self.xmin = self.x + int(L*math.cos(th)) - D//2
                self.ymin = self.y - int(L*math.sin(th)) - D//2
                self.xmax = self.xmin + D
                self.ymax = self.ymin + D
            else:
                # Build vertex list
                self._xformVertices()
                x, y = zip(*self._absolutevertices)
                self.xmin = min(x)
                self.xmax = max(x)
                self.ymin = min(y)
                self.ymax = max(y)
            self._extentsdirty = False
    def firstImage(self):
        """
        Select and display the *first* image used by this sprite.
        """
        self.GFX.texture = self.asset[0]
    
    def lastImage(self):
        """
        Select and display the *last* image used by this sprite.
        """
        self.GFX.texture = self.asset[-1]
    
    def nextImage(self, wrap = False):
        """
        Select and display the *next* image used by this sprite.
        If the current image is already the *last* image, then
        the image is not advanced.
        If the optional `wrap` parameter is set to `True`, then calling
        `ggame.Sprite.nextImage` on the last image will cause the *first*
        image to be loaded.
        """
        self._index += 1
        if self._index >= len(self.asset):
            if wrap:
                self._index = 0
            else:
                self._index = len(self.asset)-1
        self.GFX.texture = self.asset[self._index]
    
    def prevImage(self, wrap = False):
        """
        Select and display the *previous* image used by this sprite.
        If the current image is already the *first* image, then
        the image is not changed.
        If the optional `wrap` parameter is set to `True`, then calling
        `ggame.Sprite.prevImage` on the first image will cause the *last*
        image to be loaded.
        """
        self._index -= 1
        if self._index < 0:
            if wrap:
                self._index = len(self.asset)-1
            else:
                self._index = 0
        self.GFX.texture = self.asset[self._index]
    
    def setImage(self, index=0):
        """
        Select the image to display by giving its `index`, where an index
        of zero represents the *first* image in the asset.
        This is equivalent to setting the `ggame.Sprite.index` property
        directly.
        """
        self.index = index
    def rectangularCollisionModel(self):
        """
        Obsolete. No op.
        """
        pass
    
    def circularCollisionModel(self):
        """
        Obsolete. No op.
        """
        pass
    
    
    @property
    def index(self):
        """This is an integer index in to the list of images available for this sprite."""
        return self._index
        
    @index.setter
    def index(self, value):
        self._index = value
        try:
            self.GFX.texture = self.asset[self._index]
        except:
            self._index = 0
            self.GFX.texture = self.asset[self._index]
    @property
    def width(self):
        """
        This is an integer representing the display width of the sprite.
        Assigning a value to the width will scale the image horizontally.
        """
        return self.GFX.width
        
    @width.setter
    def width(self, value):
        self.GFX.width = value
        self._extentsdirty = True
    
    @property
    def height(self):
        """
        This is an integer representing the display height of the sprite.
        Assigning a value to the height will scale the image vertically.
        """
        return self.GFX.height
    
    @height.setter
    def height(self, value):
        self.GFX.height = value
        self._extentsdirty = True
        
    @property
    def x(self):
        """
        This represents the x-coordinate of the sprite on the screen. Assigning
        a value to this attribute will move the sprite horizontally.
        """
        return self.GFX.position.x
        
    @x.setter
    def x(self, value):
        deltax = value - self.GFX.position.x
        self.xmax += deltax
        self.xmin += deltax
        """Adjust extents directly with low overhead"""
        self.GFX.position.x = value
    @property
    def y(self):
        """
        This represents the y-coordinate of the sprite on the screen. Assigning
        a value to this attribute will move the sprite vertically.
        """
        return self.GFX.position.y
        
    @y.setter
    def y(self, value):
        deltay = value - self.GFX.position.y
        self.ymax += deltay
        self.ymin += deltay
        """Adjust extents directly with low overhead"""
        self.GFX.position.y = value
    @property
    def position(self):
        """
        This represents the (x,y) coordinates of the sprite on the screen. Assigning
        a value to this attribute will move the sprite to the new coordinates.
        """
        return (self.GFX.position.x, self.GFX.position.y)
        
    @position.setter
    def position(self, value):
        self.x, self.y = value
    @property
    def fxcenter(self):
        """
        This represents the horizontal position of the sprite "center", as a floating
        point number between 0.0 and 1.0. A value of 0.0 means that the x-coordinate
        of the sprite refers to its left hand edge. A value of 1.0 refers to its 
        right hand edge. Any value in between may be specified. Values may be assigned
        to this attribute. 
        """
        try:
            return self.GFX.anchor.x
            self._extentsdirty = True
        except:
            return 0.0
        
    @fxcenter.setter
    def fxcenter(self, value):
        """
        Float: 0-1
        """
        try:
            self.GFX.anchor.x = value
            self._extentsdirty = True
        except:
            pass
        
    @property
    def fycenter(self):
        """
        This represents the vertical position of the sprite "center", as a floating
        point number between 0.0 and 1.0. A value of 0.0 means that the x-coordinate
        of the sprite refers to its top edge. A value of 1.0 refers to its 
        bottom edge. Any value in between may be specified. Values may be assigned
        to this attribute. 
        """
        try:
            return self.GFX.anchor.y
        except:
            return 0.0
        
    @fycenter.setter
    def fycenter(self, value):
        """
        Float: 0-1
        """
        try:
            self.GFX.anchor.y = value
            self._extentsdirty = True
        except:
            pass
    
    @property
    def center(self):
        """
        This attribute represents the horizontal and vertical position of the 
        sprite "center" as a tuple of floating point numbers. See the 
        descriptions for `ggame.Sprite.fxcenter` and `ggame.Sprite.fycenter` for 
        more details.
        """
        try:
            return (self.GFX.anchor.x, self.GFX.anchor.y)
        except:
            return (0.0, 0.0)
        
    @center.setter
    def center(self, value):
        try:
            self.GFX.anchor.x = value[0]
            self.GFX.anchor.y = value[1]
            self._extentsdirty = True
        except:
            pass
    
    @property
    def visible(self):
        """
        This boolean attribute may be used to change the visibility of the sprite. Setting
        `ggame.Sprite.visible` to `False` will prevent the sprite from rendering on the 
        screen.
        """
        return self.GFX.visible
    
    @visible.setter
    def visible(self, value):
        self.GFX.visible = value
    @property
    def scale(self):
        """
        This attribute may be used to change the size of the sprite ('scale' it) on the 
        screen. Value may be a floating point number. A value of 1.0 means that the sprite
        image will keep its original size. A value of 2.0 would double it, etc.
        """
        try:
            return self.GFX.scale.x
        except AttributeError:
            return 1.0
        
    @scale.setter
    def scale(self, value):
        self.GFX.scale.x = value
        self.GFX.scale.y = value
        self._extentsdirty = True
    @property
    def rotation(self):
        """
        This attribute may be used to change the rotation of the sprite on the screen.
        Value may be a floating point number. A value of 0.0 means no rotation. A value 
        of 1.0 means  a rotation of 1 radian in a counter-clockwise direction. One radian
        is 180/pi or approximately 57.3 degrees.
        """
        try:
            return -self.GFX.rotation
        except AttributeError:
            return 0.0
        
    @rotation.setter
    def rotation(self, value):
        self.GFX.rotation = -value
        if value:
            self._extentsdirty = True
    @classmethod
    def collidingCircleWithPoly(cls, circ, poly):
        return True
    
    def collidingPolyWithPoly(self, obj):
        return True
    def collidingWith(self, obj):
        """
        Return a boolean True if this sprite is currently overlapping the sprite 
        referenced by `obj`. Returns False if checking for collision with 
        itself. Returns False if extents of object make it impossible for
        collision to occur. Returns True if sprite's `edgedef` parameter overlaps
        with other sprite's `edgedef` parameter, taking into consideration both
        sprites' center, rotation and scale settings.
        """
        if self is obj:
            return False
        else:
            self._setExtents()
            obj._setExtents()
            # Gross check for overlap will usually rule out a collision
            if (self.xmin > obj.xmax
                or self.xmax < obj.xmin
                or self.ymin > obj.ymax
                or self.ymax < obj.ymin):
                return False
            # Otherwise, perform a careful overlap determination
            elif type(self.asset) is CircleAsset:
                if type(obj.asset) is CircleAsset:
                    # two circles .. check distance between
                    sx = (self.xmin + self.xmax) / 2
                    sy = (self.ymin + self.ymax) / 2
                    ox = (obj.xmin + obj.xmax) / 2
                    oy = (obj.ymin + obj.ymax) / 2
                    d = math.sqrt((sx-ox)**2 + (sy-oy)**2)
                    return d <= self.width/2 + obj.width/2
                else:
                    return self.collidingCircleWithPoly(self, obj)
            else:
                if type(obj.asset) is CircleAsset:
                    return self.collidingCircleWithPoly(obj, self)
                else:
                    return self.collidingPolyWithPoly(obj)
                
                
    def collidingWithSprites(self, sclass = None):
        """
        Return a list of sprite objects identified by the `sclass` parameter
        that are currently colliding with (that is, with which the `ggame.Sprite.collidingWith`
        method returns True) this sprite. If `sclass` is set to `None` (default), then
        all other sprites are checked for collision, otherwise, only sprites whose
        class matches `sclass` are checked.
        """
        if sclass is None:
            slist = App.spritelist
        else:
            slist = App.getSpritesbyClass(sclass)
        return list(filter(self.collidingWith, slist))
    def destroy(self):
        """
        Call the `ggame.Sprite.destroy` method to prevent the sprite from being displayed,
        or checked in collision detection. If you only want to prevent a sprite from being
        displayed, set the `ggame.Sprite.visible` attribute to `False`.
        """
        App._remove(self)
        self.GFX.destroy()
Ancestors (in MRO)
- Sprite
- builtins.object
Static methods
def __init__(
self, asset, pos=(0, 0), edgedef=None)
The Sprite must be created with an existing graphical asset.
An optional pos or position may be provided, which specifies the 
starting (x,y) coordinates of the sprite on the screen. By default,
the position of a sprite defines the location of its upper-left hand
corner. This behavior can be modified by customizing the center of
the sprite.
An optional edgedef or edge definition may be provided, which
specifies an asset that will be used to define the boundaries of
the sprite for the purpose of collision detection. If no edgedef 
asset is given, the Sprite asset is used, which will be a rectangular
asset in the case of an image texture. This option is typically used
to define a visible image outline for a texture-based sprite that has
a transparent texture image background.
Example: player = Sprite(ImageAsset("player.png", (100,100), CircleAsset(50))
This creates a sprite using the player.png image, positioned with its
upper left corner at coordinates (100,100) and with a 50 pixel radius 
circular collision border.
def __init__(self, asset, pos=(0,0), edgedef=None):
    """
    The `ggame.Sprite` must be created with an existing graphical `asset`.
    
    An optional `pos` or position may be provided, which specifies the 
    starting (x,y) coordinates of the sprite on the screen. By default,
    the position of a sprite defines the location of its upper-left hand
    corner. This behavior can be modified by customizing the `center` of
    the sprite.
    
    An optional `edgedef` or edge definition may be provided, which
    specifies an asset that will be used to define the boundaries of
    the sprite for the purpose of collision detection. If no `edgedef` 
    asset is given, the Sprite asset is used, which will be a rectangular
    asset in the case of an image texture. This option is typically used
    to define a visible image outline for a texture-based sprite that has
    a transparent texture image background.
    
    Example: player = Sprite(ImageAsset("player.png", (100,100), CircleAsset(50))
    
    This creates a sprite using the `player.png` image, positioned with its
    upper left corner at coordinates (100,100) and with a 50 pixel radius 
    circular collision border. 
    """
    self._index = 0
    if type(asset) == ImageAsset:
        self.asset = asset
        try:
            #self.GFX = GFX_Sprite()
            self.GFX = GFX_Sprite(asset.GFX) # GFX is PIXI Sprite
        except:
            self.GFX = None
    elif type(asset) in [RectangleAsset, 
        CircleAsset, 
        EllipseAsset, 
        PolygonAsset,
        LineAsset,
        ]:
        self.asset = asset
        self.GFX = GFX_Sprite(asset.GFX.generateTexture())
        #self.GFX = asset.GFX.clone() # GFX is PIXI Graphics (from Sprite)
        #self.GFX.visible = True
    elif type(asset) in [TextAsset]:
        self.asset = asset._clone()
        self.GFX = self.asset.GFX # GFX is PIXI Text (from Sprite)
        self.GFX.visible = True
    if not edgedef:
        self.edgedef = asset
    else:
        self.edgedef = edgedef
    self.xmin = self.xmax = self.ymin = self.ymax = 0
    self.position = pos
    """Tuple indicates the position of the sprite on the screen."""
    self._extentsdirty = True
    """Boolean indicates if extents must be calculated before collision test"""
    self._createBaseVertices()
    self._setExtents()
    """Initialize the extents (xmax, xmin, etc.) for collision detection"""
    App._add(self)
def circularCollisionModel(
self)
Obsolete. No op.
def circularCollisionModel(self):
    """
    Obsolete. No op.
    """
    pass
def collidingPolyWithPoly(
self, obj)
def collidingPolyWithPoly(self, obj):
    return True
def collidingWith(
self, obj)
Return a boolean True if this sprite is currently overlapping the sprite 
referenced by obj. Returns False if checking for collision with 
itself. Returns False if extents of object make it impossible for
collision to occur. Returns True if sprite's edgedef parameter overlaps
with other sprite's edgedef parameter, taking into consideration both
sprites' center, rotation and scale settings.
def collidingWith(self, obj):
    """
    Return a boolean True if this sprite is currently overlapping the sprite 
    referenced by `obj`. Returns False if checking for collision with 
    itself. Returns False if extents of object make it impossible for
    collision to occur. Returns True if sprite's `edgedef` parameter overlaps
    with other sprite's `edgedef` parameter, taking into consideration both
    sprites' center, rotation and scale settings.
    """
    if self is obj:
        return False
    else:
        self._setExtents()
        obj._setExtents()
        # Gross check for overlap will usually rule out a collision
        if (self.xmin > obj.xmax
            or self.xmax < obj.xmin
            or self.ymin > obj.ymax
            or self.ymax < obj.ymin):
            return False
        # Otherwise, perform a careful overlap determination
        elif type(self.asset) is CircleAsset:
            if type(obj.asset) is CircleAsset:
                # two circles .. check distance between
                sx = (self.xmin + self.xmax) / 2
                sy = (self.ymin + self.ymax) / 2
                ox = (obj.xmin + obj.xmax) / 2
                oy = (obj.ymin + obj.ymax) / 2
                d = math.sqrt((sx-ox)**2 + (sy-oy)**2)
                return d <= self.width/2 + obj.width/2
            else:
                return self.collidingCircleWithPoly(self, obj)
        else:
            if type(obj.asset) is CircleAsset:
                return self.collidingCircleWithPoly(obj, self)
            else:
                return self.collidingPolyWithPoly(obj)
def collidingWithSprites(
self, sclass=None)
Return a list of sprite objects identified by the sclass parameter
that are currently colliding with (that is, with which the collidingWith
method returns True) this sprite. If sclass is set to None (default), then
all other sprites are checked for collision, otherwise, only sprites whose
class matches sclass are checked.
def collidingWithSprites(self, sclass = None):
    """
    Return a list of sprite objects identified by the `sclass` parameter
    that are currently colliding with (that is, with which the `ggame.Sprite.collidingWith`
    method returns True) this sprite. If `sclass` is set to `None` (default), then
    all other sprites are checked for collision, otherwise, only sprites whose
    class matches `sclass` are checked.
    """
    if sclass is None:
        slist = App.spritelist
    else:
        slist = App.getSpritesbyClass(sclass)
    return list(filter(self.collidingWith, slist))
def destroy(
self)
Call the destroy method to prevent the sprite from being displayed,
or checked in collision detection. If you only want to prevent a sprite from being
displayed, set the visible attribute to False.
def destroy(self):
    """
    Call the `ggame.Sprite.destroy` method to prevent the sprite from being displayed,
    or checked in collision detection. If you only want to prevent a sprite from being
    displayed, set the `ggame.Sprite.visible` attribute to `False`.
    """
    App._remove(self)
    self.GFX.destroy()
def firstImage(
self)
Select and display the first image used by this sprite.
def firstImage(self):
    """
    Select and display the *first* image used by this sprite.
    """
    self.GFX.texture = self.asset[0]
def lastImage(
self)
Select and display the last image used by this sprite.
def lastImage(self):
    """
    Select and display the *last* image used by this sprite.
    """
    self.GFX.texture = self.asset[-1]
def nextImage(
self, wrap=False)
Select and display the next image used by this sprite. If the current image is already the last image, then the image is not advanced.
If the optional wrap parameter is set to True, then calling
nextImage on the last image will cause the first
image to be loaded.
def nextImage(self, wrap = False):
    """
    Select and display the *next* image used by this sprite.
    If the current image is already the *last* image, then
    the image is not advanced.
    If the optional `wrap` parameter is set to `True`, then calling
    `ggame.Sprite.nextImage` on the last image will cause the *first*
    image to be loaded.
    """
    self._index += 1
    if self._index >= len(self.asset):
        if wrap:
            self._index = 0
        else:
            self._index = len(self.asset)-1
    self.GFX.texture = self.asset[self._index]
def prevImage(
self, wrap=False)
Select and display the previous image used by this sprite. If the current image is already the first image, then the image is not changed.
If the optional wrap parameter is set to True, then calling
prevImage on the first image will cause the last
image to be loaded.
def prevImage(self, wrap = False):
    """
    Select and display the *previous* image used by this sprite.
    If the current image is already the *first* image, then
    the image is not changed.
    If the optional `wrap` parameter is set to `True`, then calling
    `ggame.Sprite.prevImage` on the first image will cause the *last*
    image to be loaded.
    """
    self._index -= 1
    if self._index < 0:
        if wrap:
            self._index = len(self.asset)-1
        else:
            self._index = 0
    self.GFX.texture = self.asset[self._index]
def rectangularCollisionModel(
self)
Obsolete. No op.
def rectangularCollisionModel(self):
    """
    Obsolete. No op.
    """
    pass
def setImage(
self, index=0)
Select the image to display by giving its index, where an index
of zero represents the first image in the asset.
This is equivalent to setting the index property
directly.
def setImage(self, index=0):
    """
    Select the image to display by giving its `index`, where an index
    of zero represents the *first* image in the asset.
    This is equivalent to setting the `ggame.Sprite.index` property
    directly.
    """
    self.index = index
Instance variables
var center
This attribute represents the horizontal and vertical position of the 
sprite "center" as a tuple of floating point numbers. See the 
descriptions for fxcenter and fycenter for 
more details.
var fxcenter
This represents the horizontal position of the sprite "center", as a floating point number between 0.0 and 1.0. A value of 0.0 means that the x-coordinate of the sprite refers to its left hand edge. A value of 1.0 refers to its right hand edge. Any value in between may be specified. Values may be assigned to this attribute.
var fycenter
This represents the vertical position of the sprite "center", as a floating point number between 0.0 and 1.0. A value of 0.0 means that the x-coordinate of the sprite refers to its top edge. A value of 1.0 refers to its bottom edge. Any value in between may be specified. Values may be assigned to this attribute.
var height
This is an integer representing the display height of the sprite. Assigning a value to the height will scale the image vertically.
var index
This is an integer index in to the list of images available for this sprite.
var position
Tuple indicates the position of the sprite on the screen.
var rotation
This attribute may be used to change the rotation of the sprite on the screen. Value may be a floating point number. A value of 0.0 means no rotation. A value of 1.0 means a rotation of 1 radian in a counter-clockwise direction. One radian is 180/pi or approximately 57.3 degrees.
var scale
This attribute may be used to change the size of the sprite ('scale' it) on the screen. Value may be a floating point number. A value of 1.0 means that the sprite image will keep its original size. A value of 2.0 would double it, etc.
var visible
This boolean attribute may be used to change the visibility of the sprite. Setting
visible to False will prevent the sprite from rendering on the 
screen.
var width
This is an integer representing the display width of the sprite. Assigning a value to the width will scale the image horizontally.
var x
This represents the x-coordinate of the sprite on the screen. Assigning a value to this attribute will move the sprite horizontally.
var y
This represents the y-coordinate of the sprite on the screen. Assigning a value to this attribute will move the sprite vertically.
Methods
def collidingCircleWithPoly(
cls, circ, poly)
@classmethod
def collidingCircleWithPoly(cls, circ, poly):
    return True
class TextAsset
The TextAsset is a "virtual" asset that is created on the fly
without requiring creation of an image file. A TextAsset instance
represents a block of text, together with its styling (font, color, etc.).
class TextAsset(_GraphicsAsset):
    """
    The `ggame.TextAsset` is a "virtual" asset that is created on the fly
    without requiring creation of an image file. A `TextAsset` instance
    represents a block of text, together with its styling (font, color, etc.).
    """
 
    def __init__(self, text, **kwargs):
        """
        The `ggame.TextAsset` must be created with a string as the `text` parameter.
        
        The remaining optional arguments must be supplied as keyword parameters. These
        parameters are described under the class attributes, below:
        """
        super().__init__()
        self.text = text
        self.style = kwargs.get('style', '20px Arial')
        """A string that specifies style, size and typeface (e.g. `'italic 20pt Helvetica'` or `'20px Arial'`)"""
        width = kwargs.get('width', 100)
        """Width of the text block on the screen, in pixels."""
        self.fill = kwargs.get('fill', Color(0, 1))
        """A valid `ggame.Color` instance that specifies the color and transparency of the text."""
        self.align = kwargs.get('align', 'left')
        """The alignment style of the text. One of: `'left'`, `'center'`, or `'right'`."""
        self.GFX = GFX_Text(self.text, 
            {'font': self.style,
                'fill' : self.fill.color,
                'align' : self.align,
                'wordWrap' : True,
                'wordWrapWidth' : width,
                })
        """The `GFX` property represents the underlying system object."""
        self.GFX.alpha = self.fill.alpha
        self.GFX.visible = False
        
    def _clone(self):
        return type(self)(self.text,
            style = self.style,
            width = self.width,
            fill = self.fill,
            align = self.align)
    
    @property
    def width(self):
        return self.GFX.width
        
    @property
    def height(self):
        return self.GFX.height
Ancestors (in MRO)
- TextAsset
- __pdoc_file_module__._GraphicsAsset
- __pdoc_file_module__._Asset
- builtins.object
Static methods
def __init__(
self, text, **kwargs)
The TextAsset must be created with a string as the text parameter.
The remaining optional arguments must be supplied as keyword parameters. These parameters are described under the class attributes, below:
def __init__(self, text, **kwargs):
    """
    The `ggame.TextAsset` must be created with a string as the `text` parameter.
    
    The remaining optional arguments must be supplied as keyword parameters. These
    parameters are described under the class attributes, below:
    """
    super().__init__()
    self.text = text
    self.style = kwargs.get('style', '20px Arial')
    """A string that specifies style, size and typeface (e.g. `'italic 20pt Helvetica'` or `'20px Arial'`)"""
    width = kwargs.get('width', 100)
    """Width of the text block on the screen, in pixels."""
    self.fill = kwargs.get('fill', Color(0, 1))
    """A valid `ggame.Color` instance that specifies the color and transparency of the text."""
    self.align = kwargs.get('align', 'left')
    """The alignment style of the text. One of: `'left'`, `'center'`, or `'right'`."""
    self.GFX = GFX_Text(self.text, 
        {'font': self.style,
            'fill' : self.fill.color,
            'align' : self.align,
            'wordWrap' : True,
            'wordWrapWidth' : width,
            })
    """The `GFX` property represents the underlying system object."""
    self.GFX.alpha = self.fill.alpha
    self.GFX.visible = False
def destroy(
self)
def destroy(self):
    if hasattr(self, 'GFX'):
        try:
            for gfx in self.GFXlist:
                try:
                    gfx.destroy(True)
                except:
                    pass
        except:
            pass
Instance variables
var GFX
The GFX property represents the underlying system object.
var align
The alignment style of the text. One of: 'left', 'center', or 'right'.
var height
var style
A string that specifies style, size and typeface (e.g. 'italic 20pt Helvetica' or '20px Arial')
var text
var width