zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
main.cpp
Go to the documentation of this file.
1 #include <zenilib.h>
2 
3 #include <jni.h>
4 #include <errno.h>
5 
6 #include <GLES/gl.h>
7 
8 #include <android/sensor.h>
10 
11 #include <android/window.h>
12 #include <cmath>
13 #include <utility>
14 
15 using namespace Zeni;
16 
20 struct engine {
21  struct android_app* app;
22 
23  ASensorManager* sensorManager;
24  const ASensor* accelerometerSensor;
25  ASensorEventQueue* sensorEventQueue;
26 };
27 
28 class Play_State : public Gamestate_Base {
29  Play_State(const Play_State &);
30  Play_State operator=(const Play_State &);
31 
32 public:
33  struct Saved_State {
34  Saved_State() {}
35  ~Saved_State() {}
36  public:
37  static Saved_State & get() {
38  static Saved_State ss;
39  return ss;
40  }
41 
42  Point2f position;
43  Vector2f velocity;
44  Vector3f acceleration;
45  };
46 
47  Play_State() {
48 #ifndef ANDROID
49  set_pausable(true);
50 #endif
51  }
52 
53 private:
54 #ifdef ANDROID
55  void on_event(android_app * const &app, const AInputEvent * const &event) {
56  }
57 #else
58  void on_push() {
59  get_Window().mouse_hide(true);
60  }
61 
62  void on_pop() {
63  get_Window().mouse_hide(false);
64  }
65 
66  void on_key(const SDL_KeyboardEvent &event) {
67  if(event.keysym.sym == SDLK_SPACE) {
68  if(event.state == SDL_PRESSED)
69  play_sound("hello_world");
70  }
71  else
73  }
74 #endif
75 
76  void prerender() {
77  if(!get_Textures().find("sson")) {
79  image.set_Color(Point2i(), Color(1.0f, 1.0f, 0.0f, 0.0f));
80  image.set_Color(Point2i(0, 1), Color(1.0f, 0.0f, 1.0f, 0.0f));
81  image.set_Color(Point2i(1, 0), Color(1.0f, 0.0f, 0.0f, 1.0f));
82  image.set_Color(Point2i(1, 1), Color());
83  get_Textures().give("sson", get_Video().create_Texture(image), false);
84  }
85 
86  if(!get_Textures().find("ssoff")) {
87  Image image(Point2i(2, 2), Image::Color_Space::Luminance, true);
88  image.set_Color(Point2i(), Color());
89  image.set_Color(Point2i(0, 1), Color(1.0f, 0.0f, 0.0f, 0.0f));
90  image.set_Color(Point2i(1, 0), Color(1.0f, 0.0f, 0.0f, 0.0f));
91  image.set_Color(Point2i(1, 1), Color());
92  get_Textures().give("ssoff", get_Video().create_Texture(image), false);
93  }
94  }
95 
96  void render() {
97  Window &wr = get_Window();
98 
99  glViewport(0, 0, wr.get_width(), wr.get_height());
100 
101  // Just fill the screen with a color.
103 
104 
105 
106  const float w = 600.0f * wr.get_width() / wr.get_height();
107 
108 // get_Video().set_2d(make_pair(Point2f(), Point2f(w, 600.0f)));
109 
111  glLoadIdentity();
112  glOrthof(0.0f, w, 600.0f, 0.0f, -1.0f, 1.0f);
113 
114  const float w2 = w / 2.0f;
115  const float h2 = 300.0f;
116 
117  for(int i = 0; i != 4; ++i) {
118  const float x = i & 1 ? w2 : 0.0f;
119  const float y = i / 2 ? h2 : 0.0f;
120 
122  Vertex2f_Texture v1(Point2f(x, y + h2), Point2f(0.0f, 1.0f));
123  Vertex2f_Texture v2(Point2f(x + w2, y + h2), Point2f(1.0f, 1.0f));
124  Vertex2f_Texture v3(Point2f(x + w2, y), Point2f(1.0f, 0.0f));
125 
127  Material mat("blarg");
128  quad.lend_Material(&mat);
129 
130  set_sprite_frame("blarg", i);
131  get_Video().render(quad);
132  }
133 
134 #ifdef ANDROID
135  {
136  const bool ss = get_Core().is_screen_saver_enabled();
137  const int x = int(Saved_State::get().position.x) & 0xFFFFFFFE;
138  const int y = int(Saved_State::get().position.y) & 0xFFFFFFFE;
139  const float tx = 0.05f * w;
140  const float ty = 0.05f * 600.0f;
141  const float w10 = w / 10.0f;
142 
144  Vertex2f_Texture v1(Point2f(x, y + 60.0f), Point2f(0.0f, ty));
145  Vertex2f_Texture v2(Point2f(x + w10, y + 60.0f), Point2f(tx, ty));
146  Vertex2f_Texture v3(Point2f(x + w10, y), Point2f(tx, 0.0f));
147 
149  Material mat(ss ? "sson" : "ssoff");
150  quad.lend_Material(&mat);
151 
152  get_Video().render(quad);
153  }
154 #endif
155 
156  get_Fonts()["system_36_x600"].render_text("Hello world!\nThis is\nthe event\nmankind\nhas been\nwaiting for.", Point2f(), Color(1.0f, 1.0f, 0.0f, 1.0f));
157 
158 
159 
160  eglSwapBuffers(get_Window().get_display(), get_Window().get_surface());
161  }
162 };
163 
164 class Bootstrap {
165  class Gamestate_One_Initializer : public Gamestate_Zero_Initializer {
166  virtual Gamestate_Base * operator()() {
167  return new Play_State;
168  }
169  } m_goi;
170 
171 public:
172  Bootstrap() {
173  g_gzi = &m_goi;
174  }
175 } g_bootstrap;
176 
180 static int engine_init_display(struct engine* engine) {
181  get_Window();
182 
183  // Initialize GL state.
188 
189  return 0;
190 }
191 
195 static void engine_draw_frame(struct engine* /*engine*/) {
197  if(Window::is_enabled()) {
198  Video &vr = get_Video();
199 
200  if(vr.begin_prerender()) {
201  get_Game().prerender();
202 
203  if(vr.begin_render()) {
204  try {
205  get_Game().render();
206  }
207  catch(...) {
208  vr.end_render();
209  throw;
210  }
211 
212  vr.end_render();
213  }
214  }
215  }
216 }
217 
221 static void engine_term_display(struct engine* engine) {
223 #ifndef TEMP_DISABLE
225 #endif
234  Joysticks::completely_destroy();
240 
241  Window::set_enabled(false);
242 }
243 
247 static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
248  switch (AInputEvent_getType(event)) {
249  case AINPUT_EVENT_TYPE_KEY:
250  switch(AKeyEvent_getKeyCode(event)) {
251  case AKEYCODE_MENU:
252  if(AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
253  get_Core().set_screen_saver(!get_Core().is_screen_saver_enabled());
254  else {
255  ZENI_LOGI("<audio>Hello World, ...</audio>");
256  play_sound("hello_world");
258  }
259  return 1;
260 
261  case AKEYCODE_BACK:
262  break;
263 
264  case AKEYCODE_SEARCH:
265  break;
266 
267  default:
268  break;
269  }
270  break;
271 
272  case AINPUT_EVENT_TYPE_MOTION:
273  Play_State::Saved_State::get().position.x = AMotionEvent_getX(event, 0);
274  Play_State::Saved_State::get().position.y = AMotionEvent_getY(event, 0);
275  Play_State::Saved_State::get().velocity.x = 0.0f;
276  Play_State::Saved_State::get().velocity.y = 0.0f;
277  return 1;
278 
279  default:
280  break;
281  }
282 
283  return 0;
284 }
285 
289 static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
290 #ifndef NDEBUG
291  return;
292 #endif
293 
294  struct engine* engine = (struct engine*)app->userData;
295  switch (cmd) {
296  case APP_CMD_INIT_WINDOW:
297  ZENI_LOGI("APP_CMD_INIT_WINDOW");
298  // The window is being shown, get it ready.
299  if (engine->app->window != NULL) {
300  engine_init_display(engine);
301  engine_draw_frame(engine);
302  }
303  break;
305  ZENI_LOGI("APP_CMD_GAINED_FOCUS");
306  // When our app gains focus, we start monitoring the accelerometer.
307  if(engine->accelerometerSensor) {
308  ASensorEventQueue_enableSensor(engine->sensorEventQueue,
309  engine->accelerometerSensor);
310  // We'd like to get 60 events per second (in us).
311  ASensorEventQueue_setEventRate(engine->sensorEventQueue,
312  engine->accelerometerSensor,
313  (1000L/60)*1000);
314  }
315  Window::set_enabled(true);
316  break;
317  case APP_CMD_LOST_FOCUS:
318  ZENI_LOGI("APP_CMD_LOST_FOCUS");
319  // When our app loses focus, we stop monitoring the accelerometer.
320  // This is to avoid consuming battery while not being used.
321  if(engine->accelerometerSensor) {
322  ASensorEventQueue_disableSensor(engine->sensorEventQueue,
323  engine->accelerometerSensor);
324  }
325  // Also stop animating.
326  Window::set_enabled(false);
327  break;
328  case APP_CMD_TERM_WINDOW:
329  ZENI_LOGI("APP_CMD_TERM_WINDOW");
330  // The window is being hidden or closed, clean it up.
331  engine_term_display(engine);
332  break;
333  case APP_CMD_SAVE_STATE:
334  // The system has asked us to save our current state. Do so.
335  ZENI_LOGI("APP_CMD_SAVE_STATE");
336  engine->app->savedStateSize = sizeof(Play_State::Saved_State);
337  engine->app->savedState = malloc(engine->app->savedStateSize);
338  *reinterpret_cast<Play_State::Saved_State *>(engine->app->savedState) = Play_State::Saved_State::get();
339  break;
340  }
341 }
342 
343 #ifndef NDEBUG
344 bool g_ndk = false;
345 #endif
346 
352 void android_main(struct android_app* state) {
353  // Make sure glue isn't stripped.
354  app_dummy();
355 
356 #ifndef NDEBUG
357  while(!g_ndk) {
358  // Read all pending events.
359  int ident;
360  int events;
361  struct android_poll_source* source;
362  while((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
363  if(source)
364  source->process(state, source);
365  }
366  }
368  raise(SIGINT);
369 #endif
370 
371  Core::preinit(state);
372 
373  struct engine engine;
374 
375  // Keep the screen on.
376  get_Core().set_screen_saver(false);
377 
378  memset(&engine, 0, sizeof(engine));
379  state->userData = &engine;
380  state->onAppCmd = engine_handle_cmd;
382  engine.app = state;
383 
384  // Prepare to monitor accelerometer
385  engine.sensorManager = ASensorManager_getInstance();
386  engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
387  ASENSOR_TYPE_ACCELEROMETER);
388  engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
389  state->looper,
391  NULL,
392  NULL);
393 
394  Play_State::Saved_State &saved_state = Play_State::Saved_State::get();
395  if(state->savedState) {
396  // We are starting with a previous saved state; restore from it.
397  saved_state = *reinterpret_cast<Play_State::Saved_State *>(state->savedState);
398  }
399 
400  // loop waiting for stuff to do.
401 
402  while (1) {
403  // Read all pending events.
404  int ident;
405  int events;
406  struct android_poll_source* source;
407 
408  // If not animating, we will block forever waiting for events.
409  // If animating, we loop until all events are read, then continue
410  // to draw the next frame of animation.
411  const int block = 0; // 0 == no, -1 == yes
412  while((ident=ALooper_pollAll(block, NULL, &events, (void**)&source)) >= 0)
413  {
414  // Process this event.
415  if (source != NULL) {
416  source->process(state, source);
417  }
418 
419  // If a sensor has data, process it now.
420  if (ident == LOOPER_ID_USER) {
421  if (engine.accelerometerSensor != NULL) {
422  ASensorEvent event;
423  while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
424  &event, 1) > 0) {
425  // LOGI("accelerometer: x=%f y=%f z=%f", event.acceleration.x, event.acceleration.y, event.acceleration.z);
426  saved_state.acceleration.x = event.acceleration.x;
427  saved_state.acceleration.y = event.acceleration.y;
428  saved_state.acceleration.z = event.acceleration.z;
429  }
430  }
431  }
432 
433  // Check if we are exiting.
434  if(state->destroyRequested) {
435  engine_term_display(&engine);
436  return;
437  }
438  }
439 
440  {
441  // Do updates
442  saved_state.velocity.x -= saved_state.acceleration.x;
443  saved_state.velocity.y += saved_state.acceleration.y;
444 
445  const float w10 = get_Window().get_width() / 10.0f;
446  const float h10 = get_Window().get_height() / 10.0f;
447 
448  const float v = saved_state.velocity.magnitude();
449 
450  const float mu0 = 1.5f;
451  const float mu = 0.5f;
452  const float mu_actual = v < 0.001f ? mu0 : mu;
453  const float n = mu_actual * saved_state.acceleration.z;
454 
455  if(v < n)
456  saved_state.velocity = Vector2f();
457  else if(n > 0.0f) {
458  const float fraction = 1.0f - n / v;
459  saved_state.velocity *= fraction;
460  }
461 
462  saved_state.position += saved_state.velocity;
463 
464  if(saved_state.position.x < 0.0f) {
465  saved_state.position.x = 0.0f;
466  saved_state.velocity.x = std::max(0.0f, saved_state.velocity.x);
467  }
468  else if(saved_state.position.x + w10 >= get_Window().get_width()) {
469  saved_state.position.x = get_Window().get_width() - w10;
470  saved_state.velocity.x = std::min(0.0f, saved_state.velocity.x);
471  }
472  if(saved_state.position.y < 0.0f) {
473  saved_state.position.y = 0.0f;
474  saved_state.velocity.y = std::max(0.0f, saved_state.velocity.y);
475  }
476  else if(saved_state.position.y + h10 >= get_Window().get_height()) {
477  saved_state.position.y = get_Window().get_height() - h10;
478  saved_state.velocity.y = std::min(0.0f, saved_state.velocity.y);
479  }
480 
481  // Drawing is throttled to the screen update rate, so there
482  // is no need to do timing here.
483  engine_draw_frame(&engine);
484  }
485  }
486 }
#define glHint
Definition: gl_mangle.h:918
#define glDisable
Definition: gl_mangle.h:393
void prerender()
Called in main, calls the function by the same name in the current Gamestate.
Definition: Game.cpp:235
Definition: edid.h:20
static const int & get_width()
Get the size of the window.
Definition: Window.hxx:33
GLfloat GLfloat v1
Definition: glew.h:1838
unsigned long give(const String &name, TYPE *const &type, const bool &keep, const String &filename="")
Add an entry (which it will later delete)
Definition: Database.hxx:91
#define GL_CULL_FACE
Definition: gl2.h:146
The Video Rendering Singleton.
Definition: Video.h:71
#define NULL
Definition: ftobjs.h:61
Sound_Source_Pool & get_Sound_Source_Pool()
Get access to the singleton.
GLclampf f
Definition: glew.h:3390
static const bool & is_enabled()
Determine whether the use of rendering is desired.
Definition: Window.hxx:25
GLclampd n
Definition: glew.h:7287
EGLSurface EGLint x
Definition: eglext.h:293
static void render(const Vertex_Buffer_Macrorenderer &macrorenderer, std::vector< Vertex_Buffer::Vertex_Buffer_Range * > &descriptors)
An Abstraction of a Material.
Definition: Material.h:56
static void engine_handle_cmd(struct android_app *app, int32_t cmd)
Definition: main.cpp:289
GLfloat GLfloat GLfloat GLfloat v3
Definition: glew.h:1846
#define memset
Definition: SDL_malloc.c:633
#define GL_FASTEST
Definition: gl2.h:228
An Abstraction of a Quadrilateral.
Definition: Quadrilateral.h:37
long int32_t
Definition: types.h:9
switch(yytype)
void(* onAppCmd)(struct android_app *app, int32_t cmd)
Game & get_Game()
Get access to the singleton.
Definition: Game.cpp:58
static int engine_init_display(struct engine *engine)
Definition: main.cpp:180
#define glLoadIdentity
Definition: gl_mangle.h:1003
Image.
Definition: Image.h:52
EGLImageKHR image
Definition: eglext.h:88
virtual void on_key(const SDL_KeyboardEvent &event)
Override this input callback in your Gamestates. See SDL documentation for details.
Definition: Gamestate.cpp:99
static void completely_destroy()
virtual bool begin_prerender()=0
Must be called before begin_render.
#define glClear
Definition: gl_mangle.h:170
#define GL_PERSPECTIVE_CORRECTION_HINT
Definition: glew_head.h:417
void update()
Redistribute hardware Sound_Sources according to the Replacement_Policy. Newer Sound_Sources are impl...
void app_dummy()
#define GL_COLOR_BUFFER_BIT
Definition: gl2.h:47
void android_main(struct android_app *state)
Definition: main.cpp:352
Keyboard button event structure (event.key.*)
Definition: SDL_events.h:176
A Featureful 3-Space Vector Class.
Definition: Vector3f.h:58
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: SDL_opengl.h:7828
const GLdouble * v
Definition: glew.h:1377
static void set_enabled(const bool &enabled)
Enable/Disable the use of rendering; This will not close the rendering window once it is open...
Definition: Window.cpp:396
int
Definition: SDL_systhread.c:37
#define glViewport
Definition: gl_mangle.h:2242
void set_screen_saver(const bool &enabled)
Enable/Disable the screen saver.
Definition: Core.cpp:99
class Bootstrap g_bootstrap
virtual void render(const Renderable &renderable)=0
Render a Renderable.
#define glShadeModel
Definition: gl_mangle.h:1626
#define glEnable
Definition: gl_mangle.h:441
GLfloat v0
Definition: glew.h:1834
bool is_screen_saver_enabled()
Check to see if the screen saver is enabled.
Definition: Core.cpp:85
static void engine_draw_frame(struct engine *)
Definition: main.cpp:195
SDL_Keysym keysym
Definition: SDL_events.h:185
#define glOrthof
Definition: glew.h:13861
Gamestate_Zero_Initializer * g_gzi
Definition: Game.cpp:31
GLbyte ty
Definition: SDL_opengl.h:8276
void render()
Called in main, calls the function by the same name in the current Gamestate.
Definition: Game.cpp:260
void(* process)(struct android_app *app, struct android_poll_source *source)
Textures & get_Textures()
Get access to the singleton.
Definition: Textures.cpp:64
bool g_ndk
Definition: main.cpp:344
Window & get_Window()
Get access to the singleton.
Definition: Window.cpp:392
EGLSurface EGLint EGLint y
Definition: eglext.h:293
#define malloc
Definition: SDL_malloc.c:635
double tx[3]
Definition: e_rem_pio2.c:97
An Abstraction of a Vertex in 2-space, textured.
Definition: Vertex2f.h:115
virtual bool begin_render()=0
Must be called before all rendering functions; Returns true if rendering can proceed.
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
void ZENI_LOGI(const Zeni::String &str)
Definition: Android.h:53
static int32_t engine_handle_input(struct android_app *app, AInputEvent *event)
Definition: main.cpp:247
#define GL_PROJECTION
Definition: glew_head.h:582
static const int & get_height()
Get the height of the window.
Definition: Window.hxx:37
The base class for all gamestates.
Definition: Gamestate.h:82
#define GL_SMOOTH
Definition: glew_head.h:606
#define glMatrixMode
Definition: gl_mangle.h:1053
Core & get_Core()
Get access to the singleton.
Definition: Core.cpp:71
SDL_Keycode sym
Definition: SDL_keyboard.h:50
int32_t(* onInputEvent)(struct android_app *app, AInputEvent *event)
static void engine_term_display(struct engine *engine)
Definition: main.cpp:221
GLint GLint GLint GLint GLint w
Definition: gl2ext.h:1215
virtual void end_render()=0
Must be called after all rendering functions.
Fonts & get_Fonts()
Get access to the singleton.
Definition: Fonts.cpp:60
Video & get_Video()
Get access to the singleton.
Definition: Video.cpp:149
#define min(x, y)
Definition: os.h:75
void set_sprite_frame(const String &sprite, const int &frame_number)
Definition: EZ2D.cpp:98
#define SDL_PRESSED
Definition: SDL_events.h:50
int i
Definition: pngrutil.c:1377
#define max(x, y)
Definition: os.h:79
A 2D Point represented with floats.
Definition: Coordinate.h:98
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:994
The Window Management Singleton.
Definition: Window.h:53
Color.
Definition: Color.h:41
GLfloat GLfloat GLfloat v2
Definition: glew.h:1842
void play_sound(const String &sound_name, const float &pitch, const float &gain, const Point3f &position, const Vector3f &velocity)
cl_event event
Definition: glew.h:3556
A 2-Space Vector Class.
Definition: Vector2f.h:41
#define GL_DEPTH_TEST
Definition: gl2.h:150
A 2D Point represented with integers.
Definition: Coordinate.h:85