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

Thread: Car Game Troubles

  1. #1

    Car Game Troubles

    Hi everyone.

    I’ve programmed a 2D game in Delphi 6 and UnDelphiX. The user would drive a car on a road and will have to kill monsters etc. When the up key is pressed the road and monsters moves down at the same speed and it then appears as if the car is moving up.

    I have 2 problems:

    I’ve tried to get the movement independent of fps but all the ways I’ve tried results in the movement being jerky. Is there another way?

    Code:
    dxSpriteEngine1.Move(LagCount);
    DXTimer1.Interval := 1000 div 75; This gives 64 fps
    Or

    Code:
    dxtimer1.Interval:=1000 div 70;
    NewTime := TimeGetTime;
    UpdateSpeed := (NewTime - OldTime) * (OneMSec ) //or * (LagCount/2);  
    OldTime := NewTime; 
    Y := Y + (0.5 * updatespeed)
    I’ve posted about my 2nd problem but got no response, please help:

    Code:
    constructor TRoad.create(parent:TSprite;imgs:TDXImageList;imgIndex:integer);
    begin
      inherited create(parent);
         self.Image:=imgs.Items[ImgIndex];
         self.Width:=self.image.Width;
         self.Height:=self.Image.Height;
         self.PixelCheck:=false;
         self.x:=0;
         self.Y:= form1.DXDraw1.Surface.Height - height; //form1.dxdraw1.height - height; //                                                                             self.engine.surface.height ???????? None of these settings works on other PC???????
         self.Z:=0;
    end;
    The problem is the self.y line of code. On one pc the setting self.y := -11600 (length of road image) works but not on another pc. Sometimes the road only appears halfway and it should appear at the start.

    Hope this clarifies my problems and your feedback will be appreciated. BTW Gr8 site!!!!
    Wake up from the dream and live your life to the full

  2. #2

    Car Game Troubles

    About your problems:

    #1.
    What is the exact problem there? It could be me, but I don't exactly get the point. Are you trying to create a movement by fps?

    #2.
    I guess the 2 pc's have different resolutions?
    What is the exact value of "form1.DXDraw1.Surface.Height" on both pc's ?
    It's clear that 1 number is varieing on the pc's.
    "What we cannot speak about we must pass over in silence."

  3. #3

    Car Game Troubles

    No, movement must be independent of fps. If it is by fps the game runs smoothley but the fps is too high to accomadate the same speed on different pc's. So I'm trying to get movement independent of fps but the ways I've tried only makes movement jerky :-(

    Nope they have the same resolution, I checked that. The road image is exactly 11600 in length and all that needs to happen is for the form to load the exact same image at the correct starting y point and it's not happening :-(
    Wake up from the dream and live your life to the full

  4. #4

    Car Game Troubles

    Ok, now I fully understand you.

    How to make movement independent of FPS...
    You could try it with a timer, but that's not a real solution I think.
    Well, in my projects I have it outside the "game-procedure", and I mean by saying this, that I separate the key-handling and ingame procedures.

    For your second problem, I think the defined "height" is varieing.
    Or you haven't defined it before (I had that once, I forgot to set the value of it, and somehow it has different values then...).
    But one thing is certain, 1 variable is varieing...
    "What we cannot speak about we must pass over in silence."

  5. #5

    Car Game Troubles

    Ok, regarding the 2nd problem. I've done some tests and it would seem that if I have a value of 12200 set as the pattern height of the road image in the object inspector and the following in the procedure: self.engine.surface.height - height, that it works. Don't know, will have to test it on my LapTop tonight.

    But I'm still stumped on the 1st question...
    Wake up from the dream and live your life to the full

  6. #6

    Car Game Troubles

    #1:

    How does your system works?
    I mean, the key handling.
    In one of my projects the keys determined whether something was executed or not.
    In another example you could use a kind of timer.
    The procedure inside the timer will check if a key is down or not, but I think you currently have that system, am I right?
    Because if you hit the key while the procedure is checking it will not check now but in the next interval, which means your movement is meshed up.

    I can suggest reading this (directly copied from GLScene, but very usefull since this works 100%)
    [pascal]//
    // This unit is part of the GLScene Project, http://glscene.org
    //
    {: Keyboard<p>

    Provides on demand state of any key on the keyboard as well as a set of
    utility functions for working with virtual keycodes.<p>

    Note that windows maps the mouse buttons to virtual key codes too, and you
    can use the functions/classes in this unit to check mouse buttons too.<br>
    See "Virtual-Key Codes" in the Win32 programmers r?©ferences for a list of
    key code constants (VK_* constants are declared in the "Windows" unit).<p>

    Historique : <font><ul>[*]17/11/03 - Egg - Fixed IsKeyDown (VK) (A. P. Mohrenweiser)[*]09/10/00 - Egg - Fixed VirtualKeyCodeToKeyName
    [*]03/08/00 - Egg - Creation, partly based Silicon Commander code
    [/list]</font>
    }
    unit Keyboard;

    interface

    {$i GLScene.inc}
    {$IFDEF LINUX}{$Message Error 'Unit not supported'}{$ENDIF LINUX}

    uses
    Windows;

    type

    TVirtualKeyCode = Integer;

    const
    // pseudo wheel keys (we squat F23/F24), see KeyboardNotifyWheelMoved
    VK_MOUSEWHEELUP = VK_F23;
    VK_MOUSEWHEELDOWN = VK_F24;

    {: Check if the key corresponding to the given Char is down.<p>
    The character is mapped to the main keyboard only, and not to the
    numeric keypad.<br>
    The Shift/Ctrl/Alt state combinations that may be required to type the
    character are ignored (ie. 'a' is equivalent to 'A', and on my french
    keyboard, '5' = '(' = '[' since they all share the same physical key). }
    function IsKeyDown(c : Char) : Boolean; overload;
    {: Check if the given virtual key is down.<p>
    This function is just a wrapper for GetAsyncKeyState. }
    function IsKeyDown(vk : TVirtualKeyCode) : Boolean; overload;
    {: Returns the first pressed key whose virtual key code is >= to minVkCode.<p>
    If no key is pressed, the return value is -1, this function does NOT
    wait for user input.<br>
    If you don't care about multiple key presses, just don't use the parameter. }
    function KeyPressed(minVkCode : TVirtualKeyCode = 0) : TVirtualKeyCode;

    {: Converts a virtual key code to its name.<p>
    The name is expressed using the locale windows options. }
    function VirtualKeyCodeToKeyName(vk : TVirtualKeyCode) : String;
    {: Converts a key name to its virtual key code.<p>
    The comparison is case-sensitive, if no match is found, returns -1.<p>
    The name is expressed using the locale windows options, except for mouse
    buttons which are translated to 'LBUTTON', 'MBUTTON' and 'RBUTTON'. }
    function KeyNameToVirtualKeyCode(const keyName : String) : TVirtualKeyCode;
    {: Returns the virtual keycode corresponding to the given char.<p>
    The returned code is untranslated, f.i. 'a' and 'A' will give the same
    result. A return value of -1 means that the characted cannot be entered
    using the keyboard. }
    function CharToVirtualKeyCode(c : Char) : TVirtualKeyCode;

    {: Use this procedure to notify a wheel movement and have it resurfaced as key stroke.<p>
    Honoured by IsKeyDown and KeyPressed }
    procedure KeyboardNotifyWheelMoved(wheelDelta : Integer);

    var
    vLastWheelDelta : Integer;

    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    implementation
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------

    uses SysUtils;

    const
    cLBUTTON = 'LBUTTON';
    cMBUTTON = 'MBUTTON';
    cRBUTTON = 'RBUTTON';
    cUP = 'UP';
    cDOWN = 'DOWN';
    cRIGHT = 'RIGHT';
    cLEFT = 'LEFT';
    cPAGEUP = 'PAGE UP';
    cPAGEDOWN = 'PAGE DOWN';
    cHOME = 'HOME';
    cEND = 'END';
    cMOUSEWHEELUP = 'MWHEEL UP';
    cMOUSEWHEELDOWN = 'MWHEEL DOWN';

    // IsKeyDown
    //
    function IsKeyDown(c : Char) : Boolean;
    var
    vk : Integer;
    begin
    // '$FF' filters out translators like Shift, Ctrl, Alt
    vk:=VkKeyScan(c) and $FF;
    if vk<>$FF then
    Result:=(GetAsyncKeyState(vk)<0>0);
    if Result then vLastWheelDelta:=0;
    end;
    VK_MOUSEWHEELDOWN : begin
    Result:=(vLastWheelDelta<0);
    if Result then vLastWheelDelta:=0;
    end;
    else
    Result:=(GetAsyncKeyState(vk)<0>=0);
    Result:=-1;
    if GetKeyboardState(buf) then begin
    for i:=minVkCode to High(buf) do begin
    if (buf[i] and $80)<>0 then begin
    Result:=i;
    Exit;
    end;
    end;
    end;
    if vLastWheelDelta<0>0 then
    Result:=VK_MOUSEWHEELUP
    else Result:=VK_MOUSEWHEELDOWN;
    vLastWheelDelta:=0;
    end;
    end;

    // VirtualKeyCodeToKeyName
    //
    function VirtualKeyCodeToKeyName(vk : TVirtualKeyCode) : String;
    var
    nSize : Integer;
    begin
    // Win32 API can't translate mouse button virtual keys to string
    case vk of
    VK_LBUTTON : Result:=cLBUTTON;
    VK_MBUTTON : Result:=cMBUTTON;
    VK_RBUTTON : Result:=cRBUTTON;
    VK_UP : Result:=cUP;
    VK_DOWN : Result:=cDOWN;
    VK_LEFT : Result:=cLEFT;
    VK_RIGHT : Result:=cRIGHT;
    VK_PRIOR : Result:=cPAGEUP;
    VK_NEXT : Result:=cPAGEDOWN;
    VK_HOME : Result:=cHOME;
    VK_END : Result:=cEND;
    VK_MOUSEWHEELUP : Result:=cMOUSEWHEELUP;
    VK_MOUSEWHEELDOWN : Result:=cMOUSEWHEELDOWN;
    else
    nSize:=32; // should be enough
    SetLength(Result, nSize);
    vk:=MapVirtualKey(vk, 0);
    nSize:=GetKeyNameText((vk and $FF) shl 16, PChar(Result), nSize);
    SetLength(Result, nSize);
    end;
    end;

    // KeyNameToVirtualKeyCode
    //
    function KeyNameToVirtualKeyCode(const keyName : String) : TVirtualKeyCode;
    var
    i : Integer;
    begin
    if keyName=cLBUTTON then
    Result:=VK_LBUTTON
    else if keyName=cMBUTTON then
    Result:=VK_MBUTTON
    else if keyName=cRBUTTON then
    Result:=VK_RBUTTON
    else if keyName=cMOUSEWHEELUP then
    Result:=VK_MOUSEWHEELUP
    else if keyName=cMOUSEWHEELDOWN then
    Result:=VK_MOUSEWHEELDOWN
    else begin
    // ok, I admit this is plain ugly.
    Result:=-1;
    for i:=0 to 255 do begin
    if CompareText(VirtualKeyCodeToKeyName(i), keyName)=0 then begin
    Result:=i;
    Break;
    end;
    end;
    end;
    end;

    // CharToVirtualKeyCode
    //
    function CharToVirtualKeyCode(c : Char) : TVirtualKeyCode;
    begin
    Result:=VkKeyScan(c) and $FF;
    if Result=$FF then Result:=-1;
    end;

    // KeyboardNotifyWheelMoved
    //
    procedure KeyboardNotifyWheelMoved(wheelDelta : Integer);
    begin
    vLastWheelDelta:=wheelDelta;
    end;

    end.
    [/pascal]

    In your procedure it could look like this:

    [pascal] if IsKeyDown('w') then movementw;
    if ....[/pascal]
    &quot;What we cannot speak about we must pass over in silence.&quot;

  7. #7

    Car Game Troubles

    Good suggestion Angelo.
    The key handling is done in the onMove procedure and the doMove is called in the statemachine and the statemachine is called in the timer procedure:

    Code:
    if &#40;isUp in form1.DXInput1.States&#41; then
    Y &#58;= y + &#40;1 * updatespeed&#41; else
    if not&#40;isUp in form1.DXInput1.States&#41; then
    Y &#58;= Y + &#40;0.5 * updatespeed&#41;;
    I disabled the procedure to check if the key is pressed or not and it is still jerky :-(

    i.e. Y := y + (1 * updatespeed);

    Thanks for your help so far :-)
    Wake up from the dream and live your life to the full

  8. #8

    Car Game Troubles

    No problem.

    What if you try it like this (it's just a sketch):

    [pascal]Procedure Timer;
    begin
    If OnKeyPress then DoMove(KeyPressed);
    // In this case OnKeyPress is a function that only returns whether a key is pushed or not (true and false)
    // In this case KeyPressed is a function that returns the number/letter which is pressed
    end;

    Procedure DoMove(Key: string);
    begin
    If Key = 'w' then begin
    end;
    end;[/pascal]
    &quot;What we cannot speak about we must pass over in silence.&quot;

  9. #9

    Car Game Troubles

    I don't think we're moving in the right direction. Everything was working fine untill I introduced the following in the timer event:

    dxtimer1.Interval:=1000 div 70;
    NewTime := TimeGetTime;
    UpdateSpeed := (NewTime - OldTime) * OneMSec
    OldTime := NewTime;

    The objects are moved as such:

    TMan(MyMen[loop]).DoMove(1); in the statemachine.
    and y := y + (1 * updatespeed); in the doMove Procedure.

    I've run the game without any keyboard input and it's jerky so I don't think it has to do with input delays from the keyboard.

    I'll keep testing with different values in: UpdateSpeed := (NewTime - OldTime) * OneMSec;
    Wake up from the dream and live your life to the full

  10. #10

    Car Game Troubles

    Ah I get it.
    You know why it's jerky?

    Because the timer interval is too much.
    Your game is updated every 1000/70 milliseconds.
    That's really slow.
    My timer interval is 0,2 ms... which is much quicker.
    Try for example 1000/200 milliseconds and you'll see it will move how you want it to.
    BUT: Since you now enlarged the scale, the object will move quicker.
    So movingspeed should be divided by 200/70...
    &quot;What we cannot speak about we must pass over in silence.&quot;

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
  •