1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#ifndef __SCENE_H__
#define __SCENE_H__
#include "body.h"
#include "list.h"
/**
* A collection of bodies and force creators.
* The scene automatically resizes to store
* arbitrarily many bodies and force creators.
*/
typedef struct scene scene_t;
/**
* A function which adds some forces or impulses to bodies,
* e.g. from collisions, gravity, or spring forces.
* Takes in an auxiliary value that can store parameters or state.
*/
typedef void (*force_creator_t)(void *aux);
/**
* Allocates memory for an empty scene.
* Makes a reasonable guess of the number of bodies to allocate space for.
* Asserts that the required memory is successfully allocated.
*
* @return the new scene
*/
scene_t *scene_init(void);
/**
* Releases memory allocated for a given scene
* and all the bodies and force creators it contains.
*
* @param scene a pointer to a scene returned from scene_init()
*/
void scene_free(scene_t *scene);
/**
* Gets the number of bodies in a given scene.
*
* @param scene a pointer to a scene returned from scene_init()
* @return the number of bodies added with scene_add_body()
*/
size_t scene_bodies(scene_t *scene);
/**
* Gets the body at a given index in a scene.
* Asserts that the index is valid.
*
* @param scene a pointer to a scene returned from scene_init()
* @param index the index of the body in the scene (starting at 0)
* @return a pointer to the body at the given index
*/
body_t *scene_get_body(scene_t *scene, size_t index);
/**
* Adds a body to a scene.
*
* @param scene a pointer to a scene returned from scene_init()
* @param body a pointer to the body to add to the scene
*/
void scene_add_body(scene_t *scene, body_t *body);
/**
* @deprecated Use body_remove() instead
*
* Removes and frees the body at a given index from a scene.
* Asserts that the index is valid.
*
* @param scene a pointer to a scene returned from scene_init()
* @param index the index of the body in the scene (starting at 0)
*/
void scene_remove_body(scene_t *scene, size_t index);
/**
* @deprecated Use scene_add_bodies_force_creator() instead
* so the scene knows which bodies the force creator depends on
*/
void scene_add_force_creator(
scene_t *scene,
force_creator_t forcer,
void *aux,
free_func_t freer
);
/**
* Adds a force creator to a scene,
* to be invoked every time scene_tick() is called.
* The auxiliary value is passed to the force creator each time it is called.
* The force creator is registered with a list of bodies it applies to,
* so it can be removed when any one of the bodies is removed.
*
* @param scene a pointer to a scene returned from scene_init()
* @param forcer a force creator function
* @param aux an auxiliary value to pass to forcer when it is called
* @param bodies the list of bodies affected by the force creator.
* The force creator will be removed if any of these bodies are removed.
* This list does not own the bodies, so its freer should be NULL.
* @param freer if non-NULL, a function to call in order to free aux
*/
void scene_add_bodies_force_creator(
scene_t *scene,
force_creator_t forcer,
void *aux,
list_t *bodies,
free_func_t freer
);
/**
* Executes a tick of a given scene over a small time interval.
* This requires executing all the force creators
* and then ticking each body (see body_tick()).
* If any bodies are marked for removal, they should be removed from the scene
* and freed, along with any force creators acting on them.
*
* @param scene a pointer to a scene returned from scene_init()
* @param dt the time elapsed since the last tick, in seconds
*/
void scene_tick(scene_t *scene, double dt);
#endif // #ifndef __SCENE_H__