Series 40 Developer TrainingGetting Started with GameDevelopment on Nokia Series 40 FullTouch Asha PhonesMichael Samarin, ...
Today’s topics» This presentation is summary and compressed extracts  relevant to game development from previous webinars:...
New Series 40 Full Touch Platform                                    Asha 305                                    Asha 306 ...
Asha 305, 306      Asha 308, 309         Asha 311 Jar Size       2 Mb               2 Mb               2 MbJava Heap      ...
Series 40 Graphics APIs» 2D Game Development   › Game API, part of the MIDP 2.0 standard, java package:     javax.microedi...
› Game API Package (MIDP)› javax.microedition.lcdui.game  › GameCanvas  › Layer  › LayerManager  › Sprite  › TiledLayer
› GameCanvas  › Double buffered  › Convenient for minimizing code of    game loop  › Methods for querying status of keys
› GameCanvaspublic class MyCanvas extends GameCanvas implements Runnable {    public void run() {        Graphics g = getG...
› Graphical Assets
› Graphical Assets – Sprite Star
› Graphical Assets – Sprite Lightning
› Layer  › Abstract class, any visual game    element› LayerManager  › Combines layers together,    provides viewport
› Sprite  › Animated game object› TiledLayer  › Game areas, backgrounds
› Sprite  › Animated element of the game    (character)  › Define Sequence, Delay  › Flip, Rotate  › Define Reference Poin...
› TiledLayer  › Defines game backgrounds  › Can be animated  › Doesn’t have Sprite methods
› Object-Oriented 3D                         › Scene Graph based                         › Optional MIDP JSRMobile 3D Grap...
Lightweight API, only 30 classesAnimationController   IndexBuffer        RayIntersectionAnimationTrack        KeyframeSequ...
› Immediate mode               › Similar to OpenGL ideology            › Retained modeM3G Modes      › Scene Graph based  ...
Scene Graph        Background       Mesh          Group      Morphing MeshWorld                Skinned Mesh               ...
› World                      › Background                   › Morphing and Skinned MeshMost Interesting      › Animated Ge...
public class Canvas3D extends Canvas         implements Runnable {    public Canvas3D(){    }    public void paint(Graphic...
public class Canvas3D extends Canvas         implements Runnable {                                       private Thread th...
setFullScreenMode(true);                                       thread = new Thread(this);public class Canvas3D extends Can...
public class Canvas3D extends Canvas         implements Runnable {                                       graphics3D.bindTa...
public class Canvas3D extends Canvas         implements Runnable {    public Canvas3D(){                 while (running){ ...
› User input in full touch Asha devices   › Game keys simulation   › Touch events   › Multipoint-touch   › Gestures   › Se...
Game keys simulation» No touch handling in Canvas?   › Drag gestures automatically trigger simulated key events   › Up, Do...
› Tap: touch + release           › Long Press (& repeated): touch +             hold  Touch    › Drag: touch + drag       ...
Using Gestures › Register as gesture listenerpublic class MainCanvas extends Canvas implements GestureListener {    privat...
Using Gestures   › Handling gesturespublic void gestureAction(Object container, GestureInteractiveZone gestureInteractiveZ...
› Single touch                    › Canvas.pointerPressed() part                      of MIDP                    › Only tr...
Using Multipoint-Touch› Number of touch points                                  2 on Nokia 305 / 306 MultipointTouch mpt =...
Using Multipoint-Touch› Handling touch events public void pointersChanged(int[] pointerIds) {     for(int i=0; i<pointerId...
› JSR 256 Sensor API             › Optional Generic API: designed for               battery, network status, also for     ...
› Synchronous                   › Poll sensor                   › Example: accelerometer in                     game loopS...
Using Multipoint-Touch› Establish sensor connection// Find all acceleration sensors, the contextType is left undefinedSens...
Hash Acceleration» Some iterative algorithms are slow. Proper usage of  collections types of data structures can increase ...
Synchronized vs. Volatile Variables» When a variable or Object needs to be accessed from more  than one Thread.» Marking a...
Constants» We can give the compiler and Proguard more opportunities  to optimize the code at the compile step, and this wi...
Primitives» Use int instead of short, byte or long.  for (int i = 0; i < 3000000; i++) {      short/int/long a = 123;     ...
Final in methodsfor (int i = 0; i < 1000000; i++) {    a = finalMethod(1, 2, 3);}for (int i = 0; i < 1000000; i++) {    a ...
Final in methodsAverage times on a Nokia Asha 305:finalMethod: 650 msnonFinalMethod: 940 ms 45% slowerIn this case, the ti...
Static» Generally static methods and variables should be faster.  Oddly, with some combinations of ARM and JVM, instance  ...
String ConcatenationIf you are going to concatenate a large number of small Strings,use:StringBuffer.append()instead of th...
Addition vs. Multiplication vs. Divisionfor (int i = 0; i < 500000; i++) {    a = 1.23f;    b = 1.45f;    c = 0.004523f;  ...
Switch vs. IfThe switch statement in C is implemented as a direct jump which isextremely fast. In Java on Nokia Series 40 ...
Live Demo Session»   If you are watching these slides on SlideShare, next part is live coding    demonstration with Nokia ...
› Andreas Jakl, NokiaSpecial thanks
Thank you!@MichaelSamarin
Upcoming SlideShare
Loading in …5
×

Developing games for Series 40 full-touch UI

3,086 views

Published on

This presentation introduce the processes involved in developing 2D and 3D games for the full-touch UI on Series 40 phones by using Nokia SDK 2.0 for Java™. Java expert Michael Samarin of Futurice introduces APIs of particular interest to game developers. He focus on development techniques specific to games with no keyboard input and how to use gestures and sensors in your games to increase player engagement. Performance and memory considerations are also covered.

Published in: Technology
2 Comments
3 Likes
Statistics
Notes
No Downloads
Views
Total views
3,086
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
78
Comments
2
Likes
3
Embeds 0
No embeds

No notes for slide

Developing games for Series 40 full-touch UI

  1. 1. Series 40 Developer TrainingGetting Started with GameDevelopment on Nokia Series 40 FullTouch Asha PhonesMichael Samarin, Ph.DDirector,Developer Training and EvangelismFuturice+358 40 518 18 09michael.samarin@futurice.com @MichaelSamarin
  2. 2. Today’s topics» This presentation is summary and compressed extracts relevant to game development from previous webinars: › Overview of full touch Asha Devices › Overview of graphical APIs for 2D and 3D Game development Mobile Java › User input in full touch devices › Useful in games performance tips on Series 40
  3. 3. New Series 40 Full Touch Platform Asha 305 Asha 306 Asha 311 Retail 70 – 120 $
  4. 4. Asha 305, 306 Asha 308, 309 Asha 311 Jar Size 2 Mb 2 Mb 2 MbJava Heap 2 Mb 2 Mb 4 Mb CPU -- -- 1 GHz Resistive Capacitive CapacitiveScreen Multipoint-Touch Multipoint-Touch Multipoint-Touch
  5. 5. Series 40 Graphics APIs» 2D Game Development › Game API, part of the MIDP 2.0 standard, java package: javax.microedition.lcdui.game › http://www.developer.nokia.com/Resources/Library/Java/#!deve lopers-guides/ui-and-graphics/game-api.html» 3D Game Development › Mobile 3D Graphics API, optional JSR-184 also known as M3G › http://www.developer.nokia.com/Resources/Library/Java/#!deve lopers-guides/ui-and-graphics/mobile-3d-graphics.html
  6. 6. › Game API Package (MIDP)› javax.microedition.lcdui.game › GameCanvas › Layer › LayerManager › Sprite › TiledLayer
  7. 7. › GameCanvas › Double buffered › Convenient for minimizing code of game loop › Methods for querying status of keys
  8. 8. › GameCanvaspublic class MyCanvas extends GameCanvas implements Runnable { public void run() { Graphics g = getGraphics(); while(true) { // update the game state int k = getKeyStates(); // respond to key events flushGraphics(); } }}
  9. 9. › Graphical Assets
  10. 10. › Graphical Assets – Sprite Star
  11. 11. › Graphical Assets – Sprite Lightning
  12. 12. › Layer › Abstract class, any visual game element› LayerManager › Combines layers together, provides viewport
  13. 13. › Sprite › Animated game object› TiledLayer › Game areas, backgrounds
  14. 14. › Sprite › Animated element of the game (character) › Define Sequence, Delay › Flip, Rotate › Define Reference Point › Detect Collisions
  15. 15. › TiledLayer › Defines game backgrounds › Can be animated › Doesn’t have Sprite methods
  16. 16. › Object-Oriented 3D › Scene Graph based › Optional MIDP JSRMobile 3D Graphics API › Very compact API JSR-184 or M3G › Very fast development › Optimized for small memory and budget CPU › Excellent implementation on Series 40
  17. 17. Lightweight API, only 30 classesAnimationController IndexBuffer RayIntersectionAnimationTrack KeyframeSequence SkinnedMeshAppearance Light Sprite3DBackground Loader Texture2DCamera Material TransformCompositingMode Mesh TransformableFog MorphingMesh TriangleStripArrayGraphics3D Node VertexArrayGroup Object3D VertexBufferImage2D PolygonMode World
  18. 18. › Immediate mode › Similar to OpenGL ideology › Retained modeM3G Modes › Scene Graph based › Entire Scene Graph can be restored from file › Well defined M3G format › Can be freely mixed
  19. 19. Scene Graph Background Mesh Group Morphing MeshWorld Skinned Mesh Sprite 3D Group Sprite 3D User Object Group Camera Light
  20. 20. › World › Background › Morphing and Skinned MeshMost Interesting › Animated Geometry Objects Scene Graph › Mesh Elements › 3D Geometry of Visible Object › Sprite 3D › 2D image in 3D space
  21. 21. public class Canvas3D extends Canvas implements Runnable { public Canvas3D(){ } public void paint(Graphics g) { } public void run() { }}
  22. 22. public class Canvas3D extends Canvas implements Runnable { private Thread thread; public Canvas3D(){ private long startTime; } private Graphics3D graphics3D; public void paint(Graphics g) { private World world; } private Camera camera; public void run() { private boolean running = false; }}
  23. 23. setFullScreenMode(true); thread = new Thread(this);public class Canvas3D extends Canvas startTime = System.currentTimeMillis() implements Runnable { graphics3D = Graphics3D.getInstance(); public Canvas3D(){ world = new World(); } camera = new Camera(); public void paint(Graphics g) { float aspect = (float) getWidth() / (float) getHeight(); } camera.setPerspective(30.0f, aspect, 1.0f, 1000.0f); public void run() { world.addChild(camera); } world.setActiveCamera(camera);} running = true; thread.start();
  24. 24. public class Canvas3D extends Canvas implements Runnable { graphics3D.bindTarget(g); public Canvas3D(){ world.animate( } (int)(System.currentTimeMillis() - startTime)); public void paint(Graphics g) { graphics3D.render(world); } graphics3D.releaseTarget(); public void run() { }}
  25. 25. public class Canvas3D extends Canvas implements Runnable { public Canvas3D(){ while (running){ } repaint(); public void paint(Graphics g) { Thread.sleep(20); } } public void run() { }}
  26. 26. › User input in full touch Asha devices › Game keys simulation › Touch events › Multipoint-touch › Gestures › Sensors
  27. 27. Game keys simulation» No touch handling in Canvas? › Drag gestures automatically trigger simulated key events › Up, Down, Left, Right
  28. 28. › Tap: touch + release › Long Press (& repeated): touch + hold Touch › Drag: touch + drag › Drop: touch + drag + touch downGestures (“stop”) + release › Flick: touch + drag + release while dragging › Pinch (new!): 2x touch + 2x drag + 2x touch down (“stop”) + 2x release
  29. 29. Using Gestures › Register as gesture listenerpublic class MainCanvas extends Canvas implements GestureListener { private int curPinchDistance = -1; public MainCanvas() { // Set this as container (gesture source) and listener GestureRegistrationManager.setListener(this, this); // Register for pinch events in the whole canvas area gestureZone = new GestureInteractiveZone(GestureInteractiveZone.GESTURE_PINCH); GestureRegistrationManager.register(this, gestureZone); } › Zone: reacts to 1+ specified gestures › Whole screen or rectangular area › Overlap possible › Received events → GestureListener
  30. 30. Using Gestures › Handling gesturespublic void gestureAction(Object container, GestureInteractiveZone gestureInteractiveZone, GestureEvent gestureEvent) { int eventType = gestureEvent.getType(); switch (eventType) { case GestureInteractiveZone.GESTURE_PINCH: // Pinch detected curPinchDistance = gestureEvent.getPinchDistanceCurrent(); break; case GestureInteractiveZone.GESTURE_RECOGNITION_START: /* ... */ break; case GestureInteractiveZone.GESTURE_RECOGNITION_END: /* ... */ break; }} › Executed in UI thread › Lengthy operations (scaling image, etc.) → own thread!
  31. 31. › Single touch › Canvas.pointerPressed() part of MIDP › Only tracks 1st touch pointPointer events › Multipoint Touch and › Tracks multiple touch points Multipoint- Touch › But: use Gesture API if only interested in pinch › Each associated with unique ID, x, y and state › Call-back for touch changes, but status available any time
  32. 32. Using Multipoint-Touch› Number of touch points 2 on Nokia 305 / 306 MultipointTouch mpt = MultipointTouch.getInstance(); 5 on Nokia 311 int numTouchPoints = MultipointTouch.getMaxPointers(); › Limited accuracy of simultaneous touch points on a resistive screen (Nokia 305) → no on-screen joystick & shoot button› Register: touch point listener public class MainCanvas extends Canvas implements MultipointTouchListener { public MainCanvas() { // ... mpt.addMultipointTouchListener(this); }
  33. 33. Using Multipoint-Touch› Handling touch events public void pointersChanged(int[] pointerIds) { for(int i=0; i<pointerIds.length; i++) { // Loop through the changed touch points { int pointerId = pointerIds[i]; // Get the touch point ID int state = MultipointTouch.getState(pointerId); // Get the touch point state // Get the touch point x and y coordinates int x = MultipointTouch.getX(pointerId); int y = MultipointTouch.getY(pointerId); // Handle the UI update based on the touch point state, ID and coordinates switch(state) { case MultipointTouch.POINTER_PRESSED: // A new finger was pressed against the screen drawTouch(pointerId, x, y); break; case MultipointTouch.POINTER_DRAGGED: // A pressed finger was dragged over the screen drawTouch(pointerId, x, y); break; case MultipointTouch.POINTER_RELEASED: // A pressed finger was lifted from the screen break; } } }
  34. 34. › JSR 256 Sensor API › Optional Generic API: designed for battery, network status, also for temperature, blood pressure, etc.Sensors › Usefull in Games › Acceleration: –2g .. +2g, x / y / z axis › Double Tap: 1 .. 63, phone sides › Orientation: 0 .. 6, phone orientation
  35. 35. › Synchronous › Poll sensor › Example: accelerometer in game loopSensors Modes › Asynchronous › DataListener callbacks › Example: phone charger plugged in
  36. 36. Using Multipoint-Touch› Establish sensor connection// Find all acceleration sensors, the contextType is left undefinedSensorInfo[] sensorInfos = SensorManager.findSensors("acceleration", null);// Find an acceleration sensor that returns double valuesfor (int i = 0; i < sensorInfos.length; i++) { if (sensorInfos[i].getChannelInfos()[0].getDataType() == ChannelInfo.TYPE_DOUBLE) { accSensor = (SensorConnection) Connector.open(sensorInfos[i].getUrl()); }}› Check data in game loop // Use 1 as a buffer size to get exactly 1 value for each axis Data[] data = accSensor.getData(1); speedX = -data[0].getDoubleValues()[0]; // data[0] => x-axis speedY = data[1].getDoubleValues()[0]; // data[1] => y-axis
  37. 37. Hash Acceleration» Some iterative algorithms are slow. Proper usage of collections types of data structures can increase performance.» Vector.contains() is very slow, but Hashtable.containsKey() is very fast. Reconsider your algorithms to use Hashtables.» Usage can be found in very surprising places. For example, Font.stringWidth() is slow, but necessary for drawing multiline text on Canvas. Creating a Hashtable with the width in each character you have used in the Font can transform this into a fast operation and increase Canvas.paint() speed.
  38. 38. Synchronized vs. Volatile Variables» When a variable or Object needs to be accessed from more than one Thread.» Marking a variable as volatile is the least restrictive approach and can have very high performance because no Thread is blocked.» Only one Thread may enter the synchronized sections at any one time.» Consider atomic operations on two variables. For example, when updating firstName and lastName from “John Smith” to “Jane Marceau”, do so within a synchronized block to avoid briefly exposing the transitional state “Jane Smith” to other threads.
  39. 39. Constants» We can give the compiler and Proguard more opportunities to optimize the code at the compile step, and this will also give the ARM processor opportunities for handling these variables with more efficient byte codes. private static int loopCount = 10; private static long startTime = System.currentTimeMillis(); private static boolean enableImages = true; Should be private static final int LOOP_COUNT = 10; private static final long START_TIME = System.currentTimeMillis(); private static final boolean ENABLE_IMAGES = true;
  40. 40. Primitives» Use int instead of short, byte or long. for (int i = 0; i < 3000000; i++) { short/int/long a = 123; short/int/long b = -44; short/int/long c = 12; a += c; b += a; c *= b; } Average times spent in loops on Nokia Asha 305 (obfuscated): int: 710 (580) ms short: 900 (850) ms 50% slower long: 1450 (1150) ms 100% slower
  41. 41. Final in methodsfor (int i = 0; i < 1000000; i++) { a = finalMethod(1, 2, 3);}for (int i = 0; i < 1000000; i++) { a = nonFinalMethod(1, 2, 3);}public final int finalMethod(final int a, final int b, final int c) { final float x = 1.23f, y = 0.05f; final float z = x * y; final int d = a + b + c; return d;}public int nonFinalMethod(int a, int b, int c) { float x = 1.23f, y = 0.05f; float z = x * y; int d = a + b + c; return d;}
  42. 42. Final in methodsAverage times on a Nokia Asha 305:finalMethod: 650 msnonFinalMethod: 940 ms 45% slowerIn this case, the time difference comes from final keyword beforex and y. It is logical because then z value can be precalculated.The final keywords with parameters a, b, c let us not precalculated or anything. And because we don’t use z, it being final does nothelp us
  43. 43. Static» Generally static methods and variables should be faster. Oddly, with some combinations of ARM and JVM, instance accesses are slightly faster. for (int i = 0; i < 1000000; i++) { staticMethod(); Average times spent in loops } on Nokia Asha 305 for (int i = 0; i < 1000000; i++) { nonStaticMethod(); (obfuscated): } private static void staticMethod() { nonStaticMethod: 570 ms b++; // static variable } staticMethod: 680 ms 20% private void nonStaticMethod() { slower a++; // instance variable }
  44. 44. String ConcatenationIf you are going to concatenate a large number of small Strings,use:StringBuffer.append()instead of theString +=operator. String is much slower because every time youconcatenate a string to another with += operator, a newStringBuffer is created under the hood. Depending on the numberof concatenations, a single explicit StringBuffer can be many timesfaster than multiple implicit StringBuffers created by Stringaddition.
  45. 45. Addition vs. Multiplication vs. Divisionfor (int i = 0; i < 500000; i++) { a = 1.23f; b = 1.45f; c = 0.004523f; c += a; a = b + c;}for (int i = 0; i < 500000; i++) { Average times spent in loops a = 1.23f; b = 1.45f; on Nokia Asha 305: c = 0.004523f; c *= a; Multiplying: 330 ms a = b * c;} Addition: 360 ms 9% slowerfor (int i = 0; i < 500000; i++) { a = 1.23f; Division: 560 ms 70% slower b = 1.45f; c = 0.004523f; c /= a; a = b / c;}
  46. 46. Switch vs. IfThe switch statement in C is implemented as a direct jump which isextremely fast. In Java on Nokia Series 40 phones, switches areimplemented at the bytecode level as a series of if statements.Therefore in many cases a switch statement is less efficient than amanually created series of if..else statements in which the firstpositive case is selected as the one which occurs more frequently. Ifyou prefer to use switch statements for code clarity, then arrangethem so that the most frequent cases appear first.
  47. 47. Live Demo Session» If you are watching these slides on SlideShare, next part is live coding demonstration with Nokia SDK 2.0 for Java and NetBeans. Full recording of the live session can be found at Nokia Developer website:» http://www.developer.nokia.com/Resources/Multimedia/Webinars.xhtml
  48. 48. › Andreas Jakl, NokiaSpecial thanks
  49. 49. Thank you!@MichaelSamarin

×