// -*- C++ -*-
/* $Id: SpritePixel.h 1.1 1998/04/23 17:46:25 atterer Exp $
  __   _
  |_) /|  Copyright Richard Atterer
  | \/|  <atterer@informatik.tu-muenchen.de>
   ` 
  SpritePixel and SpritePixel{1,2,4,8,16,32}bpp classes.
  OSLib needed.

  Provides a type of "turtle" - an object which has x and y coordinates in
  a sprite and which can be moved by one pixel in either of the four
  directions (which can be done very fast) or set to definite x/y
  coordinates.
  SpritePixel objects work for sprites of any bpp; not implemented using an
  abstract class because then methods from SpritePixel4bpp:: couldn't be used
  on an object returned by SpritePixel()

  Only implemented for 4bpp ATM.

  $Log: SpritePixel.h $
  Revision 1.1  1998/04/23 17:46:25  atterer
  Initial revision

*/
#ifndef _SpritePixel_h
#define _SpritePixel_h
#ifndef _Sprite_h
#include "Sprite.h"
#endif

class SpritePixel4bpp;

class SpritePixel {
  friend class SpritePixel4bpp;
public:
  SpritePixel() { }; // Doesn't initialise *anything* yet!
  SpritePixel(const Sprite& spr, int x = 0, int y = 0);
  SpritePixel(const osspriteop_header& rawsprite, int x = 0, int y = 0);
  /* Mainly internal use: Initialise pointers to methods acc. to sprite's bpp
     Returns false if outside sprite */
  static bool init(SpritePixel&, int x = 0, int y = 0);
  int x() const { return xpos; }
  int y() const { return ypos; }
  int width() const { return xres + 1; }
  int height() const { return sprdata->height + 1; }
  /* Move to given x, y coordinates; returns false if outside sprite, but
     sets the data accordingly nevertheless, so it's OK e.g. to give coo. of
     (-1, 0) to move into the sprite during a subsequent right() */
  bool xy(int x = 0, int y = 0) { return (*boolxy)(this, x, y); }
  /* Move by one pixel. Returns contents of pixel (i.e. raw colour number)
     or -1 if the sprite has been left. NB once sprite *has* been left,
     return value is undefined when moving in directions other than the one
     in which it was left. However, the x/y coo. are maintained. */
  int  left() { return (*intleft) (this); }
  int right() { return (*intright)(this); }
  int    up() { return (*intup)   (this); }
  int  down() { return (*intdown) (this); }
  // Fast alternative, which doesn't return a value.
  void  fleft() { (*voidleft) (this); return; }
  void fright() { (*voidright)(this); return; }
  void    fup() { (*voidup)   (this); return; }
  void  fdown() { (*voiddown) (this); return; }
  // return pixel contents without moving
  int col() { return (*intcol)(this); }
protected:
  bool (*boolxy)(SpritePixel*, int, int);
  int (*intleft)(SpritePixel*);
  int (*intright)(SpritePixel*);
  int (*intup)(SpritePixel*);
  int (*intdown)(SpritePixel*);
  void (*voidleft)(SpritePixel*);
  void (*voidright)(SpritePixel*);
  void (*voidup)(SpritePixel*);
  void (*voiddown)(SpritePixel*);
  int (*intcol)(SpritePixel*);
  osspriteop_header* sprdata;
  word* pos; // in image data
  int xpos, ypos, xres; // xres is resolution - 1 (yres is sprdata->height)
};

class SpritePixel4bpp {
  friend class SpritePixel;
  static bool xy(SpritePixel*, int, int);
  static int left(SpritePixel*);
  static int right(SpritePixel*);
  static int up(SpritePixel*);
  static int down(SpritePixel*);
  static void fleft(SpritePixel*);
  static void fright(SpritePixel*);
  static void fup(SpritePixel*);
  static void fdown(SpritePixel*);
  static int col(SpritePixel*);
};

#endif
