summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 99cf8a7)
raw | patch | inline | side by side (parent: 99cf8a7)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Tue, 5 Sep 2017 22:10:01 +0000 (01:10 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Tue, 5 Sep 2017 22:12:22 +0000 (01:12 +0300) |
src/game/g_grid.pas | patch | blob | history |
diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas
index 5fd0a331d0448d7bc7c63c60c30914bbc7fc8836..ec9c2aed80386c41332efae12d3d21fd55b801b5 100644 (file)
--- a/src/game/g_grid.pas
+++ b/src/game/g_grid.pas
result := (xd = term);
end;
-// move to next tile; return `true` if the line is complete (and walker state is undefined then)
function TLineWalker.stepToNextTile (): Boolean; inline;
var
- ex, ey, wklen, f: Integer;
+ ex, ey: Integer;
+ xwalk, ywalk, wklen: Integer; // to the respective edges
+ lstx, lsty, lterm: Integer;
+ le, ldx2, ldy2: Integer;
+ lxd, lyd: Integer;
+ f: Integer;
begin
result := false;
- //writeln('stx=', stx, '; sty=', sty);
+ lstx := stx;
+ lsty := sty;
+ lterm := term;
+ lxd := xd;
// ortho?
- if (sty = 0) then
+ if (lsty = 0) then
begin
// only xd
- assert(sty <> 0);
- if (stx < 0) then
+ //assert(lsty <> 0);
+ if (lstx < 0) then
begin
// xd: to left edge
- xd := (xd and (not (TileSize-1)))-1;
- result := (xd <= term);
+ xd := (lxd and (not (TileSize-1)))-1;
+ result := (lxd <= lterm);
exit;
end
else
begin
// xd: to right edge
- xd := (xd or (TileSize-1))+1;
- result := (xd >= term);
+ xd := (lxd or (TileSize-1))+1;
+ result := (lxd >= lterm);
exit;
end;
end;
- assert(stx <> 0); // invariant
-
// not ortho
- if (sty < 0) then ey := (yd and (not (TileSize-1)))-1 else ey := (yd or (TileSize-1))+1;
+ //assert(lstx <> 0); // invariant
- //FIXME: do some math to avoid single-stepping
- if (stx < 0) then
+ lyd := yd;
+ le := e;
+ ldx2 := dx2;
+ ldy2 := dy2;
+
+ // calculate xwalk
+ if (lstx < 0) then
begin
- // xd: to left edge
- ex := (xd and (not (TileSize-1)))-1;
- if (ex <= term) then begin result := true; exit; end;
- wklen := xd-ex;
+ ex := (lxd and (not (TileSize-1)))-1;
+ xwalk := lxd-ex;
end
else
begin
- // xd: to right edge
- ex := (xd or (TileSize-1))+1;
- if (ex >= term) then begin result := true; exit; end;
- wklen := ex-xd;
+ ex := (lxd or (TileSize-1))+1;
+ xwalk := ex-lxd;
end;
- //writeln('xd=', xd, '; yd=', yd, '; ex=', ex, '; ey=', ey, '; term=', term, '; wklen=', wklen);
-
- for f := wklen downto 1 do
+ // calculate ywalk
+ if (lsty < 0) then
begin
- // do step
- if (e >= 0) then begin yd += sty; e -= dx2; end else e += dy2;
- xd += stx;
- if (xd = term) then begin result := true; exit; end;
- if (xd = ex) or (yd = ey) then exit; // done
+ ey := (lyd and (not (TileSize-1)))-1;
+ ywalk := lyd-ey;
+ end
+ else
+ begin
+ ey := (lyd or (TileSize-1))+1;
+ ywalk := ey-lyd;
end;
- raise Exception.Create('TLineWalker.stepToNextTile: the thing that should not be!');
+ while true do
+ begin
+ // in which dir we want to walk?
+ if (xwalk <= ywalk) then wklen := xwalk else wklen := ywalk;
+ // walk x
+ if (lstx < 0) then
+ begin
+ lxd -= wklen;
+ if (lxd <= lterm) then begin xd := lxd; result := true; exit; end;
+ end
+ else
+ begin
+ lxd += wklen;
+ if (lxd >= lterm) then begin xd := lxd; result := true; exit; end;
+ end;
+ // walk y
+ for f := 1 to wklen do if (le >= 0) then begin lyd += lsty; le -= ldx2; end else le += ldy2;
+ if (lxd = ex) or (lyd = ey) then break;
+ xwalk -= wklen; if (xwalk = 0) then xwalk := TileSize;
+ ywalk -= wklen; if (ywalk = 0) then ywalk := TileSize;
+ end;
+ //assert((xd div TileSize <> lxd div TileSize) or (yd div TileSize <> lyd div TileSize));
+ xd := lxd;
+ yd := lyd;
+ e := le;
end;
// NOT TESTED!