# QwSpriteField Class Reference

A QwSpriteField is a 2D graphic area upon which QwSpriteFieldGraphic objects are drawn. More...

`#include <QwSpriteField.h>`

Inherited by QwImageSpriteField.

List of all member functions.

## Public Members

- QwSpriteField ()
- QwSpriteField ( int w, int h, int chunksize=16, int maxclusters=100 )
- virtual ~QwSpriteField ()
- void update ()
- virtual void resize ( int width, int height )
- int width () const
- int height () const
- int chunkSize () const
- void retune ( int chunksize, int maxclusters )
- Pix all ()
- Pix topAt ( int x, int y )
- Pix lookIn ( int x, int y, int w, int h )
- void next ( Pix & ) const
- void end ( Pix & p ) const
- QwSpriteFieldGraphic* at ( Pix p ) const
- bool exact ( Pix p ) const
- void protectFromChange ( Pix p )
- bool sameChunk ( int x1, int y1, int x2, int y2 ) const
- void setChangedChunk ( int i, int j )
- void setChangedChunkContaining ( int x, int y )
- void addGraphicToChunk ( QwSpriteFieldGraphic *, int i, int j )
- void removeGraphicFromChunk ( QwSpriteFieldGraphic *, int i, int j )
- void addGraphicToChunkContaining ( QwSpriteFieldGraphic *, int x, int y )
- void removeGraphicFromChunkContaining ( QwSpriteFieldGraphic *, int x, int y )
- void* listAtChunkTopFirst ( int i, int j ) const
- void* allList ()
- void addView ( QwAbsSpriteFieldView * )
- void removeView ( QwAbsSpriteFieldView * )
- void updateInView ( QwAbsSpriteFieldView *, const QRect & )
- void addGraphic ( QwSpriteFieldGraphic * )
- void removeGraphic ( QwSpriteFieldGraphic * )

## Static Public Members

- void setPositionPrecision ( int downshifts )
- int positionPrecision ()
- int world_to_x ( int i )
- int x_to_world ( int i )

## Protected Members

- virtual void drawBackground ( QPainter &, const QRect & area )
- virtual void drawForeground ( QPainter &, const QRect & area )
- void forceRedraw ( const QRect & )

## Detailed Description

A QwSpriteField is a 2D graphic area upon which QwSpriteFieldGraphic objects are drawn.

The QwSpriteField and related classes (primarily QwSpriteFieldView and QwSprite, but also the other sprite abstractions) provide for multiple concurrent views of a 2D area containing moving graphical objects.

The QwSpriteField is also an indexing mechanism to the sprites it contains, providing 2D-area-based iteration and pixelwise collision detection.

Most of the methods in QwSpriteField are mainly used by the existing QwSpriteFieldGraphic classes, so will only be interesting if you intend to add a new type of QwSpriteFieldGraphic class. The methods of primary interest to the typical user are, in approximate order of decreasing usefulness:

- QwSpriteField (int w, int h, int chunksize, int maxclusters)
- void update ()
- int width () const
- int height () const
- Pix topAt (int x, int y)
- Pix lookIn (int x, int y, int w, int h)
- QwSpriteFieldGraphic* at (Pix) const
- bool exact (Pix) const
- void next (Pix&)
- void end (Pix&)
- void protectFromChange (Pix)
- virtual void drawBackground (QPainter&, const QRect& area)
- virtual void drawForeground (QPainter&, const QRect& area)

This class provides for very high redraw efficiency. The properties of the mechanism are:

- There is no size or number limitation on sprites (except memory).
- QwSprites are fairly light-weight (small in memory size).
- QwVirtualSprites are very light-weight (small in memory size).
- Collision detection is efficient.
- Finding sprites in an area is efficient.
- Only moving sprites are redrawn.
- The number of unmoving sprites on the field has little effect.
- Redraws can be batched (see update)
- Only visible areas (those in the visible part of a QwSpriteFieldView) are redrawn.

For example, it is quite feasible to have thousands of sprites used to create background scenery, and even animate pieces of that scenery occasionally. It is less feasible to have views where the entire scene is in continous motion, such as a continously scrolling background. You will be suprised how little animation is required to make a scene look `alive'.

The various sprite abstractions are:

QwSprite
  A sprite with a position given by int coordinates.
QwRealSprite
  A sprite with a position given by double coordinates.
QwPositionedSprite<COORD>
  A sprite with a position given by COORD coordinates. This is a template class.
QwVirtualSprite
  A sprite with a position determined dynamically.

QwVirtualSprite is the base class, from which is derived QwPositionedSprite, and from that is derived the QwSprite and QwRealSprite classes. This hierarchy provides you with multiple points at which to adapt to your requirements.

For the purpose of simplified description, we use the term sprite to refer to all these and derived classes.

## Member Function Documentation

### QwSpriteField::QwSpriteField ()

Create a QwSpriteField with no size, and default chunksize/maxclusters. You will want to call resize(int,int) at some time after creation.

### QwSpriteField::QwSpriteField ( int w, int h, int chunksze=16, int maxclust=100 )

Constructs a QwSpriteField with size `w` wide and `h` high, measured in world coordinates (by default, world coordinates equal pixel coordinates).

The values `maxclusters` and `chunksize` effect the grouping heuristics used when redrawing the QwSpriteField.

`chunksize` is the size of square chunk used to break up the QwSpriteField into area to be considered for redrawing. It should be about the average size of graphics in the QwSpriteField. Chunks too small increase the amount of calculation required when drawing. Chunks too large increase the amount of drawing that is needed.

`maxclusters` is the number of rectangular groups of chunks that will be separately drawn. If the QwSpriteField has a large number of small, dispersed graphics, this should be about that number. The more clusters the slower the redraw, but also the bigger clusters are the slower the redraw, so a balance is needed. Testing reveals that a large number of clusters is almost always best.

### QwSpriteField::~QwSpriteField () `[virtual]`

Destruct the field. Does nothing. Does not destroy QwSpriteFieldGraphic objects in the field.

### void QwSpriteField::addGraphic ( QwSpriteFieldGraphic * graphic )

(internal) This method adds an element to the list of QwSpriteFieldGraphic objects in this QwSpriteField. The QwSpriteFieldGraphic class calls this, so you should not need it.

### void QwSpriteField::addGraphicToChunk ( QwSpriteFieldGraphic * g, int x, int y )

This method adds a QwSpriteFieldGraphic to the list of those which need to be drawn if the given chunk is redrawn. Like SetChangedChunk and SetChangedChunkContaining, this method marks the chunk as `dirty'.

### void QwSpriteField::addGraphicToChunkContaining ( QwSpriteFieldGraphic * g, int x, int y )

This method adds a QwSpriteFieldGraphic to the list of those which need to be drawn if the chunk containing the given pixel is redrawn. Like SetChangedChunk and SetChangedChunkContaining, this method marks the chunk as `dirty'.

### void QwSpriteField::addView ( QwAbsSpriteFieldView * view )

For internal use only.

### Pix QwSpriteField::all ()

Provides for traversal of all QwSpriteFieldGraphic objects in the field, regardless of whether they are visible, on the field, or anything else. No particular ordering it given. You should iterate to the end of the list, or use end(Pix&).

### void* QwSpriteField::allList ()

Returns the sorted list of all graphics. You should not need this method - it is used internally for iteration.

See also: QwSpriteField::all().

### QwSpriteFieldGraphic* QwSpriteField::at ( Pix p ) const

Returns the QwSpriteFieldGraphic for a given point in a traversal.

See also: topAt(int,int) and lookIn(int,int,int,int).

### int QwSpriteField::chunkSize () const

Returns the chunk size of the sprite field as set at construction.

See also: QwSpriteField::QwSpriteField(...).

### void QwSpriteField::drawBackground ( QPainter & painter, const QRect & area ) `[virtual protected]`

This method is called for all updates of the QwSpriteField. It renders any background graphics. The default is to simply clear it in the background colour to the default painter background (white). You may also override this method to initialize the QPainter which will be passed to the draw method of all QwSpriteFieldGraphic objects.

Note that you should not put dynamic graphics on this background. If the graphics for a region change, call forceRedraw(const QRect&). Such a change should be done only very occasionally, as the redraw is inefficient. See the main notes for this class for a discussion of redraw efficiency.

See also: forceRedraw(QRect&).

### void QwSpriteField::drawForeground ( QPainter &, const QRect & ) `[virtual protected]`

This method is called for all updates of the QwSpriteField. It renders any foreground graphics. In general, it is more efficient to use additional QwSpriteFieldGraphic objects on the QwSpriteField rather than adding rendering at this point, as this method is always called, whereas QwSpriteFieldGraphic objects are only redrawn if they are in the area of change.

The same warnings regarding change apply to this method as given in drawBackground(QPainter&, const QRect&).

The default is to do nothing.

See also: forceRedraw(QRect&).

### void QwSpriteField::end ( Pix & p ) const

This should be called if you want to terminate a traversal without looking at all results. It frees memory used for the iteration.

### bool QwSpriteField::exact ( Pix p ) const

Test to see if the QwSpriteFieldGraphic which at(Pix) indicates is in a traversal truly is in that traversal.

The QwSpriteFieldGraphic returned by at(Pix) is very approximate, but is found very efficiently. It should be used as a first-cut to ignore QwSpriteFieldGraphic objects you are not interested in.

### void QwSpriteField::forceRedraw ( const QRect & area ) `[protected]`

Forces the given area to be redrawn. This is useful when the foreground or background are changed.

### int QwSpriteField::height () const

Returns the height of the sprite field, in world coordinates.

### void* QwSpriteField::listAtChunkTopFirst ( int i, int j ) const

Returns the sorted list of chunks at the given chunk. You should not need this method - it is used internally for collision detection.

See also: QwSpriteField::topAt(int,int).

### Pix QwSpriteField::lookIn ( int x, int y, int w, int h )

QwSpriteFieldGraphic objects in an area can be traversed using:

       for (Pix p=lookIn(x,y,w,h); p; next(p)) {
        QwSpriteFieldGraphic* the_graphic = at(p);
        ...
        }

This traverses at least all the graphics in the given rectangle at least once.

See also: topAt(int,int) and at(Pix).

### void QwSpriteField::next ( Pix & p ) const

Look to the next QwSpriteFieldGraphic in the traversal.

See also: topAt(int,int) and lookIn(int,int,int,int).

### int QwSpriteField::positionPrecision () `[static]`

Returns the position precision for all coordinates in the QwSpriteField.

See also: setPositionPrecision(int).

### void QwSpriteField::protectFromChange ( Pix p )

During the traversal, the QwSpriteField must not be modified. If you wish to modify it, call this method on the Pix. This will allow the QwSpriteField to be subsequently modified without damaging the list of hits.

### void QwSpriteField::removeGraphic ( QwSpriteFieldGraphic * graphic )

(internal) This method removes an element from the list of QwSpriteFieldGraphic objects in this QwSpriteField. The QwSpriteFieldGraphic class calls this, so you should not need it.

### void QwSpriteField::removeGraphicFromChunk ( QwSpriteFieldGraphic * g, int x, int y )

This method removes a QwSpriteFieldGraphic from the list of those which need to be drawn if the given chunk is redrawn. Like SetChangedChunk and SetChangedChunkContaining, this method marks the chunk as `dirty'.

### void QwSpriteField::removeGraphicFromChunkContaining ( QwSpriteFieldGraphic * g, int x, int y )

This method removes a QwSpriteFieldGraphic from the list of those which need to be drawn if the chunk containing the given pixel is redrawn. Like SetChangedChunk and SetChangedChunkContaining, this method marks the chunk as `dirty'.

### void QwSpriteField::removeView ( QwAbsSpriteFieldView * view )

For internal use only.

### void QwSpriteField::resize ( int w, int h ) `[virtual]`

Change the size of the QwSpriteField. This is a slow operation.

### void QwSpriteField::retune ( int chunksze, int mxclusters )

Change the efficiency tuning parameters. This is a slow operation.

### bool QwSpriteField::sameChunk ( int x1, int y1, int x2, int y2 ) const

Tells if the points (x1,y1) and (x2,y2) are within the same chunk.

### void QwSpriteField::setChangedChunk ( int x, int y )

This method to informs the QwSpriteField that a given chunk is `dirty' and needs to be redrawn in the next Update.

(x,y) is a chunk location.

The sprite classes call this. Any new derived class of QwSpriteFieldGraphic must do so too. SetChangedChunkContaining can be used instead.

### void QwSpriteField::setChangedChunkContaining ( int x, int y )

This method to informs the QwSpriteField that the chunk containing a given pixel is `dirty' and needs to be redrawn in the next Update.

(x,y) is a pixel location.

The sprite classes call this. Any new derived class of QwSpriteFieldGraphic must do so too. SetChangedChunk can be used instead.

### void QwSpriteField::setPositionPrecision ( int downshifts ) `[static]`

The precision of QwSpriteFieldGraphic positions (and collisions - see sprite) can be set. A positive precision means world co-ordinates will be bit-shifted that many places higher. So, if the precision is 1, world co-ordinate (50,100) is the pixel co-ordinate (25,50); for precision 3, (50,100) is pixel (6,12). Negative positions are also allowed, and they imply that world-coordinates are lower resolution than pixel co-ordinates. IF ANYONE FINDS A USE FOR NEGATIVES, LET ME KNOW, OR I MIGHT REMOVE IT.

By default, pixel and world coordinates are the same.

### Pix QwSpriteField::topAt ( int x, int y )

QwSpriteFieldGraphic objects at a point can be traversed from top to bottom using:

            for (Pix p=topAt(x,y); p; next(p)) {
            QwSpriteFieldGraphic* the_graphic = at(p);
            if (you_are_interested_in_collisions_with(the_graphic) && exact(p)) {
                    // Collision!
                    ...
                }
            }

This traverses at least all the graphics at pixel position (x,y).

The QwSpriteFieldGraphic returned by at(Pix) is very approximate, but is found very efficiently. It should be used as a first-cut to ignore QwSpriteFieldGraphic objects you are not interested in.

exact(Pix) should be used to further examine the QwSpriteFieldGraphic, as depicted above.

During the traversal, the QwSpriteField must not be modified unless protectFromChange(Pix) is first called on the iterator. This is for efficiency reasons (protecting the list of hits requires extra work).

Warning: Currently, the collision model is not quite correct at this level of abstraction, because it cannot check collision exactness beyond the rectangular level. This will change in futures versions. For now, you should perhaps use the QwVirtualSprite::neighbourhood(...) methods instead.

See also: QwSpriteFieldGraphic::rtti().

### void QwSpriteField::update ()

This method causes all QwAbsSpriteFieldView objects currently viewing this QwSpriteField to be refreshed in all areas of the QwSpriteField which have changed since the last call to this method.

In a continuously animated QwSpriteField, this method should be called at a regular rate. The best way to accomplish this is to use the QTimer class of the Qt toolkit, or the startTimer method of QObject. It would not be useful to call this method excessively (eg. whenever a sprite is moved) as the efficiency of the system is derived from a clustering and bulk-update mechanism.

Depending on how you use QwSpriteField and on the hardware, you may get improved smoothness by calling qApp->syncX() after this method.

### void QwSpriteField::updateInView ( QwAbsSpriteFieldView * view, const QRect & area )

For internal use only.

### int QwSpriteField::width () const

Returns the width of the sprite field, in world coordinates.

### int QwSpriteField::world_to_x ( int i ) `[static]`

Convert a coordinate from world to pixel coordinates.

See also: setPositionPrecision(int).

### int QwSpriteField::x_to_world ( int i ) `[static]`

Convert a coordinate from pixel to world coordinates.

See also: setPositionPrecision(int).

This file is copyright © 1995-97 Warwick Allison.

It was generated from the following files:

- QwSpriteField.h
- QwSpriteField-double.cpp
- QwSpriteField-int.cpp
- QwSpriteField-mobdouble.cpp
- QwSpriteField-mobint.cpp
- QwSpriteField-template.cpp
- QwSpriteField.cpp