Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: DirectInput Limiting Movement

  1. #1

    DirectInput Limiting Movement

    hi there, i've been trying to find something on limiting the users movement on my game.. i use directinput in which it detects keypress and moves character, but i have no idea how todo this and its really aggrivating me now...

    [pascal]
    procedure TFury.Render;
    begin
    if F_DXDevice = nil then exit;

    // clear the backbuffer to black
    F_DXDevice.Clear(0, nil, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0, 0);

    // Rendering of scene objects can happen here
    F_DXDevice.BeginScene;
    begin
    //get user input.
    ProcessKBInput;

    F_MapBuilder.DrawBricks;
    end;
    F_DXDevice.EndScene;

    // Present the backbuffer contents to the display
    F_DXDevice.Present(nil, nil, 0, nil);
    end;
    [/pascal]

    the processkbinput is as follows:

    [pascal]
    procedure TFury.ProcessKBInput;
    var
    buffer: array[0..255] of byte;
    hr: HResult;
    begin
    hr := F_DIDevice.GetDeviceState(SizeOf(buffer), @buffer);
    if FAILED(hr) then begin
    WriteLN('FAIL');
    exit; //**** knows.... probably try to reaquire, todo...
    end;

    if (buffer[DIK_LEFT] and $80) <> 0 then //... need to move character smoothly not 1000mph...
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - 1
    else if (buffer[DIK_RIGHT] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + 1; //way to fast :/
    end;
    [/pascal]

    so basically when i press left key, the character moves farrrrrrr too quick and vice versa with right, i considering only checking input after x amount of seconds, but then it will miss keypress...

    any help would be greatly appreciated


    *EDIT*

    i slowed down the movement by using single for posx and y, however problem is that if the framerate increases or drops it also changes the movement rate

    [pascal]
    if (buffer[DIK_LEFT] and $80) <> 0 then //... need to move character smoothly not 1000mph...
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - 0.05
    else if (buffer[DIK_RIGHT] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + 0.05;
    [/pascal]

    -MM

  2. #2

    DirectInput Limiting Movement

    You should multiply the step (0.05) by the number of seconds or milliseconds elapsed since the last frame. That way you would be moving the character N units per second/millisecond.

  3. #3

    DirectInput Limiting Movement

    Quote Originally Posted by cronodragon
    You should multiply the step (0.05) by the number of seconds or milliseconds elapsed since the last frame. That way you would be moving the character N units per second/millisecond.
    yep i jus sorted it, thanks anyways for replying ^ that was spot on answer, thanks alot

    [pascal]
    if (buffer[DIK_LEFT] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - (((tick - F_LastCheck) / 60) * 5)
    else if (buffer[DIK_RIGHT] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + (((tick - F_LastCheck) / 60) * 5);
    [/pascal]

  4. #4

    DirectInput Limiting Movement

    hi i've done a bit more testing and im still doing it wrong by looks of it, if i set max 60fps then moving left or right drops to a snails pace... i've tried alsorts of way, and my math is terrible in compare to what it used to be... lol any sample of what you meant? maybe i misunderstood...

    thanks in advance

  5. #5

    DirectInput Limiting Movement

    You really don't need to divide by 60, and removing that will increase the speed 60 times:

    [pascal] if (buffer[DIK_LEFT] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - ((tick - F_LastCheck) * 5)
    else if (buffer[DIK_RIGHT] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + ((tick - F_LastCheck) * 5); [/pascal]

    It all depends on the size of your world...

  6. #6

    DirectInput Limiting Movement

    hi, thanks for responding...

    problem is i need it to move the character at the same speed no matter what framerate is drawn, sometime people may get 60fps for me i get 5000fps, but i want them both to move at the same speed no matter of the fps.

    thanks

  7. #7

    DirectInput Limiting Movement

    Yes, that's the idea behind multiplying by the time elapsed:

    (tick - F_LastCheck) * 5

    If the time elapsed is large (meaning a low frame rate), you will get a large value, making the step larger. If the time elapsed is small (meaning a fast frame rate), you will get a small value, making the step smaller. If the time elapsed is being calculated properly, you should get a constant speed, no matter if the frame rate is going up and down while animating.

  8. #8

    DirectInput Limiting Movement

    hi, thank you very much, i understand now... but it seems to jitter

    if i set vsync mode on, limiting at 60fps and i add code as:

    [pascal]
    d := 5;

    if (buffer[DIK_A] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + d
    else if (buffer[DIK_D] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - d;

    if (buffer[DIK_W] and $80) <> 0 then
    F_MapBuilder.Player.PosY := F_MapBuilder.Player.PosY + d
    else if (buffer[DIK_S] and $80) <> 0 then
    F_MapBuilder.Player.PosY := F_MapBuilder.Player.PosY - d;
    [/pascal]

    then it moves perfectly, no jitter or anything. if i then change to:

    [pascal]
    d := (F_ThisTick - F_LastTick) * 0.5;

    if (buffer[DIK_A] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + d
    else if (buffer[DIK_D] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - d;

    if (buffer[DIK_W] and $80) <> 0 then
    F_MapBuilder.Player.PosY := F_MapBuilder.Player.PosY + d
    else if (buffer[DIK_S] and $80) <> 0 then
    F_MapBuilder.Player.PosY := F_MapBuilder.Player.PosY - d;
    [/pascal]

    if you'd like to check what i mean >

    http://www.meka-meka.com/meka/FuryEngine.rar

    thanks alot for help

  9. #9

    DirectInput Limiting Movement

    Why not use QueryPerformanceCounter and QueryPerformanceFrequency?? They will be a lot more accurate than GetTickCount (which i assume you use now). I alway's calculate the "FrameTime", which is the time it took to render the last frame. I make this value globally available and i multiply it when moving/scaling etc...

    [pascal]
    Obj.x := Obj.x + 100*FrameTime;
    [/pascal]

    Will move the object 100 pixels to the right in one second. When running @ 60FPS, your FrameTime should be 1/60.

    Hope it helps.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  10. #10

    DirectInput Limiting Movement

    hi, thannkssssssssssssssss, i have changed to this and it works perfect, doing as you said thanks very much DDDD

    for anyone else it may help to see, i have changed to >

    private's >
    [pascal]
    F_Freq : Int64;
    F_DeltaTime : Single;
    F_LastTime : Single;
    F_ThisTime : Single;
    [/pascal]

    [pascal]
    procedure TFury.ProcessKBInput;
    const
    iSpeed = 60;
    var
    buffer: array[0..255] of byte;
    hr: HResult;

    d: Double;
    begin
    hr := F_DIDevice.GetDeviceState(SizeOf(buffer), @buffer);
    if FAILED(hr) then begin
    F_DIDevice.Acquire;
    exit;
    end;

    d := iSpeed * F_DeltaTime;

    if (buffer[DIK_A] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX + d
    else if (buffer[DIK_D] and $80) <> 0 then
    F_MapBuilder.Player.PosX := F_MapBuilder.Player.PosX - d;

    if (buffer[DIK_W] and $80) <> 0 then
    F_MapBuilder.Player.PosY := F_MapBuilder.Player.PosY + d
    else if (buffer[DIK_S] and $80) <> 0 then
    F_MapBuilder.Player.PosY := F_MapBuilder.Player.PosY - d;
    end;

    procedure TFury.Render;
    var
    iTime: Int64;
    begin
    if F_DXDevice = nil then exit;

    // clear the backbuffer to black
    F_DXDevice.Clear(0, nil, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0, 0);

    // Rendering of scene objects can happen here
    F_DXDevice.BeginScene;
    begin
    //get user input.
    ProcessKBInput;

    F_MapBuilder.DrawBricks;
    end;
    F_DXDevice.EndScene;

    // Present the backbuffer contents to the display
    F_DXDevice.Present(nil, nil, 0, nil);

    QueryPerformanceCounter(iTime);
    F_ThisTime := (iTime / F_Freq);
    F_DeltaTime := F_ThisTime - F_LastTime;

    F_LastTime := F_ThisTime;
    end;
    [/pascal]

    thanks again

    -MM

Page 1 of 2 12 LastLast

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
  •