VbaGX Input Code Fix January 24, 2012 12:39PM | Registered: 12 years ago Posts: 4 |
u32 StandardMovement(unsigned short chan) { u32 J = 0; s8 pad_x = userInput[chan].pad.stickX; s8 pad_y = userInput[chan].pad.stickY; #ifdef HW_RVL s8 wm_ax = userInput[0].WPAD_StickX(0); s8 wm_ay = userInput[0].WPAD_StickY(0); #endif /*** Gamecube Joystick input, same as normal ***/ // Is XY inside the "zone"? if (pad_x * pad_x + pad_y * pad_y > PADCAL * PADCAL) { if (pad_y == 0) { if(pad_x > 0) { J |= VBA_RIGHT; } else if(pad_x < 0) { J |= VBA_LEFT; } } if (pad_x == 0) { if(pad_y > 0) { J |= VBA_UP; } else if(pad_y < 0) { J |= VBA_DOWN; } } if ((pad_x|pad_y) != 0) { if ((fabs((double)(pad_y) / (double)(pad_x))) < 2.41421356237) { if (pad_x >= 0) J |= VBA_RIGHT; else J |= VBA_LEFT; } if ((fabs((double)(pad_x) / (double)(pad_y))) < 2.41421356237) { if (pad_y >= 0) J |= VBA_UP; else J |= VBA_DOWN; } } } #ifdef HW_RVL /*** Wii Joystick (classic, nunchuk) input ***/ // OLD CODE: Doesn't work properly.. //// Is XY inside the "zone"? //if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL) //{ // /*** we don't want division by zero ***/ // if (wm_ay == 0) // { // if(wm_ax > 0) // { // J |= VBA_RIGHT; // printf("RIGHT"); // return J; // } // else if(pad_x < 0) // { // J |= VBA_LEFT; // printf("LEFT"); // return J; // } // } // if (wm_ax == 0) // { // if(wm_ay > 0) // { // J |= VBA_UP; // printf("UP"); // return J; // } // else if(pad_y < 0) // { // J |= VBA_DOWN; // printf("DOWN"); // return J; // } // } //// // if (wm_ax != 0 && wm_ay != 0) // { // if ((fabs((double)(wm_ay) / (double)(wm_ax))) < 2.41421356237) // { // if (wm_ax >= 0) // { // J |= VBA_RIGHT; // printf("RIGHT"); // return J; // } // else // { // J |= VBA_LEFT; // printf("LEFT"); // return J; // } // } // if ((fabs((double)(wm_ax) / (double)(wm_ay))) < 2.41421356237) // { // if (wm_ay >= 0) // { // J |= VBA_UP; // return J; // } // else // { // J |= VBA_DOWN; // return J; // } // } // } //} /// OLD CODE: Doesn't work properly. // Input Detected (NEW CODE) if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL) { // inside the 'valid direction' block. double angle = atan2(wm_ay, wm_ax); const double THRES = 1.0 / sqrt(2.0); if ( cos(angle) > THRES ) J |= VBA_RIGHT; else if ( cos(angle) < -THRES ) J |= VBA_LEFT; if ( sin(angle) > THRES ) J |= VBA_UP; else if ( sin(angle) < -THRES) J |= VBA_DOWN; } #endif return J; }
if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL) { // inside the 'valid direction' block. double angle = atan2(wm_ay, wm_ax); const double THRES = 1.0 / sqrt(2.0); if ( cos(angle) > THRES ) J |= VBA_RIGHT; else if ( cos(angle) < -THRES ) J |= VBA_LEFT; if ( sin(angle) > THRES ) J |= VBA_UP; else if ( sin(angle) < -THRES) J |= VBA_DOWN; }
Re: VbaGX Input Code Fix January 26, 2012 02:24AM | Registered: 12 years ago Posts: 4 |
static void decodepad (int chan) { int i, offset; float t; s8 pad_x = userInput[chan].pad.stickX; s8 pad_y = userInput[chan].pad.stickY; u32 jp = userInput[chan].pad.btns_h; #ifdef HW_RVL s8 wm_ax = userInput[chan].WPAD_StickX(0); s8 wm_ay = userInput[chan].WPAD_StickY(0); u32 wp = userInput[chan].wpad->btns_h; u32 exp_type; if ( WPAD_Probe(chan, &exp_type) != 0 ) exp_type = WPAD_EXP_NONE; #endif /*** Gamecube Joystick input ***/ // Is XY inside the "zone"? if (pad_x * pad_x + pad_y * pad_y > PADCAL * PADCAL) { /*** we don't want division by zero ***/ if (pad_x > 0 && pad_y == 0) jp |= PAD_BUTTON_RIGHT; if (pad_x < 0 && pad_y == 0) jp |= PAD_BUTTON_LEFT; if (pad_x == 0 && pad_y > 0) jp |= PAD_BUTTON_UP; if (pad_x == 0 && pad_y < 0) jp |= PAD_BUTTON_DOWN; if (pad_x != 0 && pad_y != 0) { /*** Recalc left / right ***/ t = (float) pad_y / pad_x; if (t >= -2.41421356237 && t < 2.41421356237) { if (pad_x >= 0) jp |= PAD_BUTTON_RIGHT; else jp |= PAD_BUTTON_LEFT; } /*** Recalc up / down ***/ t = (float) pad_x / pad_y; if (t >= -2.41421356237 && t < 2.41421356237) { if (pad_y >= 0) jp |= PAD_BUTTON_UP; else jp |= PAD_BUTTON_DOWN; } } } #ifdef HW_RVL /*** Wii Joystick (classic, nunchuk) input ***/ // Is XY inside the "zone"? if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL) { // inside the 'valid direction' block. double angle = atan2(wm_ay, wm_ax); const double THRES = 1.0 / sqrt(2.0); if ( cos(angle) > THRES ) wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_RIGHT : WPAD_BUTTON_RIGHT; else if ( cos(angle) < -THRES ) wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_LEFT : WPAD_BUTTON_LEFT; if ( sin(angle) > THRES ) wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_UP : WPAD_BUTTON_UP; else if ( sin(angle) < -THRES) wp |= (exp_type == WPAD_EXP_CLASSIC) ? WPAD_CLASSIC_BUTTON_DOWN : WPAD_BUTTON_DOWN; } #endif /*** Fix offset to pad ***/ offset = ((chan + 1) << 4); /*** Report pressed buttons (gamepads) ***/ for (i = 0; i < MAXJP; i++) { if ( (jp & btnmap[CTRL_PAD][CTRLR_GCPAD]) // gamecube controller #ifdef HW_RVL || ( (exp_type == WPAD_EXP_NONE) && (wp & btnmap[CTRL_PAD][CTRLR_WIIMOTE]) ) // wiimote || ( (exp_type == WPAD_EXP_CLASSIC) && (wp & btnmap[CTRL_PAD][CTRLR_CLASSIC]) ) // classic controller || ( (exp_type == WPAD_EXP_NUNCHUK) && (wp & btnmap[CTRL_PAD][CTRLR_NUNCHUK]) ) // nunchuk + wiimote #endif ) S9xReportButton (offset + i, true); else S9xReportButton (offset + i, false); } /*** Superscope ***/ if (Settings.SuperScopeMaster && chan == 0) // report only once { // buttons offset = 0x50; for (i = 0; i < 6; i++) { if (jp & btnmap[CTRL_SCOPE][CTRLR_GCPAD] #ifdef HW_RVL || wp & btnmap[CTRL_SCOPE][CTRLR_WIIMOTE] #endif ) { if(i == 3 || i == 4) // turbo { if((i == 3 && scopeTurbo == 1) || // turbo ON already, don't change (i == 4 && scopeTurbo == 0)) // turbo OFF already, don't change { S9xReportButton(offset + i, false); } else // turbo changed to ON or OFF { scopeTurbo = 4-i; S9xReportButton(offset + i, true); } } else S9xReportButton(offset + i, true); } else S9xReportButton(offset + i, false); } // pointer offset = 0x80; UpdateCursorPosition(chan, cursor_x[0], cursor_y[0]); S9xReportPointer(offset, (u16) cursor_x[0], (u16) cursor_y[0]); } /*** Mouse ***/ else if (Settings.MouseMaster && chan == 0) { // buttons offset = 0x60 + (2 * chan); for (i = 0; i < 2; i++) { if (jp & btnmap[CTRL_MOUSE][CTRLR_GCPAD] #ifdef HW_RVL || wp & btnmap[CTRL_MOUSE][CTRLR_WIIMOTE] #endif ) S9xReportButton(offset + i, true); else S9xReportButton(offset + i, false); } // pointer offset = 0x81; UpdateCursorPosition(chan, cursor_x[1 + chan], cursor_y[1 + chan]); S9xReportPointer(offset + chan, (u16) cursor_x[1 + chan], (u16) cursor_y[1 + chan]); } /*** Justifier ***/ else if (Settings.JustifierMaster && chan < 2) { // buttons offset = 0x70 + (3 * chan); for (i = 0; i < 3; i++) { if (jp & btnmap[CTRL_JUST][CTRLR_GCPAD] #ifdef HW_RVL || wp & btnmap[CTRL_JUST][CTRLR_WIIMOTE] #endif ) S9xReportButton(offset + i, true); else S9xReportButton(offset + i, false); } // pointer offset = 0x83; UpdateCursorPosition(chan, cursor_x[3 + chan], cursor_y[3 + chan]); S9xReportPointer(offset + chan, (u16) cursor_x[3 + chan], (u16) cursor_y[3 + chan]); } #ifdef HW_RVL // screenshot (temp) if (wp & CLASSIC_CTRL_BUTTON_ZR) S9xReportButton(0x90, true); else S9xReportButton(0x90, false); #endif }
Re: VbaGX Input Code Fix January 26, 2012 05:13AM | Moderator Registered: 14 years ago Posts: 686 |
Re: VbaGX Input Code Fix January 26, 2012 10:21AM | Registered: 12 years ago Posts: 4 |
Point p = new Point(0, -100); double Angle = Math.Atan2(p.Y, p.X); double Thresh = 1.0 / Math.Sqrt(2.0); if ( Math.Cos(Angle) > Thresh ) Console.WriteLine("Right"); else if ( Math.Cos(Angle) < -Thresh ) Console.WriteLine("Left"); else if ( Math.Sin(Angle) > Thresh ) Console.WriteLine("Up"); else if ( Math.Sin(Angle) < -Thresh) Console.WriteLine("Down"); double Result1 = Math.Sin(Angle); double Result2 = Math.Cos(Angle); Console.WriteLine(String.Format("Angle: {0}\n Sin: {1}\n Cos: {2}\n Threshold: {3}\n", Angle, Result1, Result2, Thresh));
Down Angle: -1.5707963267949 Sin: -1 Cos: 6.12303176911189E-17 Threshold: 0.707106781186547
Re: VbaGX Input Code Fix January 27, 2012 08:25PM | Registered: 12 years ago Posts: 4 |
Re: VbaGX Input Code Fix February 02, 2012 02:02AM | Registered: 13 years ago Posts: 282 |
Quote
tueidj
This seems kind of backwards; you start with wm_ax and wm_ay which you use to find the angle, then you take the sine and cosine... doesn't that just give you back the original wm_ax and wm_ay values?
Re: VbaGX Input Code Fix February 02, 2012 03:44AM | Moderator Registered: 14 years ago Posts: 686 |
Quote
Axel
There is a flaw in your math logic. The sine and cosine of an angle don't give you the value of X and Y, it gives you a decimal value between -1 and 1.
1) The inverse Tan of x/y gives you the angle
2) The sine of the angle gives you a value between -1 (full down) and 1 (full up)
3) The cosine of the angle gives you a value between -1 (full left) and 1 (full right)
4) The Threshold calculated is a 45 degrees angle (1 / square root of 2). If the joystick has an inclination of more than 45 degrees in any direction, it activates the press of that direction.
I hope this explanation makes it clearer on why this new approach works.
if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL)It's not checking an angle or "inclination", it's the magnitude of the stick compared to the center position i.e. if the stick has been pushed far enough to register as a digital movement.