Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2. ------------------------------------------------------------
  3.         Fixed Rate Pig - a fixed logic frame rate demo
  4. ------------------------------------------------------------
  5.  * Copyright (C) 2004 David Olofson <david@olofson.net>
  6.  *
  7.  * This software is released under the terms of the GPL.
  8.  *
  9.  * Contact author for permission if you want to use this
  10.  * software, or work derived from it, under other terms.
  11.  */
  12.  
  13. #ifndef PIG_ENGINE_H
  14. #define PIG_ENGINE_H
  15.  
  16. #include "SDL.h"
  17. #include <math.h>
  18. #ifndef M_PI
  19. #       define M_PI 3.14159265358979323846      /* pi */
  20. #endif
  21. #include "dirty.h"
  22.  
  23.  
  24. /*----------------------------------------------------------
  25.         Game Engine
  26. ----------------------------------------------------------*/
  27.  
  28. typedef struct PIG_object PIG_object;
  29. typedef struct PIG_engine PIG_engine;
  30.  
  31.  
  32. /* Interpolated point */
  33. typedef struct PIG_ipoint
  34. {
  35.         /* From the last logic frame: */
  36.         float   ox, oy;         /* Position */
  37.  
  38.         /* From the last/current rendered frame: */
  39.         int     gimage;         /* Sprite frame index */
  40.         float   gx, gy;         /* Interpolated position */
  41. } PIG_ipoint;
  42.  
  43.  
  44. /*
  45.  * Game logic events
  46.  *
  47.  * PREFRAME:
  48.  *      Occurs once per logic frame, before collision and
  49.  *      off-screen detection, and before timer handlers.
  50.  *
  51.  * TIMERx:
  52.  *      Occurs whenever timer x expires. Timers are one-
  53.  *      shot, but can be reloaded by the handler for
  54.  *      periodic action. Timer events are handled before
  55.  *      before collision and off-screen detection.
  56.  *
  57.  * HIT_TILE:
  58.  *      Occurs when the hot-spot of an object hits a
  59.  *      marked side of a tile, and the corresponding bit
  60.  *      in 'tilemask' is set.
  61.  *
  62.  * HIT_OBJECT:
  63.  *      Occurs when the collision circle of an object
  64.  *      intersects the collision circle of another object,
  65.  *      provided one or more bits in 'hitgroup' of the
  66.  *      other object matches bits in 'hitmask'.
  67.  *
  68.  * OFFSCREEN:
  69.  *      Occurs when an object is off-screen. This takes
  70.  *      in account the hot-spot and bounding rectangle of
  71.  *      the current sprite frame.
  72.  *
  73.  * POSTFRAME:
  74.  *      Occurs once per logic frame, after collision
  75.  *      detection, off-screen detection and all other
  76.  *      events.
  77.  *
  78.  */
  79. #define PIG_TIMERS      3
  80. typedef enum
  81. {
  82.         PIG_PREFRAME,
  83.         PIG_TIMER0,
  84.         PIG_TIMER1,
  85.         PIG_TIMER2,
  86.         PIG_HIT_TILE,
  87.         PIG_HIT_OBJECT,
  88.         PIG_OFFSCREEN,
  89.         PIG_POSTFRAME
  90. } PIG_events;
  91.  
  92.  
  93. typedef enum
  94. {
  95.         PIG_NONE =      0,
  96.  
  97.         /* Bit positions */
  98.         PIG_TOP_B =     0,
  99.         PIG_BOTTOM_B =  1,
  100.         PIG_LEFT_B =    2,
  101.         PIG_RIGHT_B =   3,
  102.  
  103.         /* Masks */
  104.         PIG_TOP =       1 << PIG_TOP_B,
  105.         PIG_BOTTOM =    1 << PIG_BOTTOM_B,
  106.         PIG_LEFT =      1 << PIG_LEFT_B,
  107.         PIG_RIGHT =     1 << PIG_RIGHT_B,
  108.  
  109.         /* Combined masks */
  110.         PIG_TL =        PIG_TOP | PIG_LEFT,
  111.         PIG_TR =        PIG_TOP | PIG_RIGHT,
  112.         PIG_BL =        PIG_BOTTOM | PIG_LEFT,
  113.         PIG_BR =        PIG_BOTTOM | PIG_RIGHT,
  114.         PIG_ALL =       0xf,
  115. } PIG_sides;
  116.  
  117.  
  118. typedef enum
  119. {
  120.         PIG_UNCHANGED = -10000000,
  121.         PIG_MIN =       -10000001,
  122.         PIG_CENTER =    -10000002,
  123.         PIG_MAX =       -10000003
  124. } PIG_values;
  125.  
  126.  
  127. /* Collision info */
  128. typedef struct
  129. {
  130.         float           ff;     /* Fractional frame */
  131.         int             x, y;   /* Exact position */
  132.         PIG_sides       sides;  /* Side of tile hit */
  133. } PIG_cinfo;
  134.  
  135.  
  136. typedef struct PIG_event
  137. {
  138.         PIG_events      type;
  139.  
  140.         /* For HIT_TILE, HIT_OBJECT and OFFSCREEN: */
  141.         PIG_cinfo       cinfo;  /* Detailed collision info */
  142.  
  143.         /* For HIT_OBJECT: */
  144.         PIG_object      *obj;   /* Which object? */
  145. }  PIG_event;
  146.  
  147.  
  148. /* Logic object */
  149. struct PIG_object
  150. {
  151.         PIG_engine      *owner;
  152.         PIG_object      *next, *prev;
  153.  
  154.         int             id;             /* Unique ID. 0 means "free". */
  155.  
  156.         int             ibase;          /* Sprite frame base index */
  157.         int             image;          /* Sprite frame offset */
  158.         float           x, y;           /* Position */
  159.         float           vx, vy;         /* Speed */
  160.         float           ax, ay;         /* Acceleration */
  161.         PIG_ipoint      ip;
  162.         int             tilemask;       /* Sprite/tile mask [PIG_ALL] */
  163.  
  164.         int             hitmask;        /* Sprite/sprite mask [0] */
  165.         int             hitgroup;       /* Sprite/sprite group [0] */
  166.  
  167.         int             timer[PIG_TIMERS];      /* Down-counting timers */
  168.         int             age;            /* Age timer (logic frames) */
  169.  
  170.         int             score;
  171.         int             power;
  172.         int             target;
  173.         int             state;
  174.  
  175.         void (*handler)(PIG_object *po, const PIG_event *ev);
  176.  
  177.         void            *userdata;
  178. };
  179.  
  180.  
  181. /* Level map */
  182. typedef struct PIG_map
  183. {
  184.         PIG_engine      *owner;
  185.  
  186.         int             w, h;           /* Size of map (tiles) */
  187.         unsigned char   *map;           /* 2D aray of tile indices */
  188.         unsigned char   *hit;           /* 2D aray of collision flags */
  189.  
  190.         int             tw, th;         /* Size of one tile (pixels) */
  191.         SDL_Surface     *tiles;         /* Tile palette image */
  192.         unsigned char   hitinfo[256];   /* Collision info for the tiles */
  193. } PIG_map;
  194.  
  195.  
  196. /* Sprite frame */
  197. typedef struct PIG_sprite
  198. {
  199.         int             w, h;           /* Size of sprite (pixels) */
  200.         int             hotx, hoty;     /* Hot-spot offset (pixels) */
  201.         int             radius;         /* Collision zone radius (pixels) */
  202.         SDL_Surface     *surface;
  203. } PIG_sprite;
  204.  
  205. /* Engine */
  206. struct PIG_engine
  207. {
  208.         /* Video stuff */
  209.         SDL_Surface     *screen;
  210.         SDL_Surface     *buffer;        /* For h/w surface displays */
  211.         SDL_Surface     *surface;       /* Where to render to */
  212.         int             pages;          /* # of display VRAM buffers */
  213.         SDL_Rect        view;           /* Viewport pos & size (pixels) */
  214.         int             page;           /* Current page (double buffer) */
  215.         PIG_dirtytable  *pagedirty[2];  /* One table for each page */
  216.         PIG_dirtytable  *workdirty;     /* The work dirtytable */
  217.  
  218.         /* "Live" switches */
  219.         int             interpolation;
  220.         int             direct;         /* 1 ==> render directly to screen */
  221.         int             show_dirtyrects;
  222.  
  223.         /* Time */
  224.         double          time;           /* Logic time (frames) */
  225.         int             frame;          /* Logic time; integer part */
  226.  
  227.         /* Background graphics */
  228.         PIG_map         *map;
  229.  
  230.         /* Sprites and stuff */
  231.         PIG_object      *objects;
  232.         PIG_object      *object_pool;
  233.         int             object_id_counter;
  234.         int             nsprites;
  235.         PIG_sprite      **sprites;
  236.  
  237.         /* Logic frame global handlers */
  238.         void (*before_objects)(PIG_engine *pe);
  239.         void (*after_objects)(PIG_engine *pe);
  240.  
  241.         /* Space for user data */
  242.         void            *userdata;
  243. };
  244.  
  245.  
  246. /*
  247.  * Engine
  248.  */
  249. PIG_engine *pig_open(SDL_Surface *screen);
  250. void pig_close(PIG_engine *pe);
  251.  
  252. /* Set viewport size and position */
  253. void pig_viewport(PIG_engine *pe, int x, int y, int w, int h);
  254.  
  255. /* Start engine at logic time 'frame' */
  256. void pig_start(PIG_engine *pe, int frame);
  257.  
  258. /*
  259.  * Load a sprite palette image. The image is chopped up into
  260.  * sprites, based on 'sw' and 'sh', and added as new frames
  261.  * in the sprite bank. Default values:
  262.  *      Hot-spot:               (sw/2, sh/2)
  263.  *      Collision radius:       0.2 * (sw + sh)
  264.  *
  265.  * Passing 0 for 'sw' and/or 'sh' makes pig_sprites() take
  266.  * the respective value from the image width and/or height.
  267.  *
  268.  * Returns the index of the first frame loaded.
  269.  */
  270. int pig_sprites(PIG_engine *pe, const char *filename, int sw, int sh);
  271.  
  272. /* Set hot-spot of sprite 'frame' to (hotx, hoty) */
  273. int pig_hotspot(PIG_engine *pe, int frame, int hotx, int hoty);
  274.  
  275. /* Set sprite/sprite collision zone radius of 'frame' */
  276. int pig_radius(PIG_engine *pe, int frame, int radius);
  277.  
  278. /* Advance logic time by 'frames' logic frames */
  279. void pig_animate(PIG_engine *pe, float frames);
  280.  
  281. /*
  282.  * Manually add a dirtyrect for pig_refresh().
  283.  * 'dr' can be outside the engine viewport.
  284.  */
  285. void pig_dirty(PIG_engine *pe, SDL_Rect *dr);
  286.  
  287. /*
  288.  * Do what's needed to deal with the dirtyrects
  289.  * and then make the new frame visible.
  290.  */
  291. void pig_flip(PIG_engine *pe);
  292.  
  293. /*
  294.  * Refresh the viewport and any additional dirtyrects.
  295.  *
  296.  * Note that this does not refresh the entire viewport;
  297.  * only the areas that have actually changed!
  298.  */
  299. void pig_refresh(PIG_engine *pe);
  300.  
  301. /*
  302.  * Refresh the whole viewport, including sprites.
  303.  */
  304. void pig_refresh_all(PIG_engine *pe);
  305.  
  306. /* Render a sprite "manually", bypassing the engine */
  307. void pig_draw_sprite(PIG_engine *pe, int frame, int x, int y);
  308.  
  309. /*
  310.  * Get the collision flags for the tile at (x, y),
  311.  * where the unit of x and y is pixels. The return
  312.  * is the PIG_sides flags for the tile, or PIG_NONE
  313.  * if (x, y) is outside the map.
  314.  */
  315. int pig_test_map(PIG_engine *pe, int x, int y);
  316.  
  317. /*
  318.  * Find the first "collidable" tile side when going from
  319.  * (x1, y1) to (x2, y2). 'mask' determines which tile sides
  320.  * are considered for collisions.
  321.  *
  322.  * Returns the side(s) hit, if any tile was hit. If the return
  323.  * is non-zero, the PIG_cinfo struct at 'ci' contains detailed
  324.  * information about the collision.
  325.  */
  326. int pig_test_map_vector(PIG_engine *pe, int x1, int y1, int x2, int y2,
  327.                 int mask, PIG_cinfo *ci);
  328.  
  329.  
  330. /*
  331.  * Map
  332.  */
  333. PIG_map *pig_map_open(PIG_engine *pe, int w, int h);
  334. void pig_map_close(PIG_map *pm);
  335.  
  336. /* Load a tile palette image */
  337. int pig_map_tiles(PIG_map *pm, const char *filename, int tw, int th);
  338.  
  339. /*
  340.  * Set tile collision info for 'count' tiles, starting at
  341.  * 'first'. Each tile in the tile palette has a set of
  342.  * PIG_sides flags that determine which sides the tile are
  343.  * considered for sprite/map collisions.
  344.  */
  345. void pig_map_collisions(PIG_map *pm, unsigned first, unsigned count,
  346.                 PIG_sides sides);
  347.  
  348. /*
  349.  * Load a map from a string (one byte/tile). 'trans'
  350.  * is a string used for translating 'data' into integer
  351.  * tile indices. Each position in 'trans' corresponds
  352.  * to one tile in the tile palette.
  353.  */
  354. int pig_map_from_string(PIG_map *pm, const char *trans, const char *data);
  355.  
  356.  
  357. /*
  358.  * Object
  359.  */
  360.  
  361. /*
  362.  * Create an object with the initial position (x, y). If
  363.  * 'last' is 1, the object will end up last in the
  364.  * processing and rendering order, otherwise, first.
  365.  *
  366.  * Note that relative processing order is very important
  367.  * to objects that chase each other and stuff like that!
  368.  * If they're placed in the "wrong" order, the tracking
  369.  * objects get an extra frame of reaction time, which is
  370.  * annoying if it's not what you intend.
  371.  */
  372. PIG_object *pig_object_open(PIG_engine *pe, int x, int y, int last);
  373.  
  374. /*
  375.  * Delete an object.
  376.  *
  377.  * Note that objects are never actually deleted. Instead,
  378.  * they are placed in a free pool, where pig_object_open()
  379.  * looks for objects to recycle.
  380.  *
  381.  * In fact, they are not even freed when you ask for it,
  382.  * but rather kept around until the next rendered frame,
  383.  * so they can be removed from the screen correctly.
  384.  */
  385. void pig_object_close(PIG_object *po);
  386.  
  387. /*
  388.  * Close all objects.
  389.  */
  390. void pig_object_close_all(PIG_engine *pe);
  391.  
  392. /*
  393.  * Find object by 'id', starting at object 'start'.
  394.  *
  395.  * The search starts at 'start' and is done in both
  396.  * directions in parallel, assuming that the matching
  397.  * object is near 'start' in the list. (It usually is
  398.  * when dealing with linked objects.)
  399.  *
  400.  * Returns NULL if the object was not found.
  401.  */
  402. PIG_object *pig_object_find(PIG_object *start, int id);
  403.  
  404. #endif  /* PIG_ENGINE_H */
  405.