PDA

View Full Version : [SOLVED] Weird SDL_PollEvent behaviour with SDL_JOYAXISMOTION



Atien
April 7th, 2011, 02:09
Hi everyone,

From time to time, I'm working on my Frontier Elite 2 PSP port (http://www.atien.net/?static2/frontier), and this is one of those times.
As the game now works faster than before, I had to add a R-Trigger shortcut in order to slowdown the mouse cursor for better aim during space dogfight.

I handle the PSP keys with SDL_PollEvent, and this is where I have a little problem that maybe somebody knows about: I want the cursor moving slowlier when I press the Right trigger. My code is working, but the Rtrigger boolean is only taken in account when I change direction with the joystick.

I wrote down a little test program to illustrate my problem for anyone who is willing to help me moving the cursor the way I want.

Here it is:

#include <pspkernel.h>
#include <pspdebug.h>

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>

PSP_MODULE_INFO("SDL_event", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

int SetupCallbacks(void);
int exit_callback(int arg1, int arg2, void *common);
int CallbackThread(SceSize args, void *argp);

int main()
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);

SDL_Joystick *joystick = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *cursor = IMG_Load("image.png");
SDL_Event event;

int continuer = 1;
int Rtrigger = 0;

SDL_JoystickEventState(SDL_ENABLE);
joystick = SDL_JoystickOpen(0);

screen = SDL_SetVideoMode(480, 272, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

SDL_Rect position;
position.x = 25;
position.y = 84;

int motion_x = 0;
int motion_y = 0;

pspDebugScreenInit();
SetupCallbacks();

SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_Flip(screen);

while(continuer)
{
char cursorSpeedDivider = 2;
if (Rtrigger) cursorSpeedDivider = 6;

while (SDL_PollEvent (&event)) {
switch (event.type) {
case SDL_JOYBUTTONDOWN:
if (event.jbutton.button == 5) Rtrigger = 1;
if (event.jbutton.button == 11) continuer = 0;
break;
case SDL_JOYBUTTONUP:
if (event.jbutton.button == 5) Rtrigger = 0;
break;
case SDL_JOYAXISMOTION:
switch (event.jaxis.axis) {
case 0:
motion_x = abs(event.jaxis.value) * event.jaxis.value / (100000000 * cursorSpeedDivider);
break;
case 1:
motion_y = abs(event.jaxis.value) * event.jaxis.value / (100000000 * cursorSpeedDivider);
break;
}
break;
}
}

position.x += motion_x;
if (position.x < 1) position.x = 1;
if (position.x > 470) position.x = 470;
position.y += motion_y;
if (position.y < 2) position.y = 2;
if (position.y > 260) position.y = 260;

SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_BlitSurface(cursor, NULL, screen, &position);
SDL_Flip(screen);

SDL_Delay(10);
}

SDL_JoystickClose(joystick);
SDL_Quit();
sceKernelExitGame();
return 0;
}

int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0) sceKernelStartThread(thid, 0, 0);
return thid;
}And the makefile :

TARGET = SDL_PollEvent
PSPSDK = $(shell psp-config --pspsdk-path)
PSPBIN = $(PSPSDK)/../bin
SDL_CONFIG = $(PSPBIN)/sdl-config

OBJS = main.o

DEFAULT_CFLAGS = -I/usr/local/pspdev/psp/include/SDL
CFLAGS = $(DEFAULT_CFLAGS) -G4 -Wall -O3
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

PSPSDK = $(shell psp-config --pspsdk-path)
PSPBIN = $(PSPSDK)/../bin
SDL_CONFIG = $(PSPBIN)/sdl-config

LIBDIR =
LDFLAGS =
STDLIBS= -lSDLmain -lSDL_image -lSDL -lGL -lpng -ljpeg -lz -lm\
-lstdc++ -lpspgu -lpspvfpu -lpsprtc -lpsphprm -lpspaudio -lpspirkeyb -lpsppower
LIBS=$(STDLIBS)$(YOURLIBS)

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = SDL_PollEvent

BUILD_PRX = 1
PSP_LARGE_MEMORY = 1
PSP_FW_VERSION = 371
include $(PSPSDK)/lib/build.makAs you see, it is quite simple. Not optimised at all, but still...
You also need some whatever little image.png you want to move around inside your folder.

As explained before, with this program you can move around the "cursor" with the joystick, and slow it down by pressing the R-Trigger. But the problem is that the cursor switches speed only when you change joystick direction. Otherwise, the trigger isn't taken in account...

Do somebody knows how to get rid of that problem?
Thank you very much!

JLF65
April 20th, 2011, 06:01
It seems to me your problem is you only use the divisor when the stick changes direction. Instead, use it where the motion is added, like this:


while(continuer)
{
char cursorSpeedDivider = 2;
if (Rtrigger) cursorSpeedDivider = 6;

while (SDL_PollEvent (&event)) {
switch (event.type) {
case SDL_JOYBUTTONDOWN:
if (event.jbutton.button == 5) Rtrigger = 1;
if (event.jbutton.button == 11) continuer = 0;
break;
case SDL_JOYBUTTONUP:
if (event.jbutton.button == 5) Rtrigger = 0;
break;
case SDL_JOYAXISMOTION:
switch (event.jaxis.axis) {
case 0:
motion_x = abs(event.jaxis.value) * event.jaxis.value / (100000000);
break;
case 1:
motion_y = abs(event.jaxis.value) * event.jaxis.value / (100000000);
break;
}
break;
}
}

position.x += motion_x / cursorSpeedDivider;
if (position.x < 1) position.x = 1;
if (position.x > 470) position.x = 470;
position.y += motion_y / cursorSpeedDivider;
if (position.y < 2) position.y = 2;
if (position.y > 260) position.y = 260;

SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_BlitSurface(cursor, NULL, screen, &position);
SDL_Flip(screen);

SDL_Delay(10);
}


EDIT: Faster code would only do the divide when it needed to be, like this:


while(continuer)
{
while (SDL_PollEvent (&event)) {
switch (event.type) {
case SDL_JOYBUTTONDOWN:
if (event.jbutton.button == 5) {
motion_x = motion_xx / 6;
motion_y = motion_yy / 6;
Rtrigger = 1;
}
if (event.jbutton.button == 11) continuer = 0;
break;
case SDL_JOYBUTTONUP:
if (event.jbutton.button == 5) {
motion_x = motion_xx / 2;
motion_y = motion_yy / 2;
Rtrigger = 0;
}
break;
case SDL_JOYAXISMOTION:
switch (event.jaxis.axis) {
case 0:
motion_xx = abs(event.jaxis.value) * event.jaxis.value / (100000000);
motion_x = motion_xx / (Rtrigger ? 6 : 2);
break;
case 1:
motion_yy = abs(event.jaxis.value) * event.jaxis.value / (100000000);
motion_y = motion_yy / (Rtrigger ? 6 : 2);
break;
}
break;
}
}

position.x += motion_x;
if (position.x < 1) position.x = 1;
if (position.x > 470) position.x = 470;
position.y += motion_y;
if (position.y < 2) position.y = 2;
if (position.y > 260) position.y = 260;

SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_BlitSurface(cursor, NULL, screen, &position);
SDL_Flip(screen);

SDL_Delay(10);
}

Atien
April 25th, 2011, 21:34
Thank you JLF65, I just saw your response and it's working like a charm!
I'm adding this to Frontier right away :)

JLF65
April 26th, 2011, 00:42
No problem. Glad to help; it's always good to see updates to ports. :)

jhayprince07
April 26th, 2011, 14:38
tnx :)