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

Thread: Shared code snippets!

  1. #11

    Shared code snippets!

    Yeah, in general the scoping of that snippet could result in different pieces of code on different compilers Razz

    Looks like it's been converted directly from C code Smile
    Can you elaborate a little more on this? Is it because i allready assigned a result before the last statement is executed?

    This would probably be better:
    [pascal]
    function Angle(X,Y: single): single;
    begin
    if X = 0 then
    begin
    if Y > 0 then Result := 180
    else Result := 0;
    end else
    Result := 180+RadToDeg(Arctan2(-X,Y));
    end;
    [/pascal]
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  2. #12

    Shared code snippets!

    This is perfectly functional at least in Delphi7. Arctan2() is defined to handle the divide by zero case in itself. If you do it yourself it's double code (slower ofc).

    [pascal]// Result = ]-180, 180]
    const
    ToRad = 0.0174532925199432; // PI / 180 = Deg to Rad
    ToDeg = 57.295779513082320; // 180 / PI = Rad to Deg
    function Angle(px1,py1,px2,py2: double): double;
    begin
    result:=ToDeg*arctan2(py2-py1,px2-px1);
    // Add if result<0 then result:=result+360;
    // if you want range to be [0..360[
    end;[/pascal]

    I also noticed that you negate X, which is false.

  3. #13

    Shared code snippets!

    Sometimes you need the angles to be represented only between 0..360, you probably seen functions like this one:

    Code:
    function OLDclamp360&#40;angle&#58; single&#41;&#58; single;
    begin
      Result &#58;= angle;
    
      while Result <0> 360 do
        Result &#58;= Result - 360;
    
    end;
    Not only it's a bad code with a lot of branching that gets slower the bigger / smaller the numbers are, but there is a better / proper way:

    Code:
    function clamp360&#40;angle&#58; single&#41;&#58; single;
    begin
      Result &#58;= angle;
    
      if result > 360 then result&#58;= result - &#40;round&#40;result&#41; div 360 * 360&#41;;
      if result < 0   then result&#58;= 360 + result - &#40;round&#40;result&#41; div 360 * 360&#41;;
    
    end;
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  4. #14

    Shared code snippets!

    Quote Originally Posted by chronozphere
    Yeah, in general the scoping of that snippet could result in different pieces of code on different compilers Razz

    Looks like it's been converted directly from C code Smile
    Can you elaborate a little more on this? Is it because i allready assigned a result before the last statement is executed?

    [ code ]
    Yes, that code is perfect. Indeed, your last assignment would override any previous assignment effectively making the first 3 lines do nothing.

    The scoping would be a problem because the following piece of code would be syntactically identical as your initial piece of code
    [pascal]
    function Angle(X,Y: single): single;
    begin
    Result := 0;
    if X = 0 then
    begin
    if Y > 0 then
    Result := 180
    end
    else
    Result := 0;
    Result := 180+RadToDeg(Arctan2(-X,Y));
    end;[/pascal]
    Peregrinus, expectavi pedes meos in cymbalis
    Nullus norvegicorum sole urinat

  5. #15

    Shared code snippets!

    My snippet is helpful when formatting data sizes.
    [pascal]
    { .: FormatSize :. }
    function FormatSize(const Size: Integer): String;
    const
    KB = 1024;
    MB = KB * KB;
    GB = MB * KB;
    begin
    case Size of
    0..KB -1: Result := IntToStr(Size) + ' B';
    KB..MB -1: Result := Format('%.2f KB', [Size / KB]);
    MB..GB -1: Result := Format('%.2f MB', [Size / MB]);
    else
    Result := Format('%.2f GB', [Size / GB]);
    end;
    end;
    [/pascal]

  6. #16

    Shared code snippets!

    Okay... let's keep this topic alive shall we.

    I just baked this piece of code...

    Use this routine to read a Null-Terminated String from a MemoryStream. The function reads MaxLength - 1 Characters from the stream and adds the null-Char at the end. If the function encounters a NullChar while reading, Buffer will only contain the characters precending the NullChar and the NullChar itsself. The routine returns the ammount of bytes read.
    [pascal]
    var
    Stream: TMemoryStream; //Global stream

    function ReadStr(Buffer: PChar; MaxLength: Integer): Integer;
    type
    TCharArray = array [0..MaxInt-1] of Char;
    PCharArray = ^TCharArray;
    var
    I: Integer;
    Chars: PCharArray;
    begin
    Result := 0;
    if (Stream.Size - Stream.Position <= 0) then Exit;

    Chars := Stream.Memory;
    I := -1;
    repeat
    Inc(I);
    if Chars[Stream.Position+I] = #0 then Break;
    until (I = MaxLength -1);

    Result := Stream.Read( Buffer^, I ) + 1;
    Buffer[Result-1] := #0;
    end;
    [/pascal]

    I have tested this code, and it's working correctly AFAIK.

    Might become handy when you are trying to make a C compatible API wich relies on Null-Terminated strings.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  7. #17

    Shared code snippets!

    Okay... Here is a similair routine, but now to write a string.

    Writes MaxLength characters of a Null-Terminated String to a MemoryStream. The routine doesn't write the NullChar. If a NullChar is found in the string, Only the precending Chars are written. Returns the number of bytes written.
    [pascal]
    function WriteStr(Buffer: PChar; MaxLength: Integer): Integer;
    type
    TCharArray = array [0..MaxInt-1] of Char;
    PCharArray = ^TCharArray;
    var
    I: Integer;
    Chars: PCharArray;
    begin
    Chars := Pointer(Buffer);
    for I:=0 to MaxLength-1 do
    if Chars[I] = #0 then Break;

    Result := Stream.Write( Buffer^, I );
    end;
    [/pascal]
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  8. #18

    Shared code snippets!

    This piece of code converts seconds into "hours:minutes:seconds" format.
    [pascal]
    { .: FormatTime :. }
    function FormatTime(const TheTime: Integer): String;
    var
    Hours, Mins, Secs: Integer;
    begin
    if (TheTime > 0) then
    begin
    Mins := (TheTime div 60);
    Secs := (TheTime mod 60);
    Hours := (Mins div 60);
    Mins := (Mins mod 60);
    Result := Format('%.2d:%.2d:%.2d', [Hours, Mins, Secs]);
    end else
    Result := '00:00:00';
    end;
    [/pascal]

  9. #19

    Re: Shared code snippets!

    Hi guys, No more new snippets these days?

    I've got a new one. This routine concatenates two paths. The first is the basePath and the second is a path relative to this basepath. It handles "../" to jump to the parent directory.
    My string programming skills are not that great, so I guess there's room for improvement.

    [pascal]
    function ConcatenatePaths(aBasePath, aRelativePath: String): String;
    const
    SEPARATORS = ['\','/'];
    SEPARATOR = '/';
    var
    Name: String;
    I: Integer;
    begin
    //Trim redundant slashes
    if aRelativePath[1] in SEPARATORS then
    aRelativePath := RightStr(aRelativePath, Length(aRelativePath)-1 );
    if aBasePath[Length(aBasePath)] in SEPARATORS then
    aBasePath := LeftStr(aBasePath, Length(aBasePath)-1 );

    while Length(aRelativePath) > 0 do
    begin
    Name := Copy(aRelativePath, 1, 3);
    if (Name = '../') or (Name = '..\') then
    begin
    for I := Length(aBasePath) downto 1 do
    if aBasePath[I] in SEPARATORS then
    begin
    aBasePath := Copy(aBasePath, 1, I-1);
    Break;
    end;
    aRelativePath := Copy(aRelativePath, 4, Length(aRelativePath)-3);
    end
    else
    Break;
    end;

    Result := aBasePath + SEPARATOR + aRelativePath;
    end;
    [/pascal]

    For example:

    E:\some\groovy\file\path\to\somewhere + '..\..\..\myfile.txt'

    results in:

    E:\some\groovy\file\myfile.txt'
    Now it's your turn again.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  10. #20

    Re: Shared code snippets!

    There's few in nxMath i could show up:

    n is any floating point number. It gives a result that is always between 0 and 1, but most interesting thing happens when n is 0..1; it smoothens the pattern to match "top to low peak" of cosine wave.
    [pascal]function Smoothen(n: single): single;
    begin
    if n<0 then n:=0
    else if n>1 then n:=1;
    Smoothen:=0.5-cos(n*pi)*0.5;
    end;[/pascal]

    Simply modulus, but this handles also negative numbers so that it remains continuous pattern at 0 point. 11 mod2 10 = 1 , -11 mod2 10 = -9
    [pascal]function Mod2(a,b: integer): integer;
    begin
    if b=0 then result:=0
    else begin
    b:=abs(b);
    result:=abs(a) mod b;
    if (a<0) and (result>0) then result:=result-b;
    end;
    end;[/pascal]

    And 1 more...
    If you need to get power of 2 number that your current fits in, this is the function.
    Giving n = 140 or 220 would result in 256.
    [pascal]function Pow2fit(n: integer): integer;
    var neg: boolean;
    begin
    if n<0 then begin
    n:=-n; neg:=true;
    end else neg:=false;
    if n<3 then result:=n
    else result:=round(intpower(2,ceil(log2(n))));
    if neg then result:=-result;
    end;[/pascal]
    There's still Pow2near() which would give the nearest fit which would result in 128 in case of 140. These are all part of Next3D.

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
  •