360 likes | 488 Views
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.
E N D
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();
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 extendsActivity • 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); inti = 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 MediaPlayermp = new MediaPlayer(); AssetFileDescriptorafd = 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 • PowerManagerpm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); • WakeLockwl = 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 vsSurfaceView • 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);