Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1806 yogev_ezra 1
/*
2
------------------------------------------------------------
3
	Fixed Rate Pig - a fixed logic frame rate demo
4
------------------------------------------------------------
5
 * Copyright (C) 2004 David Olofson 
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 
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 */