60 |
60 |
61 /** |
61 /** |
62 SDL Activity |
62 SDL Activity |
63 */ |
63 */ |
64 public class SDLActivity extends Activity { |
64 public class SDLActivity extends Activity { |
65 /** |
65 /** |
66 * Set startConfig to the desired config when starting this activity. This avoids having to parcel all |
66 * Set startConfig to the desired config when starting this activity. This avoids having to parcel all |
67 * the config objects into the Intent. Not particularly elegant, but it's actually a recommended |
67 * the config objects into the Intent. Not particularly elegant, but it's actually a recommended |
68 * way to do this (http://developer.android.com/guide/faq/framework.html#3) |
68 * way to do this (http://developer.android.com/guide/faq/framework.html#3) |
69 */ |
69 */ |
70 public static volatile GameConfig startConfig; |
70 public static volatile GameConfig startConfig; |
71 public static volatile boolean startNetgame; |
71 public static volatile boolean startNetgame; |
72 |
72 |
73 // Main components |
73 // Main components |
74 public static SDLActivity mSingleton; |
74 public static SDLActivity mSingleton; |
75 private static SDLSurface mSurface; |
75 private static SDLSurface mSurface; |
76 private static Thread mSDLThread; |
76 private static Thread mSDLThread; |
77 |
77 |
78 // Audio |
78 // Audio |
79 private static Thread mAudioThread; |
79 private static Thread mAudioThread; |
80 private static AudioTrack mAudioTrack; |
80 private static AudioTrack mAudioTrack; |
81 |
81 |
82 // EGL private objects |
82 // EGL private objects |
83 private static EGLContext mEGLContext; |
83 private static EGLContext mEGLContext; |
84 private static EGLSurface mEGLSurface; |
84 private static EGLSurface mEGLSurface; |
85 private static EGLDisplay mEGLDisplay; |
85 private static EGLDisplay mEGLDisplay; |
86 private static EGLConfig mEGLConfig; |
86 private static EGLConfig mEGLConfig; |
87 private static int mGLMajor, mGLMinor; |
87 private static int mGLMajor, mGLMinor; |
88 |
88 |
89 // Load the .so |
89 // Load the .so |
90 static { |
90 static { |
91 System.loadLibrary("SDL"); |
91 System.loadLibrary("SDL"); |
92 System.loadLibrary("main"); |
92 System.loadLibrary("main"); |
93 } |
93 } |
94 |
94 |
95 // Setup |
95 // Setup |
96 protected void onCreate(Bundle savedInstanceState) { |
96 protected void onCreate(Bundle savedInstanceState) { |
97 super.onCreate(savedInstanceState); |
97 super.onCreate(savedInstanceState); |
98 |
98 |
99 // So we can call stuff from static callbacks |
99 // So we can call stuff from static callbacks |
100 mSingleton = this; |
100 mSingleton = this; |
101 |
101 |
102 // Set up the surface |
102 // Set up the surface |
103 mSurface = new SDLSurface(getApplication(), startConfig, startNetgame); |
103 mSurface = new SDLSurface(getApplication(), startConfig, startNetgame); |
104 startConfig = null; |
104 startConfig = null; |
105 setContentView(mSurface); |
105 setContentView(mSurface); |
106 } |
106 } |
107 |
107 |
108 // Events |
108 // Events |
109 protected void onPause() { |
109 protected void onPause() { |
110 Log.v("SDL", "onPause()"); |
110 Log.v("SDL", "onPause()"); |
111 super.onPause(); |
111 super.onPause(); |
112 |
112 |
113 if(mEGLDisplay != null && mEGLContext != null){ |
113 if(mEGLDisplay != null && mEGLContext != null){ |
114 EGL10 egl = (EGL10)EGLContext.getEGL(); |
114 EGL10 egl = (EGL10)EGLContext.getEGL(); |
115 egl.eglDestroyContext(mEGLDisplay, mEGLContext); |
115 egl.eglDestroyContext(mEGLDisplay, mEGLContext); |
116 mEGLDisplay = null; |
116 mEGLDisplay = null; |
117 mEGLContext = null; |
117 mEGLContext = null; |
118 } |
118 } |
119 |
119 |
120 SDLActivity.nativePause(); |
120 SDLActivity.nativePause(); |
121 } |
121 } |
122 |
122 |
123 protected void onResume() { |
123 protected void onResume() { |
124 Log.v("SDL", "onResume()"); |
124 Log.v("SDL", "onResume()"); |
125 super.onResume(); |
125 super.onResume(); |
126 } |
126 } |
127 |
127 |
128 protected void onDestroy() { |
128 protected void onDestroy() { |
129 super.onDestroy(); |
129 super.onDestroy(); |
130 Log.v("SDL", "onDestroy()"); |
130 Log.v("SDL", "onDestroy()"); |
131 // Send a quit message to the application |
131 // Send a quit message to the application |
132 SDLActivity.nativeQuit(); |
132 SDLActivity.nativeQuit(); |
133 // Now wait for the SDL thread to quit |
133 // Now wait for the SDL thread to quit |
134 if (mSDLThread != null) { |
134 if (mSDLThread != null) { |
135 try { |
135 try { |
136 mSDLThread.join(); |
136 mSDLThread.join(); |
137 } catch(Exception e) { |
137 } catch(Exception e) { |
138 Log.w("SDL", "Problem stopping thread: " + e); |
138 Log.w("SDL", "Problem stopping thread: " + e); |
139 } |
139 } |
140 mSDLThread = null; |
140 mSDLThread = null; |
141 } |
141 } |
142 mSingleton = null; |
142 mSingleton = null; |
143 } |
143 } |
144 |
144 |
145 public static void synchronizedNativeInit(String...args) { |
145 public static void synchronizedNativeInit(String...args) { |
146 synchronized(PascalExports.engineMutex) { |
146 synchronized(PascalExports.engineMutex) { |
147 nativeInit(args); |
147 nativeInit(args); |
148 } |
148 } |
149 } |
149 } |
150 |
150 |
151 // C functions we call |
151 // C functions we call |
152 private static native void nativeInit(String...args); |
152 private static native void nativeInit(String...args); |
153 public static native void nativeQuit(); |
153 public static native void nativeQuit(); |
154 public static native void nativePause(); |
154 public static native void nativePause(); |
155 public static native void nativeResume(); |
155 public static native void nativeResume(); |
156 public static native void onNativeResize(int x, int y, int format); |
156 public static native void onNativeResize(int x, int y, int format); |
157 public static native void onNativeKeyDown(int keycode); |
157 public static native void onNativeKeyDown(int keycode); |
158 public static native void onNativeKeyUp(int keycode); |
158 public static native void onNativeKeyUp(int keycode); |
159 public static native void onNativeTouch(int touchDevId, int pointerFingerId, |
159 public static native void onNativeTouch(int touchDevId, int pointerFingerId, |
160 int action, float x, |
160 int action, float x, |
161 float y, float p); |
161 float y, float p); |
162 public static native void onNativeAccel(float x, float y, float z); |
162 public static native void onNativeAccel(float x, float y, float z); |
163 public static native void nativeRunAudioThread(); |
163 public static native void nativeRunAudioThread(); |
164 |
164 |
165 |
165 |
166 // Java functions called from C |
166 // Java functions called from C |
167 |
167 |
168 public static boolean createGLContext(int majorVersion, int minorVersion) { |
168 public static boolean createGLContext(int majorVersion, int minorVersion) { |
169 return initEGL(majorVersion, minorVersion); |
169 return initEGL(majorVersion, minorVersion); |
170 } |
170 } |
171 |
171 |
172 public static void flipBuffers() { |
172 public static void flipBuffers() { |
173 flipEGL(); |
173 flipEGL(); |
174 } |
174 } |
175 |
175 |
176 public static void setActivityTitle(final String title) { |
176 public static void setActivityTitle(final String title) { |
177 // Called from SDLMain() thread and can't directly affect the view |
177 // Called from SDLMain() thread and can't directly affect the view |
178 mSingleton.runOnUiThread(new Runnable() { |
178 mSingleton.runOnUiThread(new Runnable() { |
179 public void run() { |
179 public void run() { |
180 mSingleton.setTitle(title); |
180 mSingleton.setTitle(title); |
181 } |
181 } |
182 }); |
182 }); |
183 } |
183 } |
184 |
184 |
185 public static Context getContext() { |
185 public static Context getContext() { |
186 return mSingleton; |
186 return mSingleton; |
187 } |
187 } |
188 |
188 |
189 public static void startApp(final int width, final int height, GameConfig config, boolean netgame) { |
189 public static void startApp(final int width, final int height, GameConfig config, boolean netgame) { |
190 // Start up the C app thread |
190 // Start up the C app thread |
191 if (mSDLThread == null) { |
191 if (mSDLThread == null) { |
192 mSDLThread = new Thread(new SDLMain(width, height, config, netgame)); |
192 mSDLThread = new Thread(new SDLMain(width, height, config, netgame)); |
193 mSDLThread.start(); |
193 mSDLThread.start(); |
194 } else { |
194 } else { |
195 SDLActivity.nativeResume(); |
195 SDLActivity.nativeResume(); |
196 } |
196 } |
197 } |
197 } |
198 |
198 |
199 // EGL functions |
199 // EGL functions |
200 public static boolean initEGL(int majorVersion, int minorVersion) { |
200 public static boolean initEGL(int majorVersion, int minorVersion) { |
201 if (SDLActivity.mEGLDisplay == null) { |
201 if (SDLActivity.mEGLDisplay == null) { |
202 try { |
202 try { |
203 EGL10 egl = (EGL10)EGLContext.getEGL(); |
203 EGL10 egl = (EGL10)EGLContext.getEGL(); |
204 |
204 |
205 EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); |
205 EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); |
206 |
206 |
207 int[] version = new int[2]; |
207 int[] version = new int[2]; |
208 egl.eglInitialize(dpy, version); |
208 egl.eglInitialize(dpy, version); |
209 |
209 |
210 int EGL_OPENGL_ES_BIT = 1; |
210 int EGL_OPENGL_ES_BIT = 1; |
211 int EGL_OPENGL_ES2_BIT = 4; |
211 int EGL_OPENGL_ES2_BIT = 4; |
212 int renderableType = 0; |
212 int renderableType = 0; |
213 if (majorVersion == 2) { |
213 if (majorVersion == 2) { |
214 renderableType = EGL_OPENGL_ES2_BIT; |
214 renderableType = EGL_OPENGL_ES2_BIT; |
215 } else if (majorVersion == 1) { |
215 } else if (majorVersion == 1) { |
216 renderableType = EGL_OPENGL_ES_BIT; |
216 renderableType = EGL_OPENGL_ES_BIT; |
217 } |
217 } |
218 int[] configSpec = { |
218 int[] configSpec = { |
219 EGL10.EGL_RENDERABLE_TYPE, renderableType, |
219 EGL10.EGL_RENDERABLE_TYPE, renderableType, |
220 EGL10.EGL_NONE |
220 EGL10.EGL_NONE |
221 }; |
221 }; |
222 EGLConfig[] configs = new EGLConfig[1]; |
222 EGLConfig[] configs = new EGLConfig[1]; |
223 int[] num_config = new int[1]; |
223 int[] num_config = new int[1]; |
224 if (!egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config) || num_config[0] == 0) { |
224 if (!egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config) || num_config[0] == 0) { |
225 Log.e("SDL", "No EGL config available"); |
225 Log.e("SDL", "No EGL config available"); |
226 return false; |
226 return false; |
227 } |
227 } |
228 EGLConfig config = configs[0]; |
228 EGLConfig config = configs[0]; |
229 |
229 |
230 SDLActivity.mEGLDisplay = dpy; |
230 SDLActivity.mEGLDisplay = dpy; |
231 SDLActivity.mEGLConfig = config; |
231 SDLActivity.mEGLConfig = config; |
232 SDLActivity.mGLMajor = majorVersion; |
232 SDLActivity.mGLMajor = majorVersion; |
233 SDLActivity.mGLMinor = minorVersion; |
233 SDLActivity.mGLMinor = minorVersion; |
234 |
234 |
235 SDLActivity.createEGLSurface(); |
235 SDLActivity.createEGLSurface(); |
236 } catch(Exception e) { |
236 } catch(Exception e) { |
237 Log.v("SDL", e + ""); |
237 Log.v("SDL", e + ""); |
238 for (StackTraceElement s : e.getStackTrace()) { |
238 for (StackTraceElement s : e.getStackTrace()) { |
239 Log.v("SDL", s.toString()); |
239 Log.v("SDL", s.toString()); |
240 } |
240 } |
241 } |
241 } |
242 } |
242 } |
243 else SDLActivity.createEGLSurface(); |
243 else SDLActivity.createEGLSurface(); |
244 |
244 |
245 return true; |
245 return true; |
246 } |
246 } |
247 |
247 |
248 public static boolean createEGLContext() { |
248 public static boolean createEGLContext() { |
249 EGL10 egl = (EGL10)EGLContext.getEGL(); |
249 EGL10 egl = (EGL10)EGLContext.getEGL(); |
250 int EGL_CONTEXT_CLIENT_VERSION=0x3098; |
250 int EGL_CONTEXT_CLIENT_VERSION=0x3098; |
251 int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE }; |
251 int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE }; |
252 SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs); |
252 SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs); |
253 if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) { |
253 if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) { |
254 Log.e("SDL", "Couldn't create context"); |
254 Log.e("SDL", "Couldn't create context"); |
255 return false; |
255 return false; |
256 } |
256 } |
257 return true; |
257 return true; |
258 } |
258 } |
259 |
259 |
260 public static boolean createEGLSurface() { |
260 public static boolean createEGLSurface() { |
261 if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) { |
261 if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) { |
262 EGL10 egl = (EGL10)EGLContext.getEGL(); |
262 EGL10 egl = (EGL10)EGLContext.getEGL(); |
263 if (SDLActivity.mEGLContext == null) createEGLContext(); |
263 if (SDLActivity.mEGLContext == null) createEGLContext(); |
264 |
264 |
265 Log.v("SDL", "Creating new EGL Surface"); |
265 Log.v("SDL", "Creating new EGL Surface"); |
266 EGLSurface surface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null); |
266 EGLSurface surface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null); |
267 if (surface == EGL10.EGL_NO_SURFACE) { |
267 if (surface == EGL10.EGL_NO_SURFACE) { |
268 Log.e("SDL", "Couldn't create surface"); |
268 Log.e("SDL", "Couldn't create surface"); |
269 return false; |
269 return false; |
270 } |
270 } |
271 |
271 |
272 if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { |
272 if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { |
273 Log.e("SDL", "Old EGL Context doesnt work, trying with a new one"); |
273 Log.e("SDL", "Old EGL Context doesnt work, trying with a new one"); |
274 createEGLContext(); |
274 createEGLContext(); |
275 if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { |
275 if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, surface, surface, SDLActivity.mEGLContext)) { |
276 Log.e("SDL", "Failed making EGL Context current"); |
276 Log.e("SDL", "Failed making EGL Context current"); |
277 return false; |
277 return false; |
278 } |
278 } |
279 } |
279 } |
280 SDLActivity.mEGLSurface = surface; |
280 SDLActivity.mEGLSurface = surface; |
281 return true; |
281 return true; |
282 } |
282 } |
283 return false; |
283 return false; |
284 } |
284 } |
285 |
285 |
286 // EGL buffer flip |
286 // EGL buffer flip |
287 public static void flipEGL() { |
287 public static void flipEGL() { |
288 try { |
288 try { |
289 EGL10 egl = (EGL10)EGLContext.getEGL(); |
289 EGL10 egl = (EGL10)EGLContext.getEGL(); |
290 |
290 |
291 egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null); |
291 egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null); |
292 |
292 |
293 // drawing here |
293 // drawing here |
294 |
294 |
295 egl.eglWaitGL(); |
295 egl.eglWaitGL(); |
296 |
296 |
297 egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface); |
297 egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface); |
298 |
298 |
299 |
299 |
300 } catch(Exception e) { |
300 } catch(Exception e) { |
301 Log.v("SDL", "flipEGL(): " + e); |
301 Log.v("SDL", "flipEGL(): " + e); |
302 for (StackTraceElement s : e.getStackTrace()) { |
302 for (StackTraceElement s : e.getStackTrace()) { |
303 Log.v("SDL", s.toString()); |
303 Log.v("SDL", s.toString()); |
304 } |
304 } |
305 } |
305 } |
306 } |
306 } |
307 |
307 |
308 // Audio |
308 // Audio |
309 private static Object buf; |
309 private static Object buf; |
310 |
310 |
311 public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) { |
311 public static Object audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) { |
312 int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO; |
312 int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO; |
313 int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT; |
313 int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT; |
314 int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1); |
314 int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1); |
315 |
315 |
316 Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); |
316 Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + ((float)sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer"); |
317 |
317 |
318 // Let the user pick a larger buffer if they really want -- but ye |
318 // Let the user pick a larger buffer if they really want -- but ye |
319 // gods they probably shouldn't, the minimums are horrifyingly high |
319 // gods they probably shouldn't, the minimums are horrifyingly high |
320 // latency already |
320 // latency already |
321 desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); |
321 desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize); |
322 |
322 |
323 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, |
323 mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, |
324 channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); |
324 channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM); |
325 |
325 |
326 audioStartThread(); |
326 audioStartThread(); |
327 |
327 |
328 Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); |
328 Log.v("SDL", "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + ((float)mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer"); |
329 |
329 |
330 if (is16Bit) { |
330 if (is16Bit) { |
331 buf = new short[desiredFrames * (isStereo ? 2 : 1)]; |
331 buf = new short[desiredFrames * (isStereo ? 2 : 1)]; |
332 } else { |
332 } else { |
333 buf = new byte[desiredFrames * (isStereo ? 2 : 1)]; |
333 buf = new byte[desiredFrames * (isStereo ? 2 : 1)]; |
334 } |
334 } |
335 return buf; |
335 return buf; |
336 } |
336 } |
337 |
337 |
338 public static void audioStartThread() { |
338 public static void audioStartThread() { |
339 mAudioThread = new Thread(new Runnable() { |
339 mAudioThread = new Thread(new Runnable() { |
340 public void run() { |
340 public void run() { |
341 mAudioTrack.play(); |
341 mAudioTrack.play(); |
342 nativeRunAudioThread(); |
342 nativeRunAudioThread(); |
343 } |
343 } |
344 }); |
344 }); |
345 |
345 |
346 // I'd take REALTIME if I could get it! |
346 // I'd take REALTIME if I could get it! |
347 mAudioThread.setPriority(Thread.MAX_PRIORITY); |
347 mAudioThread.setPriority(Thread.MAX_PRIORITY); |
348 mAudioThread.start(); |
348 mAudioThread.start(); |
349 } |
349 } |
350 |
350 |
351 public static void audioWriteShortBuffer(short[] buffer) { |
351 public static void audioWriteShortBuffer(short[] buffer) { |
352 for (int i = 0; i < buffer.length; ) { |
352 for (int i = 0; i < buffer.length; ) { |
353 int result = mAudioTrack.write(buffer, i, buffer.length - i); |
353 int result = mAudioTrack.write(buffer, i, buffer.length - i); |
354 if (result > 0) { |
354 if (result > 0) { |
355 i += result; |
355 i += result; |
356 } else if (result == 0) { |
356 } else if (result == 0) { |
357 try { |
357 try { |
358 Thread.sleep(1); |
358 Thread.sleep(1); |
359 } catch(InterruptedException e) { |
359 } catch(InterruptedException e) { |
360 // Nom nom |
360 // Nom nom |
361 } |
361 } |
362 } else { |
362 } else { |
363 Log.w("SDL", "SDL audio: error return from write(short)"); |
363 Log.w("SDL", "SDL audio: error return from write(short)"); |
364 return; |
364 return; |
365 } |
365 } |
366 } |
366 } |
367 } |
367 } |
368 |
368 |
369 public static void audioWriteByteBuffer(byte[] buffer) { |
369 public static void audioWriteByteBuffer(byte[] buffer) { |
370 for (int i = 0; i < buffer.length; ) { |
370 for (int i = 0; i < buffer.length; ) { |
371 int result = mAudioTrack.write(buffer, i, buffer.length - i); |
371 int result = mAudioTrack.write(buffer, i, buffer.length - i); |
372 if (result > 0) { |
372 if (result > 0) { |
373 i += result; |
373 i += result; |
374 } else if (result == 0) { |
374 } else if (result == 0) { |
375 try { |
375 try { |
376 Thread.sleep(1); |
376 Thread.sleep(1); |
377 } catch(InterruptedException e) { |
377 } catch(InterruptedException e) { |
378 // Nom nom |
378 // Nom nom |
379 } |
379 } |
380 } else { |
380 } else { |
381 Log.w("SDL", "SDL audio: error return from write(short)"); |
381 Log.w("SDL", "SDL audio: error return from write(short)"); |
382 return; |
382 return; |
383 } |
383 } |
384 } |
384 } |
385 } |
385 } |
386 |
386 |
387 public static void audioQuit() { |
387 public static void audioQuit() { |
388 if (mAudioThread != null) { |
388 if (mAudioThread != null) { |
389 try { |
389 try { |
390 mAudioThread.join(); |
390 mAudioThread.join(); |
391 } catch(Exception e) { |
391 } catch(Exception e) { |
392 Log.v("SDL", "Problem stopping audio thread: " + e); |
392 Log.v("SDL", "Problem stopping audio thread: " + e); |
393 } |
393 } |
394 mAudioThread = null; |
394 mAudioThread = null; |
395 |
395 |
396 //Log.v("SDL", "Finished waiting for audio thread"); |
396 //Log.v("SDL", "Finished waiting for audio thread"); |
397 } |
397 } |
398 |
398 |
399 if (mAudioTrack != null) { |
399 if (mAudioTrack != null) { |
400 mAudioTrack.stop(); |
400 mAudioTrack.stop(); |
401 mAudioTrack = null; |
401 mAudioTrack = null; |
402 } |
402 } |
403 } |
403 } |
404 |
404 |
405 public static int getDensity(){ |
405 public static int getDensity(){ |
406 DisplayMetrics dm = SDLActivity.getContext().getResources().getDisplayMetrics(); |
406 DisplayMetrics dm = SDLActivity.getContext().getResources().getDisplayMetrics(); |
407 return dm.densityDpi; |
407 return dm.densityDpi; |
408 } |
408 } |
409 } |
409 } |
410 |
410 |
411 /** |
411 /** |
412 Simple nativeInit() runnable |
412 Simple nativeInit() runnable |
413 */ |
413 */ |
414 class SDLMain implements Runnable { |
414 class SDLMain implements Runnable { |
415 public static final String TAG = "SDLMain"; |
415 public static final String TAG = "SDLMain"; |
416 |
416 |
417 public static final int RQ_LOWRES = 0x00000001; // use half land array |
417 public static final int RQ_LOWRES = 0x00000001; // use half land array |
418 public static final int RQ_BLURRY_LAND = 0x00000002; // downscaled terrain |
418 public static final int RQ_BLURRY_LAND = 0x00000002; // downscaled terrain |
419 public static final int RQ_NO_BACKGROUND = 0x00000004; // don't draw background |
419 public static final int RQ_NO_BACKGROUND = 0x00000004; // don't draw background |
420 public static final int RQ_SIMPLE_ROPE = 0x00000008; // avoid drawing rope |
420 public static final int RQ_SIMPLE_ROPE = 0x00000008; // avoid drawing rope |
421 public static final int RQ_2D_WATER = 0x00000010; // disabe 3D water effect |
421 public static final int RQ_2D_WATER = 0x00000010; // disabe 3D water effect |
424 public static final int RQ_NO_MENU_ANIM = 0x00000080; // ammomenu appears with no animation |
424 public static final int RQ_NO_MENU_ANIM = 0x00000080; // ammomenu appears with no animation |
425 public static final int RQ_NO_DROPLETS = 0x00000100; // no droplets |
425 public static final int RQ_NO_DROPLETS = 0x00000100; // no droplets |
426 public static final int RQ_NO_CLAMPING = 0x00000200; // don't clamp textures |
426 public static final int RQ_NO_CLAMPING = 0x00000200; // don't clamp textures |
427 public static final int RQ_NO_TOOLTIPS = 0x00000400; // tooltips are not drawn |
427 public static final int RQ_NO_TOOLTIPS = 0x00000400; // tooltips are not drawn |
428 public static final int RQ_NO_VSYNC = 0x00000800; // don't sync on vblank |
428 public static final int RQ_NO_VSYNC = 0x00000800; // don't sync on vblank |
429 |
429 |
430 private final int surfaceWidth, surfaceHeight; |
430 private final int surfaceWidth, surfaceHeight; |
431 private final String playerName; |
431 private final String playerName; |
432 private final GameConfig config; |
432 private final GameConfig config; |
433 private final boolean netgame; |
433 private final boolean netgame; |
434 |
434 |
435 public SDLMain(int width, int height, GameConfig config, boolean netgame) { |
435 public SDLMain(int width, int height, GameConfig config, boolean netgame) { |
436 surfaceWidth = width; |
436 surfaceWidth = width; |
437 surfaceHeight = height; |
437 surfaceHeight = height; |
438 if(netgame) { |
438 if(netgame) { |
439 playerName = Netplay.getAppInstance(SDLActivity.getContext().getApplicationContext()).getPlayerName(); |
439 playerName = Netplay.getAppInstance(SDLActivity.getContext().getApplicationContext()).getPlayerName(); |
440 } else { |
440 } else { |
441 playerName = "Player"; |
441 playerName = "Player"; |
442 } |
442 } |
443 this.config = config; |
443 this.config = config; |
444 this.netgame = netgame; |
444 this.netgame = netgame; |
445 } |
445 } |
446 |
446 |
447 public void run() { |
447 public void run() { |
448 //Set up the IPC socket server to communicate with the engine |
448 //Set up the IPC socket server to communicate with the engine |
449 GameConnection gameConn; |
449 GameConnection gameConn; |
450 String path; |
450 String path; |
451 try { |
451 try { |
452 if(netgame) { |
452 if(netgame) { |
453 Netplay netplay = Netplay.getAppInstance(SDLActivity.mSingleton.getApplicationContext()); |
453 Netplay netplay = Netplay.getAppInstance(SDLActivity.mSingleton.getApplicationContext()); |
454 gameConn = GameConnection.forNetgame(config, netplay); |
454 gameConn = GameConnection.forNetgame(config, netplay); |
455 } else { |
455 } else { |
456 gameConn = GameConnection.forLocalGame(config); |
456 gameConn = GameConnection.forLocalGame(config); |
457 } |
457 } |
458 |
458 |
459 path = FileUtils.getDataPathFile(SDLActivity.mSingleton).getAbsolutePath(); |
459 path = FileUtils.getDataPathFile(SDLActivity.mSingleton).getAbsolutePath(); |
460 Log.d(TAG, "Starting engine"); |
460 Log.d(TAG, "Starting engine"); |
461 // Runs SDL_main() with added parameters |
461 // Runs SDL_main() with added parameters |
462 try { |
462 try { |
463 String pPort = String.valueOf(gameConn.port); |
463 String pPort = String.valueOf(gameConn.port); |
464 String pWidth = String.valueOf(surfaceWidth); |
464 String pWidth = String.valueOf(surfaceWidth); |
465 String pHeight = String.valueOf(surfaceHeight); |
465 String pHeight = String.valueOf(surfaceHeight); |
466 String pQuality = Integer.toString(RQ_NO_FLAKES|RQ_NO_DROPLETS|RQ_SIMPLE_EXPLOSIONS); |
466 String pQuality = Integer.toString(RQ_NO_FLAKES|RQ_NO_DROPLETS|RQ_SIMPLE_EXPLOSIONS); |
467 String pPlayerName = Base64.encodeToString(playerName.getBytes("UTF-8"), 0); |
467 String pPlayerName = Base64.encodeToString(playerName.getBytes("UTF-8"), 0); |
468 SDLActivity.synchronizedNativeInit(new String[] { pPort, pWidth, pHeight, pQuality, "en.txt", pPlayerName, "1", "1", "1", path, "" }); |
468 SDLActivity.synchronizedNativeInit(new String[] { pPort, pWidth, pHeight, pQuality, "en.txt", pPlayerName, "1", "1", "1", path, "" }); |
469 } catch (UnsupportedEncodingException e) { |
469 } catch (UnsupportedEncodingException e) { |
470 throw new AssertionError(e); // never happens |
470 throw new AssertionError(e); // never happens |
471 } |
471 } |
472 Log.d(TAG, "Engine stopped"); |
472 Log.d(TAG, "Engine stopped"); |
473 } catch(ConnectException e) { |
473 } catch(ConnectException e) { |
474 Log.e(TAG, "Error starting IPC connection"); |
474 Log.e(TAG, "Error starting IPC connection"); |
475 } catch (IOException e) { |
475 } catch (IOException e) { |
476 Log.e(TAG, "Missing SDCard"); |
476 Log.e(TAG, "Missing SDCard"); |
477 } |
477 } |
478 SDLActivity.mSingleton.runOnUiThread(new Runnable() { public void run() { |
478 SDLActivity.mSingleton.runOnUiThread(new Runnable() { public void run() { |
479 if(SDLActivity.mSingleton != null) { |
479 if(SDLActivity.mSingleton != null) { |
480 SDLActivity.mSingleton.finish(); |
480 SDLActivity.mSingleton.finish(); |
481 } |
481 } |
482 }}); |
482 }}); |
483 } |
483 } |
484 } |
484 } |
485 |
485 |
486 |
486 |
487 /** |
487 /** |
488 SDLSurface. This is what we draw on, so we need to know when it's created |
488 SDLSurface. This is what we draw on, so we need to know when it's created |
489 in order to do anything useful. |
489 in order to do anything useful. |
490 |
490 |
491 Because of this, that's where we set up the SDL thread |
491 Because of this, that's where we set up the SDL thread |
492 */ |
492 */ |
493 class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, |
493 class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, |
494 View.OnKeyListener, View.OnTouchListener, SensorEventListener { |
494 View.OnKeyListener, View.OnTouchListener, SensorEventListener { |
495 |
495 |
496 private GameConfig config; |
496 private GameConfig config; |
497 private boolean netgame; |
497 private boolean netgame; |
498 |
498 |
499 // Sensors |
499 // Sensors |
500 private static SensorManager mSensorManager; |
500 private static SensorManager mSensorManager; |
501 |
501 |
502 // Startup |
502 // Startup |
503 public SDLSurface(Context context, GameConfig _config, boolean netgame) { |
503 public SDLSurface(Context context, GameConfig _config, boolean netgame) { |
504 super(context); |
504 super(context); |
505 getHolder().addCallback(this); |
505 getHolder().addCallback(this); |
506 |
506 |
507 setFocusable(true); |
507 setFocusable(true); |
508 setFocusableInTouchMode(true); |
508 setFocusableInTouchMode(true); |
509 requestFocus(); |
509 requestFocus(); |
510 setOnKeyListener(this); |
510 setOnKeyListener(this); |
511 setOnTouchListener(this); |
511 setOnTouchListener(this); |
512 |
512 |
513 mSensorManager = (SensorManager)context.getSystemService("sensor"); |
513 mSensorManager = (SensorManager)context.getSystemService("sensor"); |
514 config = _config; |
514 config = _config; |
515 this.netgame = netgame; |
515 this.netgame = netgame; |
516 } |
516 } |
517 |
517 |
518 // Called when we have a valid drawing surface |
518 // Called when we have a valid drawing surface |
519 public void surfaceCreated(SurfaceHolder holder) { |
519 public void surfaceCreated(SurfaceHolder holder) { |
520 Log.v("SDL", "surfaceCreated()"); |
520 Log.v("SDL", "surfaceCreated()"); |
521 holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); |
521 holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); |
522 SDLActivity.createEGLSurface(); |
522 SDLActivity.createEGLSurface(); |
523 // enableSensor(Sensor.TYPE_ACCELEROMETER, true); |
523 // enableSensor(Sensor.TYPE_ACCELEROMETER, true); |
524 } |
524 } |
525 |
525 |
526 // Called when we lose the surface |
526 // Called when we lose the surface |
527 public void surfaceDestroyed(SurfaceHolder holder) { |
527 public void surfaceDestroyed(SurfaceHolder holder) { |
528 Log.v("SDL", "surfaceDestroyed()"); |
528 Log.v("SDL", "surfaceDestroyed()"); |
529 SDLActivity.nativePause(); |
529 SDLActivity.nativePause(); |
530 // enableSensor(Sensor.TYPE_ACCELEROMETER, false); |
530 // enableSensor(Sensor.TYPE_ACCELEROMETER, false); |
531 } |
531 } |
532 |
532 |
533 // Called when the surface is resized |
533 // Called when the surface is resized |
534 public void surfaceChanged(SurfaceHolder holder, |
534 public void surfaceChanged(SurfaceHolder holder, |
535 int format, int width, int height) { |
535 int format, int width, int height) { |
536 Log.v("SDL", "surfaceChanged()"); |
536 Log.v("SDL", "surfaceChanged()"); |
537 |
537 |
538 int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default |
538 int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default |
539 switch (format) { |
539 switch (format) { |
540 case PixelFormat.A_8: |
540 case PixelFormat.A_8: |
541 Log.v("SDL", "pixel format A_8"); |
541 Log.v("SDL", "pixel format A_8"); |
542 break; |
542 break; |
543 case PixelFormat.LA_88: |
543 case PixelFormat.LA_88: |
544 Log.v("SDL", "pixel format LA_88"); |
544 Log.v("SDL", "pixel format LA_88"); |
545 break; |
545 break; |
546 case PixelFormat.L_8: |
546 case PixelFormat.L_8: |
547 Log.v("SDL", "pixel format L_8"); |
547 Log.v("SDL", "pixel format L_8"); |
548 break; |
548 break; |
549 case PixelFormat.RGBA_4444: |
549 case PixelFormat.RGBA_4444: |
550 Log.v("SDL", "pixel format RGBA_4444"); |
550 Log.v("SDL", "pixel format RGBA_4444"); |
551 sdlFormat = 0x85421002; // SDL_PIXELFORMAT_RGBA4444 |
551 sdlFormat = 0x85421002; // SDL_PIXELFORMAT_RGBA4444 |
552 break; |
552 break; |
553 case PixelFormat.RGBA_5551: |
553 case PixelFormat.RGBA_5551: |
554 Log.v("SDL", "pixel format RGBA_5551"); |
554 Log.v("SDL", "pixel format RGBA_5551"); |
555 sdlFormat = 0x85441002; // SDL_PIXELFORMAT_RGBA5551 |
555 sdlFormat = 0x85441002; // SDL_PIXELFORMAT_RGBA5551 |
556 break; |
556 break; |
557 case PixelFormat.RGBA_8888: |
557 case PixelFormat.RGBA_8888: |
558 Log.v("SDL", "pixel format RGBA_8888"); |
558 Log.v("SDL", "pixel format RGBA_8888"); |
559 sdlFormat = 0x86462004; // SDL_PIXELFORMAT_RGBA8888 |
559 sdlFormat = 0x86462004; // SDL_PIXELFORMAT_RGBA8888 |
560 break; |
560 break; |
561 case PixelFormat.RGBX_8888: |
561 case PixelFormat.RGBX_8888: |
562 Log.v("SDL", "pixel format RGBX_8888"); |
562 Log.v("SDL", "pixel format RGBX_8888"); |
563 sdlFormat = 0x86262004; // SDL_PIXELFORMAT_RGBX8888 |
563 sdlFormat = 0x86262004; // SDL_PIXELFORMAT_RGBX8888 |
564 break; |
564 break; |
565 case PixelFormat.RGB_332: |
565 case PixelFormat.RGB_332: |
566 Log.v("SDL", "pixel format RGB_332"); |
566 Log.v("SDL", "pixel format RGB_332"); |
567 sdlFormat = 0x84110801; // SDL_PIXELFORMAT_RGB332 |
567 sdlFormat = 0x84110801; // SDL_PIXELFORMAT_RGB332 |
568 break; |
568 break; |
569 case PixelFormat.RGB_565: |
569 case PixelFormat.RGB_565: |
570 Log.v("SDL", "pixel format RGB_565"); |
570 Log.v("SDL", "pixel format RGB_565"); |
571 sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 |
571 sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 |
572 break; |
572 break; |
573 case PixelFormat.RGB_888: |
573 case PixelFormat.RGB_888: |
574 Log.v("SDL", "pixel format RGB_888"); |
574 Log.v("SDL", "pixel format RGB_888"); |
575 // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead? |
575 // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead? |
576 sdlFormat = 0x86161804; // SDL_PIXELFORMAT_RGB888 |
576 sdlFormat = 0x86161804; // SDL_PIXELFORMAT_RGB888 |
577 break; |
577 break; |
578 default: |
578 default: |
579 Log.v("SDL", "pixel format unknown " + format); |
579 Log.v("SDL", "pixel format unknown " + format); |
580 break; |
580 break; |
581 } |
581 } |
582 SDLActivity.onNativeResize(width, height, sdlFormat); |
582 SDLActivity.onNativeResize(width, height, sdlFormat); |
583 Log.v("SDL", "Window size:" + width + "x"+height); |
583 Log.v("SDL", "Window size:" + width + "x"+height); |
584 |
584 |
585 SDLActivity.startApp(width, height, config, netgame); |
585 SDLActivity.startApp(width, height, config, netgame); |
586 } |
586 } |
587 |
587 |
588 // unused |
588 // unused |
589 public void onDraw(Canvas canvas) {} |
589 public void onDraw(Canvas canvas) {} |
590 |
590 |
591 |
591 |
592 |
592 |
593 |
593 |
594 // Key events |
594 // Key events |
595 public boolean onKey(View v, int keyCode, KeyEvent event) { |
595 public boolean onKey(View v, int keyCode, KeyEvent event) { |
596 switch(keyCode){ |
596 switch(keyCode){ |
597 case KeyEvent.KEYCODE_BACK: |
597 case KeyEvent.KEYCODE_BACK: |
598 Log.d("SDL", "KEYCODE_BACK"); |
598 Log.d("SDL", "KEYCODE_BACK"); |
599 SDLActivity.nativeQuit(); |
599 SDLActivity.nativeQuit(); |
600 return true; |
600 return true; |
601 case KeyEvent.KEYCODE_VOLUME_DOWN: |
601 case KeyEvent.KEYCODE_VOLUME_DOWN: |
602 case KeyEvent.KEYCODE_VOLUME_UP: |
602 case KeyEvent.KEYCODE_VOLUME_UP: |
603 case KeyEvent.KEYCODE_VOLUME_MUTE: |
603 case KeyEvent.KEYCODE_VOLUME_MUTE: |
604 return false; |
604 return false; |
605 } |
605 } |
606 if (event.getAction() == KeyEvent.ACTION_DOWN) { |
606 if (event.getAction() == KeyEvent.ACTION_DOWN) { |
607 //Log.v("SDL", "key down: " + keyCode); |
607 //Log.v("SDL", "key down: " + keyCode); |
608 SDLActivity.onNativeKeyDown(keyCode); |
608 SDLActivity.onNativeKeyDown(keyCode); |
609 return true; |
609 return true; |
610 } |
610 } |
611 else if (event.getAction() == KeyEvent.ACTION_UP) { |
611 else if (event.getAction() == KeyEvent.ACTION_UP) { |
612 //Log.v("SDL", "key up: " + keyCode); |
612 //Log.v("SDL", "key up: " + keyCode); |
613 SDLActivity.onNativeKeyUp(keyCode); |
613 SDLActivity.onNativeKeyUp(keyCode); |
614 return true; |
614 return true; |
615 } |
615 } |
616 |
616 |
617 return false; |
617 return false; |
618 } |
618 } |
619 |
619 |
620 // Touch events |
620 // Touch events |
621 public boolean onTouch(View v, MotionEvent event) { |
621 public boolean onTouch(View v, MotionEvent event) { |
622 final int action = event.getAction() & MotionEvent.ACTION_MASK; |
622 final int action = event.getAction() & MotionEvent.ACTION_MASK; |
623 final int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; |
623 final int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; |
624 |
624 |
625 if (action == MotionEvent.ACTION_MOVE) { |
625 if (action == MotionEvent.ACTION_MOVE) { |
626 // TODO send motion to every pointer if its position has |
626 // TODO send motion to every pointer if its position has |
627 // changed since prev event. |
627 // changed since prev event. |
628 for (int i = 0; i < event.getPointerCount(); i++) { |
628 for (int i = 0; i < event.getPointerCount(); i++) { |
629 sendNativeTouch(event, action, i); |
629 sendNativeTouch(event, action, i); |
630 } |
630 } |
631 } else { |
631 } else { |
632 sendNativeTouch(event, action, actionPointerIndex); |
632 sendNativeTouch(event, action, actionPointerIndex); |
633 } |
633 } |
634 return true; |
634 return true; |
635 } |
635 } |
636 |
636 |
637 private static void sendNativeTouch(MotionEvent event, int action, int pointerIndex) { |
637 private static void sendNativeTouch(MotionEvent event, int action, int pointerIndex) { |
638 int touchDevId = event.getDeviceId(); |
638 int touchDevId = event.getDeviceId(); |
639 int pointerFingerId = event.getPointerId(pointerIndex); |
639 int pointerFingerId = event.getPointerId(pointerIndex); |
640 float x = event.getX(pointerIndex); |
640 float x = event.getX(pointerIndex); |
641 float y = event.getY(pointerIndex); |
641 float y = event.getY(pointerIndex); |
642 float pressure = event.getPressure(pointerIndex); |
642 float pressure = event.getPressure(pointerIndex); |
643 SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, pressure); |
643 SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, pressure); |
644 } |
644 } |
645 |
645 |
646 // Sensor events |
646 // Sensor events |
647 public void enableSensor(int sensortype, boolean enabled) { |
647 public void enableSensor(int sensortype, boolean enabled) { |
648 // TODO: This uses getDefaultSensor - what if we have >1 accels? |
648 // TODO: This uses getDefaultSensor - what if we have >1 accels? |
649 if (enabled) { |
649 if (enabled) { |
650 mSensorManager.registerListener(this, |
650 mSensorManager.registerListener(this, |
651 mSensorManager.getDefaultSensor(sensortype), |
651 mSensorManager.getDefaultSensor(sensortype), |
652 SensorManager.SENSOR_DELAY_GAME, null); |
652 SensorManager.SENSOR_DELAY_GAME, null); |
653 } else { |
653 } else { |
654 mSensorManager.unregisterListener(this, |
654 mSensorManager.unregisterListener(this, |
655 mSensorManager.getDefaultSensor(sensortype)); |
655 mSensorManager.getDefaultSensor(sensortype)); |
656 } |
656 } |
657 } |
657 } |
658 |
658 |
659 public void onAccuracyChanged(Sensor sensor, int accuracy) { |
659 public void onAccuracyChanged(Sensor sensor, int accuracy) { |
660 // TODO |
660 // TODO |
661 } |
661 } |
662 |
662 |
663 public void onSensorChanged(SensorEvent event) { |
663 public void onSensorChanged(SensorEvent event) { |
664 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { |
664 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { |
665 SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH, |
665 SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH, |
666 event.values[1] / SensorManager.GRAVITY_EARTH, |
666 event.values[1] / SensorManager.GRAVITY_EARTH, |
667 event.values[2] / SensorManager.GRAVITY_EARTH); |
667 event.values[2] / SensorManager.GRAVITY_EARTH); |
668 } |
668 } |
669 } |
669 } |
670 } |
670 } |
671 |
671 |