Initial commit: basic port of SwarmDS.
[swarmPDK.git] / src / swarm.cpp
1 #include <stdio.h>
2 #include <math.h>
3
4 #include <GLES/gl.h>
5 #include "SDL.h"
6 #include "PDL.h"
7 #include "Pixel.h"
8 #define NPIXELS 2000
9
10 SDL_Surface* screen;               // Screen surface
11 Uint16 mx, my;
12 Pixel** pixels;
13 GLfloat* vertices;
14
15 #ifdef WIN32
16 extern "C" 
17 #endif
18 GL_API int GL_APIENTRY _dgles_load_library(void *, void *(*)(void *, const char *));
19
20 static void *proc_loader(void *h, const char *name)
21 {
22     (void) h;
23     return SDL_GL_GetProcAddress(name);
24 }
25
26 void init() {
27         // Set up OpenGL
28         glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
29         glMatrixMode(GL_PROJECTION);
30         glLoadIdentity();
31         glOrthof(0.0f, 320.0f, 400.0f, 0.0f, -1.0f, 1.0f);
32         glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
33
34         // Initialize vertices
35         vertices = new GLfloat[NPIXELS * 6];
36         memset(vertices, 0, sizeof(GLfloat) * NPIXELS * 6);
37         glEnableClientState(GL_VERTEX_ARRAY);
38         glVertexPointer(3, GL_FLOAT, 0, vertices);
39
40         // Center cursor
41         mx = 160;
42         my = 200;
43
44         // Initialize pixel objects
45         pixels = new Pixel*[NPIXELS];
46         for (int x = 0; x < NPIXELS; x++) {
47                 pixels[x] = new Pixel();
48         }
49
50 }
51
52 void pushPixels(int pushX, int pushY) {
53         // Apply force to each pixel outwards from the mouse
54         for (int i = 0; i < NPIXELS; i++) {
55                 // Get the direction
56                 float dx = pixels[i]->x - pushX;
57                 float dy = pixels[i]->y - pushY;
58                 float mag = sqrtf(dx*dx + dy*dy);
59                 dx /= mag;
60                 dy /= mag;
61
62                 // Apply force.
63                 pixels[i]->accel(dx * 10.0, dy * 10.0);
64         }
65 }
66
67 void engine() {
68         // Clear the canvas
69         glClear(GL_COLOR_BUFFER_BIT);
70
71         // Update cursor
72         vertices[0] = mx - 5;
73         vertices[1] = my - 5;
74         vertices[3] = mx + 5;
75         vertices[4] = my - 5;
76         vertices[6] = mx + 5;
77         vertices[7] = my + 5;
78         vertices[9] = mx - 5;
79         vertices[10] = my + 5;
80         glDrawArrays(GL_LINE_LOOP, 0, 4);
81
82         // Update all pixel objects
83         for (int i = 0; i < NPIXELS; i++) {
84                 // Get distance
85                 float dx = mx - pixels[i]->x;
86                 float dy = my - pixels[i]->y;
87                 float d = sqrtf(dx*dx + dy*dy);
88
89                 // Apply acceleration to pixels towards the mouse cursor
90                 float ax = dx / 50.0;
91                 float ay = dy / 50.0;
92
93                 // Apply a drag proportional to the distance from the cursor
94                 if (d > 25.0) {
95                         ax += -pixels[i]->vx * (d - 25.0) / 1000.0;
96                         ay += -pixels[i]->vy * (d - 25.0) / 1000.0;
97                 }
98
99                 // And a "chaotic" acceleration inversely proportional
100                 // to the distance from the cursor
101                 ax += ((rand() / (float)RAND_MAX) * 40.0 - 20.0) / d;
102                 ay += ((rand() / (float)RAND_MAX) * 40.0 - 20.0) / d;
103
104                 pixels[i]->accel(ax,ay);
105                 pixels[i]->update();
106                 pixels[i]->draw(&vertices[i*6]);
107         }
108         glDrawArrays(GL_LINES, 0, NPIXELS * 2);
109 }
110
111 int main(int argc, char** argv)
112 {
113     // Initialize the SDL library with the Video subsystem
114     SDL_Init(SDL_INIT_VIDEO);
115
116     // start the PDL library
117     PDL_Init(0);
118     
119     // Tell it to use OpenGL ES version 1.1
120     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
121
122     // Set the video mode to full screen with OpenGL-ES support
123     screen = SDL_SetVideoMode(320, 400, 0, SDL_OPENGL);
124     if (!screen) {
125                 printf("Could not initialize video!\n");
126                 exit(1);
127     }
128     printf("width: %d, height, %d\n", screen->w, screen->h);
129
130 #if WIN32
131     // Load the desktop OpenGL-ES emulation library
132     _dgles_load_library(NULL, proc_loader);
133 #endif
134
135         init();
136
137     // Event descriptor
138     SDL_Event Event;
139         int app_is_active = 1;
140         Uint32 last = SDL_GetTicks();
141         int fps_counter = 0;
142
143     do {
144         // Process the events
145                 if (!app_is_active)
146                         SDL_WaitEvent(NULL);
147         while (SDL_PollEvent(&Event)) {
148             switch (Event.type) {
149                 // List of keys that have been pressed
150                 case SDL_KEYDOWN:
151                     switch (Event.key.keysym.sym) {
152                         // Escape forces us to quit the app
153                         // this is also sent when the user makes a back gesture
154                         case SDLK_ESCAPE:
155                             Event.type = SDL_QUIT;
156                             break;
157                         default:
158                             break;
159                     }
160                     break;
161                                 case SDL_MOUSEMOTION:
162                                         mx = Event.motion.x;
163                                         my = Event.motion.y;
164                                         break;
165                                 case SDL_MOUSEBUTTONDOWN:
166                                         pushPixels(Event.button.x, Event.button.y);
167                                 case SDL_ACTIVEEVENT:
168                                         if (Event.active.state == SDL_APPACTIVE)
169                                                 app_is_active = Event.active.gain;
170                                         break;
171                 default:
172                     break;
173             }
174         }
175
176                 engine();
177                 glFlush();
178                 SDL_GL_SwapBuffers();
179
180                 // Calculate FPS
181                 fps_counter++;
182                 Uint32 now = SDL_GetTicks();
183                 if (now - last > 1000) {
184                         printf("%d FPS\n", fps_counter);
185                         fps_counter = 0;
186                         last = now;
187                 }
188     } while (Event.type != SDL_QUIT);
189     // We exit anytime we get a request to quit the app
190
191     // Cleanup
192     PDL_Quit();
193     SDL_Quit();
194
195     return 0;
196 }