3. About
Game
Pausing
• Pause
game
when
– Phone
rings
– Back
–
buHon
is
pressed
• Remember
that
MIDlet's
pauseApp
–
method
is
never
called!
• In
GameCanvas,
implement
following
– public void showNotify() // resume
– public void hideNotify() // pause
4. About
Gameloop
and
Threading
• Gameloop
is
implemented
using
Threading
– Thread thread = new Thread(Runnable x);
– thread.start(); // calls run()
• Gameloop
usually:
– while(gameIsOn) { ….
Thread.sleep(ticks); }
• How
to
pause
the
current
thread
in
midp?
5. Synchroniza%on
• Let's
first
look
at
synchroniza5on.
• There
might
be
a
problem,
if
two
threads
accesses
the
same
data
– Two
people
each
have
a
ATM
cards
that
are
linked
to
only
one
account
– What
happens
when
these
two
people
accesses
the
account
at
the
same
%me?
• Withdrawal
is
two-‐step
process
– Check
the
balance
– If
there's
enough
money
int
the
account,
make
the
withdrawal
• What
happens
if
1
and
2
are
separated?
6. Locks
• We
must
guarantee
that
the
two
steps
are
never
split
apart.
Use
synchronized
keyword
• Synchroniza%on
works
with
locks.
Every
object
has
a
lock.
If
one
thread
has
picked
up
the
lock,
no
other
thread
can
use
the
synchronized
code.
7. Examples
• Let's
look
at
some
synchroniza%on
examples
– https://dl.dropboxusercontent.com/u/
874087/game-programming/examples/
threading/Synchronized1.java
• See
also
– Synchronized2.java -> Synchronized5.java
8. wait()
• Object
class
holds
a
method
wait()
– Causes
the
current
thread
to
wait
un%l
another
thread
invokes
the
no%fy()
method
for
this
object
• So
when
calling
wait()
it
pauses
the
current
thread
and
waits
that
some
other
thread
calls
no%fy()
or
no%fyAll()!
9. // NOTICE! This example does not work, all exception handling and synchronized blocks
// are missing
class MyApp {
public static void main(String [] args) {
new MyApp();
}
public MyApp() {
MyThread mythread;
Thread thread = new Thread(mythread = new MyThread());
thread.start();
System.out.println("Sleeping");
Thread.sleep(2000);
// Resume from wait! Calls notify from the object that is in wait…
mythread.notify();
}
}
class MyThread implements Runnable {
public void run() {
// Let's wait until someone calls notify
wait();
System.out.println("Resumed!");
}
}
10. wait()
• When
calling
wait
and
no%fy,
it
must
be
inside
synchronized
block.
synchronized(this) {
// Before calling notify, the thread calling this must
// own a lock.
notify();
}
synchronized(this) {
wait();
}
11. Game
Pausing
in
MIDlet
• In
GameCanvas,
following
methods
are
called
when
phone
rings.
// Phone rings
public void hideNotify()
{
pause(); // pause game – my own method
}
// Phone ends
public void showNotify()
{
resume(); // resume game – my own method
}
12. pause() and
resume()
public void resume() {
isPause = false;
synchronized(this) {
notify(); // Notify that waiting thread can
// continue.
}
}
public void pause() {
isPause = true;
}
13. Game
Loop
public void run() {
int i = 0;
while(true) {
checkIfPause();
checkCollisions();
moveSprites();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void checkIfPause() {
synchronized(this) {
while(isPause) { // while, just in case
try {
wait(); // Wait in current thread
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
14. Back
BuHon
to
Game
Canvas
Command backCommand = new Command("Back",
Command.BACK,
0);
addCommand(backCommand);
setCommandListener(this);
// and the listener method
public void commandAction(Command c, Displayable d) {
if(isPause) {
midlet.notifyDestroyed();
} else {
pause();
}
}
16. Adjus%ng
Device's
Orienta%on
• MIDlets
can
use
Orienta5on
API
to
– Change
their
UI
orienta%on
– Determine
their
current
UI
orienta%on
– Determine
the
current
display
orienta%on
– Receive
a
no%fica%on
whenever
the
display
orienta%on
changes
• When
MIDlet
changes
it's
UI
orienta%on,
it
has
to
redraw
the
low-‐level
components
that
it
uses.
18. Se^ng
UI
Orienta%on
• Add
following
to
JAD
file:
– Nokia-MIDlet-App-Orientation: manual
• Now
it
supports
both
portrait
and
landscape
modes
• Add
orienta%on
listener
– Orientation.addOrientationListener(orientationListener);
19. Orienta%on
Listener
Callback
/** Orientation listener callback */
public void displayOrientationChanged( int newDisplayOrientation ){
/** Check display orientation */
switch( newDisplayOrientation ){
case Orientation.ORIENTATION_PORTRAIT:
case Orientation.ORIENTATION_PORTRAIT_180:
/** Change MIDlet UI orientation to portrait */
Orientation.setAppOrientation(Orientation.ORIENTATION_PORTRAIT);
break;
case Orientation.ORIENTATION_LANDSCAPE:
case Orientation.ORIENTATION_LANDSCAPE_180:
/** Change MIDlet UI orientation to landscape */
Orientation.setAppOrientation(Orientation.ORIENTATION_LANDSCAPE);
break;
}
}
20. sizeChanged()
• When
UI
Orienta%on
changes:
/** Java platform will call this when UI orientation has been changed */
protected void sizeChanged( int w, int h ){
/** Acquiring new Graphics Object since old is not valid anymore */
g = getGraphics( );
canDraw = true;
}
22. Mobile
Sensors
• Mobile
Sensor
API
allows
MIDlets
to
fetch
data
from
the
sensors
of
the
mobile
device
• Sensor
consists
of
one
or
more
channels,
in
accelerometer
you
will
get
data
from
three
channels
(x,
y
and
z)
• Sensors
have
common
proper%es:
– accuracy
– max
and
min
value
23. Available
Sensors
in
Asha
50X
• Accelera5on
sensor
– measures
accelera%on
in
SI
units
for
x,
y
and
z
-‐
axis.
• Orienta5on
sensor
– provides
informa%on
of
devices
current
orienta%on
posi%on.
• Rota5on
sensor
– provides
informa%on
of
devices
current
rota%on
degree.
• Double
tapping
sensor
– provides
informa%on
of
double
taps
occurred
on
the
phone
sides.
• Proximity
sensor
– indicates
if
an
obstacle
is
right
in
front
of
it
• BaLery
sensor
– shows
baHery
charge
level
in
percentage.
Sensor
is
always
on.
• Charger
sensor
– shows
whether
charger
is
connected.
Sensor
is
always
on.
• Signal
strength
sensor
– shows
strength
of
network
connec%on
in
percentage.
Sensor
is
always
on.
25. Finding
and
Iden%fying
a
Sensor
// Find all sensors
SensorInfo[] sensorInfos =
SensorManager.findSensors(null, null);
for(int i=0; i<sensorInfos.length; i++) {
SensorInfo si = sensorInfos[i];
System.out.println(si.getUrl());
}
26. Finding
and
Iden%fying
a
Sensor
// Sensor type (quantity):
//
acceleration
//
orientation
//
rotation
//
double_tap
//
proximity
//
battery_charge
//
charger_state
//
network_field_intensity
//
null
String type = "acceleration";
// Sensor Context type
//
ambient
//
device
//
user
//
vehicle
//
null
String contextType = "user";
// Fetch all sensors with given information, should find only one.
SensorInfo[] si = SensorManager.findSensors(type, contextType);
// Retrieve the sensor url.
String sensorURL = si[0].getUrl();
27. Opening
a
sensor
connec%on
{
try {
// This may not be a good idea, fetch the URL from sensorinfo using sensor quantity and
// context type
String sensorURL = "sensor:acceleration;contextType=user;model=Nokia;location=NoLoc";
// How fast data is sent to listener!
final int BUFFER_SIZE = 1;
SensorConnection sensorConnection = (SensorConnection)Connector.open(sensorURL);
// this = any object that implements DataListener
sensorConnection.setDataListener(this, BUFFER_SIZE);
} catch (IOException e) {
e.printStackTrace();
}
}
// Datalistener interface method
public void dataReceived(SensorConnection sensor, Data[] data,
boolean isDataLost) {
System.out.println("Here!");
}
28. Case:
Accelera%on
listening
public void dataReceived(SensorConnection sensor, Data[] data,
boolean isDataLost) {
// We have three channels.
System.out.println("Channel amount: " + data.length);
// Channel is Data object
Data x = data[0];
// Each channel may hold several values. In this case
// only one.
double [] values = x.getDoubleValues();
System.out.println("Number of values " + values.length);
// And the value is:
System.out.println("x = " + values[0]);
// Let's fetch the rest (y and z) in just on line
System.out.println("y = " + data[1].getDoubleValues()[0]);
System.out.println("z = " + data[2].getDoubleValues()[0]);
}
32. Really
Easy
to
Use
// STEP 1: Defines a GestureInteractiveZone for the
// whole screen and all Gesture types.
GestureInteractiveZone giz = new
GestureInteractiveZone( GestureInteractiveZone.GESTURE_ALL );
// STEP 2: Register the GestureInteractiveZones for the
// GameCanvas object this.
GestureRegistrationManager.register( this, giz );
// STEP 3: Set the listener, source is this gamecanvas
// and listener is this also
GestureRegistrationManager.setListener(this, this);