Calibrate tilt on iphone?

Previous topic - Next topic

mykyl66

Hi,
I am doing some test code for compiling on the touch. I can move a rectangle around the screen no problem using the joystick commands. My issue is this.

I would like to offer the ability to calibrate the screen according to the angle the player is holding his touch.

e.g. If I lay the touch on the table and start the game there is a rectangle sitting in the center of the screen. When I tilt the screen the rectangle moves around. (I can already do this).

Now I want to hold the touch in my hand in a comfortable position and when I start the game no matter what position I am holding the touch in I want the rectangle to once again be in the center of the screen. and play the same way as before. Of course the rectangle Must stay within the screen area.

So far I can get it to start in the center regardless of the angle I am holding the touch by setting an offset but for some stupid reason the whole screen is being offset.

How are you folks doing this calibration type thing.

Thanks.

Mike R

Kitty Hello

get the accelerations for the "still" state. Then subtract these from the actual accelleration on each run.

I think to make it really work, you need to make a rotation matrix for the "is" state, then invert that and multiply the current state with the invese matrix each time. Overkill IMO.

MrTAToad

The (demo) of the games I've played on the iPhone haven't had any sort of calibration system, so I dont think its really needed.


mykyl66

#3
@Kitty Hello

I didn't really understand a word of what you just said  :-[ , but I think we're talking at cross purposes.

@MrTAToad

Most any game I have played that make use of the accelerometer in them have a form of calibration in them, whether that is presented to the user with a calibration screen (not usually) or whether it's all handled behind the scenes.

And that is what I am trying to do.

What I mean is this... (hopefully this makes some sense!):

If I draw my rectangle somewhere from 0 to 480 down the screen based upon getjoyy(), I can say that center is (screenheight/2) or 240, and I can draw it above or below that depending on joystick y value.

But (without ANY form of calibration) - and this is the crucial point - this assumes that the center value was 0,0 when we started, or to put it another way, that the iPod is lying flat on a table.

Now what if the iPod is being held at an angle that is comfortable to the user when we start? In my experience, this is exactly what most accelerometer based games allow, using a simple internal calibration of the type I am describing and trying to implement.

It's trivial to capture this x and y 'home position' value as we go into the game. But this means that the rectangle will, for example, travel only halfway down the screen when tilted down on y, and go completely off the screen when tilted up on y, based upon our 'perfect' calculations that assumed a 0,0 center.

I guess what I'm asking is how do you, mathematically speaking, scale a joystick movement based upon a center offset so that the total travel in any given direction still equals the edge of the screen?

See, I know what I'm trying to do, really, it's just the math eludes me! :S

Mike


matchy

In regards to calibrating the screen angle viewing position, that is so that you can play at any angle, for example: sitting as 30 degrees or lying down at 120 degrees.

To simply put describe it; store the still getjoyy() values when the screen is tapped then subract the still getjoyy() values from the current getjoyy() values.

mykyl66

#5
I am guessing nobody is really understanding what the problem is so here is the test code.

If you compile and run it you will see the issue. No neatening up has been done or anything. Its rough and ready test code.

When you run it (Portrait mode) hold your touch comfortably then touch the screen and you will see the red rectangle is in the center of the screen as expected no matter the angle your holding the touch at, however although it will move as you tilt all the way to the bottom it will NOT move to the top of the screen.

If you start it while having it laid down flat on the desk everything will work as expected.

Hopefully this will give you folks an understanding as to what is wrong.

Cheers

Mike R

Code (glbasic) Select
// --------------------------------- //
// Project: accel-test
// Start: Wednesday, December 09, 2009
// IDE Version: 7.198

SETCURRENTDIR("Media") // seperate media and binaries?

SYSTEMPOINTER TRUE

LOADFONT "font.png",1
SETFONT 1
SETSCREEN 320,480,0
GETSCREENSIZE sx,sy

lb1 = 0

WHILE TRUE

JOYSTATE joy_x, joy_y, joy_a, joy_b; // Variablen joy_x - joy_b     / Variables jox_x - joy_b
                                      // mit Joystick-Werten füllen  / filled with joysick state
jx# = (DecimalPower(GETJOYX(0),5) * 100.0)
jy# = (DecimalPower(GETJOYY(0),5) * 100.0)
jz# = (DecimalPower(GETJOYZ(0),5) * 100.0)

jrx# = (DecimalPower(GETJOYRX(0),5) * 100.0)
jry# = (DecimalPower(GETJOYRY(0),5) * 100.0)
jrz# = (DecimalPower(GETJOYRZ(0),5) * 100.0)

MOUSESTATE mx,my,b1,b2

IF lb1=1 AND b1 = 0
GOTO cal
ENDIF

PRINT "x = " + jx#,20,120
PRINT "y = " + jy#,20,140
PRINT "z = " + jz#,20,1

SHOWSCREEN

lb1 = b1

WEND

cal:
calibrate()
rectSize = 25
rectColor = 255

rectX = (sx/2)-(rectSize/2)
rectY = (sy/2)-(rectSize/2)

xIncrement = (sx/2) / 100
yIncrement = (sy/2) / 100

// -100 to 0 is sx/2 = 160/100

start:

DRAWRECT rectX - jxCenter#,rectY - jyCenter#,rectSize,rectSize,rectColor

noJoySticks% = GETNUMJOYSTICKS()
nameJoyStick$ = GETJOYNAME$(0)

JOYSTATE joy_x, joy_y, joy_a, joy_b; // Variablen joy_x - joy_b     / Variables jox_x - joy_b
                                      // mit Joystick-Werten füllen  / filled with joysick state

jx# = (DecimalPower(GETJOYX(0),5) * 100.0)
jy# = (DecimalPower(GETJOYY(0),5) * 100.0)
jz# = (DecimalPower(GETJOYZ(0),5) * 100.0)

jrx# = (DecimalPower(GETJOYRX(0),5) * 100.0)
jry# = (DecimalPower(GETJOYRY(0),5) * 100.0)
jrz# = (DecimalPower(GETJOYRZ(0),5) * 100.0)

LET text$="";
  IF joy_x=-1; LET text$="LEFT";   ENDIF;
  IF joy_x= 1; LET text$="RIGHT";  ENDIF;
  IF joy_y=-1; LET text$="UP";     ENDIF;
  IF joy_y= 1; LET text$="DOWN";      ENDIF;
  IF joy_a= 1; LET text$="BUTTON A"; ENDIF;
  IF joy_b= 1; LET text$="BUTTON B"; ENDIF;

PRINT nameJoyStick$,0,0
PRINT "No Joysticks = " + noJoySticks%,0,20

PRINT "JOYSTICK:",100,80;
PRINT text$, 100,100;
PRINT "x = " + jx#,20,120
PRINT "y = " + jy#,20,140
PRINT "z = " + jz#,20,160

PRINT "xr = " + jrx#,20,200
PRINT "yr = " + jry#,20,220
PRINT "zr = " + jrz#,20,240

PRINT "xC = " + jxCenter#,20,280
PRINT "yC = " + jyCenter#,20,300
PRINT "zC = " + jzCenter#,20,320

IF jx# > jxCenter# + -5.0 AND jx# < jxCenter# + 5.00 THEN PRINT "(C)",200,120
IF jy# > jyCenter# + -5.0 AND jy# < jyCenter# + 5.00 THEN PRINT "(C)",200,140

PRINT joy_a+" - "+joy_b+" - "+joy_x+" - "+joy_y,50, 50

SHOWSCREEN;

// jxCenter# = sx/2

// jyCenter# = sy/2

// 40 = sy/2

rectCx = (sx/2)
rectCy = (sy/2)

rectX = (rectCx-(rectSize/2)) + (jx# * xIncrement) - jxCenter#// jxCenter#
rectY = (rectCy-(rectSize/2)) + (jy# * yIncrement) - jyCenter#// jyCenter#

GOTO start;

FUNCTION DecimalPower: Real_Number, Decimal_Power
//Round Down, a Decimal Number, to the nearest power of 10.
// The Decimal Power must be a power of 10, ie: 1 2 3 4 etc

RETURN INTEGER( Real_Number * POW( 10, Decimal_Power ) ) / POW( 10, Decimal_Power )

ENDFUNCTION

FUNCTION calibrate:

lb1 = 0
WHILE TRUE
BLACKSCREEN
PRINT "Touch to set ZERO position",20,100
SHOWSCREEN
MOUSESTATE mx,my,b1,b2
IF lb1=1 AND b1 = 0
jxCenter# = (DecimalPower(GETJOYX(0),5) * 100.0)
jyCenter# = (DecimalPower(GETJOYY(0),5) * 100.0)
jzCenter# = (DecimalPower(GETJOYZ(0),5) * 100.0)
GOTO jumpout
ENDIF
lb1 = b1
WEND

jumpout:

ENDFUNCTION