Page 2 of 2 FirstFirst 12
Results 11 to 20 of 20

Thread: Making an input devices manager

  1. #11

    Making an input devices manager

    Quote Originally Posted by Brainer
    What do you think of it? And how do I read the pressed keys? :?
    As someone else wrote, I would largely prefer a solution that used the windows message system. But well, you would probably have to poll some device anyways so the update procedure makes sense.

    I like eventhandlers. Have some OnKeyDown, OnKeyUp, OnMouseMove, etc

    Eventually you could add threading for joystick reading?
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  2. #12

    Making an input devices manager

    I went for event handlers, too. Here's the code - just in case someone needed it.
    [pascal]
    unit UBEInput;
    {TODO 2 -oPatrick Nusbaum -cInput devices : Add gamepad support.}

    interface

    uses
    Windows;

    type
    { .: TKeyEvent :. }
    TKeyEvent = (keKeyDown, keKeyUp);

    { .: TMouseEvent :. }
    TMouseEvent = (meMove, meLeftButtonDown, meLeftButtonUp, meMiddleButtonDown,
    meMiddleButtonUp, meRightButtonDown, meRightButtonUp);

    { .: TInputSystem :. }
    TInputSystem = class(TObject)
    private
    { Private declarations }
    FKeys: array[0..255] of Boolean;
    FMouseButtons: array[0..2] of Boolean;
    FMouseX, FMouseY: Integer;
    public
    { Public declarations }
    constructor Create();

    procedure ProcessKeyboard(const KeyEvent: TKeyEvent; const TheKey: Word);
    procedure ProcessMouse(const MouseEvent: TMouseEvent; const X, Y: Integer);

    function IsKeyDown(const AKeyCode: Word): Boolean; overload;
    function IsKeyDown(const AKey: Char): Boolean; overload;
    end;

    implementation

    { TInputSystem }

    constructor TInputSystem.Create;
    var
    I: Integer;
    begin
    inherited Create();

    for I := 0 to 255 do
    FKeys[I] := False;
    for I := 0 to 2 do
    FMouseButtons[I] := False;
    FMouseX := 0;
    FMouseY := 0;
    end;

    function TInputSystem.IsKeyDown(const AKeyCode: Word): Boolean;
    begin
    Result := FKeys[AKeyCode];
    end;

    function TInputSystem.IsKeyDown(const AKey: Char): Boolean;
    var
    KeyCode: Integer;
    begin
    KeyCode := VkKeyScan(AKey) and $FF;
    if (KeyCode = $FF) then
    KeyCode := -1;
    Result := IsKeyDown(KeyCode);
    end;

    procedure TInputSystem.ProcessKeyboard(const KeyEvent: TKeyEvent;
    const TheKey: Word);
    begin
    case KeyEvent of
    keKeyDown: FKeys[TheKey] := True;
    keKeyUp: FKeys[TheKey] := False;
    end;
    end;

    procedure TInputSystem.ProcessMouse(const MouseEvent: TMouseEvent; const X,
    Y: Integer);
    begin
    case MouseEvent of
    meMove:
    begin
    FMouseX := X;
    FMouseY := Y;
    end;
    meLeftButtonDown: FMouseButtons[0] := True;
    meLeftButtonUp: FMouseButtons[0] := False;
    meMiddleButtonDown: FMouseButtons[1] := True;
    meMiddleButtonUp: FMouseButtons[1] := False;
    meRightButtonDown: FMouseButtons[2] := True;
    meRightButtonUp: FMouseButtons[2] := False;
    end;
    end;

    end.
    [/pascal]

  3. #13

    Making an input devices manager

    Quote Originally Posted by JSoftware
    noeska, to my knowledge, joystick input in mmsystem uses the 0..65535 where 0 is completely to one side and 65535 is completely to the other side.
    Buttons are bitpacked into a byte structure afaik.

    Have you calibrated your joystick?
    Would be nice if it were so. But it is not. Total left = -1000 and total right = 1000. So: -1000 to -470 then 0 then 470 to 1000. And that goes for all axis on my gamepad.
    And yes it is calibrated.

    @Brainer: How do i use your source as cannot seem to find anything like onkeypress and the likes.

    [edit]
    Oops ops:
    I feel stupid as i found the following lines:
    Code:
    constructor TGamepad.Create; 
    begin 
      inherited Create; 
      DeviceNr := 0; 
      Range := 1000; 
      DeadZone := 400; 
      Calibrate; 
    end;
    I skipped one of my rules as not to use an unit/component that i haven't studied. Now i did and it all makes sense.
    [/edit]
    http://3das.noeska.com - create adventure games without programming

  4. #14

    Making an input devices manager

    [quote="noeska"]
    Quote Originally Posted by JSoftware
    noeska, to my knowledge, joystick
    @Brainer: How do i use your source as cannot seem to find anything like onkeypress and the likes.
    I use this class with my form. Here's the code:
    [pascal]
    unit UBEWindow;

    interface

    uses
    Windows, Classes, Controls, Forms, AppEvnts,
    // -- Headers --
    dglOpenGL,
    // -- Engine units --
    UBEOpenGLBuffer, UBEInput, UBELogger, UBETimer;

    type
    { .: TBrainEngineForm :. }
    TBrainEngineForm = class(TForm)
    private
    { Private declarations }
    FAppEvent: TApplicationEvents;
    FOGLBuffer: TOpenGLBuffer;
    FInput: TInputSystem;
    FPerfTimer: TPerformanceTimer;
    procedure MyOnResize(Sender: TObject);
    procedure MyOnKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure MyOnKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure MyOnMouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    procedure MyOnMouseUp(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    procedure MyOnMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    protected
    { Protected declarations }
    procedure DoRender(); virtual; abstract;
    procedure MyOnIdle(Sender: TObject; var Done: Boolean); virtual; abstract;
    public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy(); override;

    property OpenGLBuffer: TOpenGLBuffer read FOGLBuffer;
    property InputSystem: TInputSystem read FInput;
    property PerformanceTimer: TPerformanceTimer read FPerfTimer;
    end;

    implementation

    { TBrainEngineForm }

    constructor TBrainEngineForm.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);

    FAppEvent := TApplicationEvents.Create(Self);
    FOGLBuffer := TOpenGLBuffer.Create(GetDC(Handle));
    FOGLBuffer.InitGL();
    FInput := TInputSystem.Create();
    FPerfTimer := TPerformanceTimer.Create();

    FAppEvent.OnIdle := MyOnIdle;
    OnResize := MyOnResize;
    OnKeyDown := MyOnKeyDown;
    OnKeyUp := MyOnKeyUp;
    OnMouseDown := MyOnMouseDown;
    OnMouseUp := MyOnMouseUp;
    OnMouseMove := MyOnMouseMove;

    Log.Log('Window created.', 'UBEWindow');

    FPerfTimer.StartTiming();
    end;

    destructor TBrainEngineForm.Destroy;
    begin
    FAppEvent.Free();
    FOGLBuffer.Free();
    FInput.Free();
    FPerfTimer.Free();

    Log.Log('Window freed.', 'UBEWindow');

    inherited Destroy();
    end;

    procedure TBrainEngineForm.MyOnKeyDown(Sender: TObject; var Key: Word;
    Shift: TShiftState);
    begin
    FInput.ProcessKeyboard(keKeyDown, Key);
    end;

    procedure TBrainEngineForm.MyOnKeyUp(Sender: TObject; var Key: Word;
    Shift: TShiftState);
    begin
    FInput.ProcessKeyboard(keKeyUp, Key);
    end;

    procedure TBrainEngineForm.MyOnMouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    case Button of
    mbLeft: FInput.ProcessMouse(meLeftButtonDown, X, Y);
    mbRight: FInput.ProcessMouse(meRightButtonDown, X, Y);
    mbMiddle: FInput.ProcessMouse(meMiddleButtonDown, X, Y);
    end;
    end;

    procedure TBrainEngineForm.MyOnMouseMove(Sender: TObject; Shift: TShiftState; X,
    Y: Integer);
    begin
    FInput.ProcessMouse(meMove, X, Y);
    end;

    procedure TBrainEngineForm.MyOnMouseUp(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    case Button of
    mbLeft: FInput.ProcessMouse(meLeftButtonUp, X, Y);
    mbRight: FInput.ProcessMouse(meRightButtonUp, X, Y);
    mbMiddle: FInput.ProcessMouse(meMiddleButtonUp, X, Y);
    end;
    end;

    procedure TBrainEngineForm.MyOnResize(Sender: TObject);
    begin
    glViewport(0, 0, ClientWidth, ClientHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, ClientWidth / ClientHeight, 0.1, 1000.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    end;

    end.

    [/pascal]

  5. #15

    Making an input devices manager

    Oh you are using the events from the form and feed them to your class.
    http://3das.noeska.com - create adventure games without programming

  6. #16

    Making an input devices manager

    Yes. I decided to go with this approach, because it's simple to do and I want to keep my engine as simple as possible. But I think you can easily change the code that it doesn't use VCL.

  7. #17

    Making an input devices manager

    When using a windows form application it is indeed best to use the vcl for getting them.

    I want something to work independed of vcl.
    I decided to give the following a try:
    Code:
      var
        P: TPoint;
        Msg: TMsg;
    begin
      GetCursorPos(P);
      FMouseX := P.X;
      FMouseY := P.Y;
      
      if getmessage(Msg, 0, 0, 0) then
      begin
        case Msg.message of
        WM_LBUTTONDOWN : FMouseButtons[0] := True;
        WM_LBUTTONUP : FMouseButtons[0] := False;
        WM_MBUTTONDOWN : FMouseButtons[1] := True;
        WM_MBUTTONUP : FMouseButtons[1] := False;
        WM_RBUTTONDOWN : FMouseButtons[2] := True;
        WM_RBUTTONUP : FMouseButtons[2] := False;
        end;
    
        //give message back for further processing
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
    end;
    Unfortunately some events are missed. I gues that is drawback of polling the windows message que.

    Is there a way to set up a listener to the windows message que?

    Or am i better of integrating this into an (opengl) api template as that already includes handling windows messages.

    [edit]
    Just thinking why not make a tthread descendantclass. So the timer can be left out also.
    [/edit]
    http://3das.noeska.com - create adventure games without programming

  8. #18

    Making an input devices manager

    Noeska, shouldn't you be checking the message events in the WndProc instead of in the message pump loop?

    I don't think I understood the part about missing events. Do you mean special buttons?
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  9. #19

    Making an input devices manager

    It tested it with mousebuttons. And sometimes the mouseup event is missed.
    http://3das.noeska.com - create adventure games without programming

  10. #20

    Making an input devices manager

    Quote Originally Posted by noeska
    I want something to work independed of vcl.
    [...]
    Or am i better of integrating this into an (opengl) api template as that already includes handling windows messages.
    This code of mine can be easily used with OpenGL WinAPI template. Just like you did, but I think, just like JSoftware, that it should be inside your window procedure, because this is where the messages come to.

Page 2 of 2 FirstFirst 12

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
  •