Results 1 to 5 of 5

Thread: One way to do programmable control inputs in games :)

  1. #1

    One way to do programmable control inputs in games :)

    If anyone is interested in how I have done my configurable inputs for my PGDAnnual entry, Day Of Destruction!, this is how:

    First, I have these types/constants:

    [pascal]
    {...}Const
    cLeftButton = 1;
    cMiddleButton = 2;
    cRightButton = 3;

    cButton1 = 1;
    cButton2 = 2;
    cButton3 = 3;
    cButton4 = 4;
    cButton5 = 5;
    cButton6 = 6;
    cButton7 = 7;
    cButton8 = 8;
    cButton9 = 9;
    cButton10 = 10;
    {...}
    Type
    {................................................. .............................}
    TControl = (
    eControl_InsertCredit,
    eControl_StartGame,
    eControl_PrimaryWeapon,
    eControl_SecondaryWeapon,
    eControl_HighScoreClick,
    eControl_TakeScreenshot
    );
    {................................................. .............................}

    {................................................. .............................}
    TInputType = (
    eInputType_Mouse,
    eInputType_Joystick,
    eInputType_Keyboard
    );
    {................................................. .............................}

    {................................................. .............................}
    Const
    cControlStr : Array[TControl] Of AnsiString = (
    'insert_credit',
    'start_game',
    'primary_weapon',
    'secondary_weapon',
    'highscore_click',
    'take_screenshot'
    );
    [/pascal]

    I have this array in my game which uses the control and input types from above:

    [pascal] FControls : Array[TControl,TInputType] Of Integer;[/pascal]

    I have these routines in my game to get/set the FControls array:

    [pascal]Function TGame.GetControl(Const AControl : TControl;
    Const AInputType : TInputType) : Integer;
    Begin
    Result := FControls[AControl,AInputType];
    End;
    {................................................. .............................}

    {................................................. .............................}
    Procedure TGame.SetControl(Const AControl : TControl;
    Const AInputType : TInputType;
    Const AValue : Integer);

    Begin
    FControls[AControl,AInputType] := AValue;
    End;
    [/pascal]

    I have these routines that do the actual parsing of my control input type strings and call SetControl():

    [pascal]
    Function SDLKeyFromStr(Const Str : AnsiString) : Integer;
    Var
    i : Integer;
    Name : AnsiString;
    Begin
    Result := -1;
    For i := 0 To High(Word) Do
    Begin
    Name := StringReplace(LowerCase(SDL_GetKeyName(i)),'sdlk_' ,'',[]);
    If Name = LowerCase(Str) Then
    Begin
    Result := i;
    Exit;
    End;
    End;
    End;
    {................................................. .............................}

    {................................................. .............................}
    Procedure TGame.ParseControlInput(Const AControl : TControl; AValueStr : AnsiString);
    Begin
    If Pos('mb_',AValueStr) = 1 Then
    Begin
    Delete(AValueStr,1,Length('mb_'));
    If AValueStr = 'left' Then
    SetControl(AControl,eInputType_Mouse,cLeftButton)
    Else
    If AValueStr = 'middle' Then
    SetControl(AControl,eInputType_Mouse,cMiddleButton )
    Else
    If AValueStr = 'right' Then
    SetControl(AControl,eInputType_Mouse,cRightButton)
    End
    Else
    If Pos('jb_',AValueStr) = 1 Then
    Begin
    Delete(AValueStr,1,Length('jb_'));
    Try
    SetControl(AControl,eInputType_Joystick,cButton1 + (StrToInt(AValueStr) - cButton1));
    Except
    SetControl(AControl,eInputType_Joystick,cButton1);
    End;
    End
    Else
    If Pos('kb_',AValueStr) = 1 Then
    Begin
    Delete(AValueStr,1,Length('kb_'));
    SetControl(AControl,eInputType_Keyboard,SDLKeyFrom Str(AValueStr));
    End;
    End;[/pascal]

    I have this code below that reads in the .ini file control inputs and uses the above routines:

    [pascal]Type
    {................................................. .............................}
    TParseControlInput = Procedure(Const AControl : TControl; AValueStr : AnsiString) Of Object;
    {................................................. .............................}

    {................................................. .............................}

    {................................................. .............................}
    Procedure GetControlInputs(Const AIniFile : TIniFile;
    Const AControl : TControl;
    Const ADefault : AnsiString;
    Const AParseInput : TParseControlInput);
    Var
    InputTypeStr : AnsiString;
    sl : TStringList;
    i : Integer;
    Begin
    sl := TStringList.Create;
    Try
    sl.CommaText := LowerCase(AIniFile.ReadString('controls',cControlS tr[AControl],ADefault));
    For i := 0 To sl.Count - 1 Do
    Begin
    InputTypeStr := sl.Strings[i];
    AParseInput(AControl,InputTypeStr);
    End;
    Finally
    sl.Free;
    End;
    End;[/pascal]

    Here is the final bits of code to use the GetControlInput() routine:

    [pascal]
    ConfigFile := TIniFile.Create(ModulePath + ChangeFileExt(ModuleName,'.ini'));
    Try
    SDL_Init(SDL_INIT_VIDEO Or SDL_INIT_AUDIO Or SDL_INIT_JOYSTICK);

    FullScreen := ConfigFile.ReadBool('settings','fullscreen' ,False);
    Game.MusicEnabled := ConfigFile.ReadBool('settings','music_enabled',Tru e);
    Game.SoundEnabled := ConfigFile.ReadBool('settings','sound_enabled',Tru e);
    Game.FPSEnabled := ConfigFile.ReadBool('settings','fps_enabled' ,True);

    GetControlInputs(ConfigFile,eControl_HighscoreClic k ,'kb_lctrl,kb_rctrl,left_jb_,jb_1' ,Game.ParseControlInput);

    GetControlInputs(ConfigFile,eControl_PrimaryWeapon ,'mb_left,jb_1' ,Game.ParseControlInput);
    GetControlInputs(ConfigFile,eControl_SecondaryWeap on,'mb_right,jb_2' ,Game.ParseControlInput);

    GetControlInputs(ConfigFile,eControl_InsertCredit ,'kb_c,mb_right,jb_9' ,Game.ParseControlInput);
    GetControlInputs(ConfigFile,eControl_StartGame ,'kb_1,mb_left,jb_10' ,Game.ParseControlInput);
    GetControlInputs(ConfigFile,eControl_TakeScreensho t ,'kb_s,jb_5' ,Game.ParseControlInput);

    SDL_Quit;
    Finally
    ConfigFile.Free;
    End;[/pascal]

    Here is an example of me checking the Controls array to see if the input(s) match to do different actions:

    [pascal]Procedure TState_PlayGame.OnJoystickUp(Which: UInt8; Button: UInt8; State: SInt16);
    Const
    cInputType = eInputType_Joystick;
    Var
    Game : TGame;
    x,y : Single;
    Begin
    Game := TGame(FOwner);
    x := FCrossHairs.x;
    y := FCrossHairs.y;

    If Button = Game.Control[eControl_PrimaryWeapon,cInputType] Then
    FirePrimaryWeapon(x,y,Button,Ord(cInputType))
    Else
    If Button = Game.Control[eControl_SecondaryWeapon,cInputType] Then
    FireSecondaryWeapon(x,y,Button,Ord(cInputType));
    End;[/pascal]

    Maybe I will encapsulate some of that code into a TControl (or similar) class to make it a bit neater, but for now it works just fine

    I hope this helps someone else

    cheers,
    Paul

  2. #2

    Re: One way to do programmable control inputs in games :)

    30 views and no comments?

  3. #3

    Re: One way to do programmable control inputs in games :)

    I am using a similar system, which supports both buttons and axises (what is the english plural for axis ?). Axises can be used to handle mouse coordinates or analog sticks on a gamepad. You can Bind and Unbind certain keycodes (or axiscodes) like N3DKEY_ESCAPE or N3DKEY_SPACE to a slot with a number between 0..31.
    In consequence, you can call KeyState(Slot) or AxisState(Slot) to retrieve a keystate (Press, Pressed, Release, Released) for the key's or a Float value between 0..1 for the axises. Finally, the module can also handle text input.

    My system is based on DirectInput, but I might make a similar system with SDL in the future.

    You're code looks good, but I don't need it ATM.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  4. #4

    Re: One way to do programmable control inputs in games :)

    Quote Originally Posted by chronozphere
    I am using a similar system, which supports both buttons and axises (what is the english plural for axis ?). Axises can be used to handle mouse coordinates or analog sticks on a gamepad. You can Bind and Unbind certain keycodes (or axiscodes) like N3DKEY_ESCAPE or N3DKEY_SPACE to a slot with a number between 0..31.
    In consequence, you can call KeyState(Slot) or AxisState(Slot) to retrieve a keystate (Press, Pressed, Release, Released) for the key's or a Float value between 0..1 for the axises. Finally, the module can also handle text input.

    My system is based on DirectInput, but I might make a similar system with SDL in the future.

    You're code looks good, but I don't need it ATM.
    That's fine, I wasn't expecting anyone to suddenly use it, LOL!

    Yours sounds neat...any code snippets you could share?

    BTW, I believe the plural for axis is axii

    cheers,
    Paul

  5. #5
    Legendary Member NecroDOME's Avatar
    Join Date
    Mar 2004
    Location
    The Netherlands, Eindhoven
    Posts
    1,059

    Re: One way to do programmable control inputs in games :)

    I have a kind of similar approach, but I bind my keys at runtime to 'actions'.
    NecroSOFT - End of line -

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •