Mobile Game Framework Stuff You Should Know… • • • • Genres Paper Prototyping Mechanics Theme/Backstory • Don’t Code! General Game API • Window/scene management • Input • File I/O – Playback recording (event logging) – Audio • Graphics • General game framework/loop (w/ timing) Window Management • Handle basic Android OS events – Create – Pause – Resume Input • Polling – Code asks, “what is the current state?” – Info lost between polling • Event-based – Queue of events stored • Touch down, drag/move, up • Key down, up Input Polling • • • • • • • isKeyPressed(keyCode) isTouchDown(id) getTouchX(id) getTouchY(id) getAccelX() getAccelY() getAccelZ() Event-based Input • getKeyEvents() – Returns List<KeyEvent> • getTouchEvents() – Returns List<TouchEvent> File I/O • Manage Java InputStream and OutputStream instances • Load/use assets (audio, graphics, etc.) • Save data (state, high score, settings) Audio Assets • Music – Ambient/background – Streamed (open stream and play) – Play, pause, stop, looping (bool), volume (float) • Sound – – – – Shorter Typically event-driven Load entirely in memory Play • Dispose when not needed Graphics • Handle typical APIs like color, pixel maps, compression, double buffering, and alpha compositing • Load/store imgs • Framebuffer – – – – – Clear DrawSprite Primitives Swap Height/width Game Loop Input input = new Input(); Graphics graphics = new Graphics(); Audio audio = new Audio(); Screen currentScreen = new MainMenu(); Float lastFrameTime = currentTime(); while (!userQuit() ) { float deltaTime = currentTime() – lastFrameTime; lastFrameTime = currentTime(); currentScreen.updateState(input, deltaTime); currentScreen.present(graphics, audio, deltaTime); } cleanupResources(); Frame Rate Management vs Java/ADK Specifics XML and the Manifest Best Practices • Utilize latest SDKs but be compatible back to 1.5 • Install to SD whenever possible • Single main activity that handles all events – Debatable relative to general Android App dev • Portrait or landscape (or both?) • Access SD • Obtain a wake lock (keep from sleeping) Defining Multi-Resolution Assets • Handle difference devices – ldpi=36x36 – mdpi=48x48 – hdpi=72x72 – xhdpi=96x96 • /res/drawable/ic_launcher.png – Same as mdpi – For Android 1.5 compatibility Core Android Activity Events • Create – Set up window/UI • Resume – (Re)start game loop • Pause – Pause game loop – Check isFinishing • Save state Test Your Understanding • LogCat (debugging event list) – Utilize debugging view in Eclipse • Define new class that extends Activity – Override • onCreate • onResume • onPause – Check isFinishing() Handling Touch Events • setOnTouchListener(this) • onTouch(view, event) – Handle types of touch events – switch(event.getAction()) • MotionEvent.ACTION_DOWN • MotionEvent.ACTION_UP • … – event.getX() • Multitouch involves handling array of touch data Handling Key Events • setOnKeyListener(this) • onKey(view, keyCode, event) – Handle KeyEvent.ACTION_DOWN – Handle KeyEvent.ACTION_UP Accelerometer Input • Check if accelerometer present on device – getSensorList(Sensor.TYPE_ACCELEROMETER) • Register activity as listener to accelerometer events – registerListener(this, accel, m.SENSOR_DELAY_GAME) • onSensorChanged(event) – event.values[0] <- x – event.values[1] <- y – event.values[2] <- z • Deal with orientation by axis swapping Asset File I/O • assets/ folder quite useful via AssetManager AssetManager am = getAssets(); InputStream is = am.open(filename); … is.close(); External/SD Access • Use <uses-permissions> in manifest • Check if external storage exists – Environment.getExternalStorageState(); • Get directory root – Environment.getExternalStorageDirectory(); • Utilize standard Java file I/O APIs • Beware: complete SD access to read/write! Shared Preferences • Stores key-value pairs p = getPreferences(Context.MODE_PRIVATE); e = p.edit(); e.putString(key, value); e.putInt(key, value); e.commit(); String s = p.getString(key, null); int i = p.getInt(key, 0); Sound Effect Audio Setup… setVolumeControlStream(AudioManager.STREA_MUSIC); soundPool = new SoundPool(max, AudioManager.STREAM_MUSIC, 0); Get file descriptor and id: d = assetManager.openFd(“soundEffect.ogg”); int id =soundPool.load(d, 1); Then play… soundPool.play(id, left, right, 0, loop, playback); Finally… soundPool.unload(id); Streaming Audio MediaPlayer mp = new MediaPlayer(); AssetFileDescriptor afd = am.openFd(“ambient.ogg”); mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); mp.prepare(); mp.start(); … mp.setVolume(left, right); mp.pause(); mp.stop(); mp.setLooping(bool); Handle when completed: mp.isPlaying() mp.setOnCompletionListener(listener); mp.release(); Well-Lit Graphics Keep screen completely on with wake lock… • Setup – <uses-permission> in manifest • onCreate – PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); – WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Lock"); • onResume – wl.acquire(); • onPause – wl.release(); Full Screen Graphics • Remove the title bars • Get full resolution for graphics/display • In onCreate: requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); NOTE: do this before setting the content view of activity! FPS++ • Heretofore, the application only refreshes/draws itself in response to events • This is good given battery considerations • But we can increase the FPS/draw rate • Inherit from View • Define onDraw(Canvas) method • Invoke ‘invalidate’ at the end of onDraw • Don’t forget to set the content view to a new instance of this derived class The Limitless Possibilities of Canvas • Canvas (parameter to onDraw) provides a wealth of options – – – – – – getWidth(); getHeight(); drawPoint(x,y,paint); drawLine(x1,y1,x2,y2,paint); drawRect(x1,y1,x2,y2,paint); drawCircle(x,y,radius,paint); • Paint – setARGB(a,r,g,b); – setColor(0xaarrggbb); Drawing Bitmaps/Sprites • Bitmap – InputStream is = assetManager.open(file); – Bitmap bmp = BitmapFactory.decodeStream(is); – getWidth(); – getHeight(); – When done, bmp.recycle(); • Drawing the Bitmap – canvas.drawBitmap(bmp, x, y, paint); – canvas.drawBitmap(bmp, srcRect, dstRect, paint); Drawing Text • Fonts are placed in the assets/ directory • Then loaded – Typeface font = Typeface.createFromAsset(context.getAssets(), fontFileName); • Set the paint instance – paint.setTypeFace(font); – paint.setTextSize(x); – paint.setTextAlign(Paint.Align.LEFT|CENTER|RIGHT); • Draw using canvas – canvas.drawText(string, x, y, paint); Problem with onDraw/invalidate • • • • • This presumes nothing else in the game runs UI dominates View vs SurfaceView We want to have a thread running to do rendering Create new class that inherits SurfaceView – Maintain thread – Implement run, pause methods • To draw – Canvas c = holder.lockCanvas(); – c.draw… – holder.unlockCanvasAndPost(c); SurfaceView Subclass Using SurfaceView Subclass