📄 isomath.pas
字号:
unit isoMath;
{****************************************************************************
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.
The Original Code is IsoEdit.
The Initial Developer of the Original Code is No.2 Games, Inc. and
Michael Wilson. Portions created by Michael Wilson are Copyright
(C) No.2 Games, Inc. All Rights Reserved.
Contributor(s):
******************************************************************************}
// *****************************************
// * isoMath - 256 cycle trig functions *
// * and vector equations that are *
// * useful in isometric perspective *
// * games. All functions are skewed *
// * to reflect a 2:1 orthoginal *
// * perspective. (c)1999 Michael Wilson *
// *****************************************
interface
const
isoPi = 3.14159; // (192)
isoNorth = 192; // screen up n Clock-wise
isoSouth = 64; // screen down (128) w + e (0) rotation
isoWest = 128; // screen left s
isoEast = 0; // screen right (64)
type
isoPolar = record
a {ngle}: integer; // 256 cycle angle [0..255] is more than enough
v {elocity}: single; // pixel movements as small as 0.00000001
end;
isoVector = record
x, y: single; // pixel movements as small as 0.00000001
end;
// these are used to represent x,y locations in a grid
// so if you see a function using TGridint or
// TCellsCoord, it's dealing with cells, not pixels
TGridInt = Integer;
TCellsCoord = record
X, Y: TGridInt;
end;
function isoSin(a {ngle}: integer): single;
function isoCos(a {ngle}: integer): single;
// function isoArcTanAsm(Y, X: extended): extended;
function normArcTan(dy, dx: single): byte;
function isoArcTan(dy, dx: single): byte;
function normFindAngle(x, y, x1, y1: integer): byte;
function isoFindAngle(x, y, x1, y1: integer): byte;
function isoIsLeft(a {ngle}, t {est}: byte): boolean;
function isoNormAngle(angle: integer): byte;
function isoDistance(x, y, x1, y1: integer): integer;
function isoPointInQuad(x0, y0, x1, y1, x2, y2, x3, y3, x, y: integer): boolean;
function GetNW(FromCell : TCellsCoord) : TCellsCoord;
function GetNE(FromCell : TCellsCoord) : TCellsCoord;
function GetSW(FromCell : TCellsCoord) : TCellsCoord;
function GetSE(FromCell : TCellsCoord) : TCellsCoord;
implementation
function isoSin(a {ngle}: integer): single; // integer allows for negative angles
begin
result := sin(((a and 255) / 256) * 2 * isoPi) / 2 // one-half of the y vector
end; {function}
function isoCos(a {ngle}: integer): single;
begin
result := cos(((a and 255) / 256) * 2 * isoPi)
end; {function}
{function isoArcTanAsm(Y, X: extended): extended;
asm
FLD Y
FLD X
FPATAN
FWAIT
end;}
function normArcTan(dy, dx: single): byte;
begin
result := abs(round(ArcTan(dy / dx) * (128 / isoPi))); // one-half of the y vector
end; {function}
function isoArcTan(dy, dx: single): byte;
begin
result := abs(round(ArcTan((dy / 2) / dx) * (128 / isoPi))); // one-half of the y vector
end; {function}
function normFindAngle(x, y, x1, y1: integer): byte;
var
dx, dy: integer;
begin
dx := (x - x1); {get dx dy}
dy := (y - y1);
if (dx = 0) then
begin {check special cases}
if (dy > 0) then
result := 64
else
result := 192;
exit;
end; {special cases}
if (dx < 0) and (dy > 0) then { 2nd quad }
result := 128 - normarctan(dy, dx)
else
if (dx < 0) and (dy <= 0) then { 3rd quad }
result := 128 + normarctan(dy, dx)
else
if (dx > 0) and (dy < 0) then { 4th quad }
result := 256 - normarctan(dy, dx)
else { 1st quad }
result := normarctan(dy, dx)
end; {function}
function isoFindAngle(x, y, x1, y1: integer): byte;
var
dx, dy: integer;
begin
dx := (x - x1); {get dx dy}
dy := (y - y1);
if (dx = 0) then
begin {check special cases}
if (dy > 0) then
result := 64
else
result := 192;
exit;
end; {special cases}
if (dx < 0) and (dy > 0) then { 2nd quad }
result := 128 - isoarctan(dy, dx)
else
if (dx < 0) and (dy <= 0) then { 3rd quad }
result := 128 + isoarctan(dy, dx)
else
if (dx > 0) and (dy < 0) then { 4th quad }
result := 256 - isoarctan(dy, dx)
else { 1st quad }
result := isoarctan(dy, dx)
end; {function}
function isoIsLeft(a {ngle}, t {est}: byte): boolean;
var loop: integer; // loop
begin
loop:=0;
repeat
inc(loop)
until (isonormangle(a + loop) = t) or (isonormangle(a - loop) = t);
if (isonormangle(a - loop) = t) then result := true
else
result := false;
end;
function isoNormAngle(angle: integer): byte;
begin
result := angle and 255;
end; {function}
function isoDistance(x, y, x1, y1: integer): integer;
begin
result := round(sqrt((x - x1) * (x - x1) + ((y - y1) * 2) * ((y - y1) * 2)));
end; {function}
function isoPointInQuad(x0, y0, x1, y1, x2, y2, x3, y3, x, y: integer): boolean;
begin
result := false;
if ((y0 - y1) * (x - x1) + (x1 - x0) * (y - y1) > -1) and
((y1 - y2) * (x - x2) + (x2 - x1) * (y - y2) > -1) and
((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3) > -1) and
((y3 - y0) * (x - x0) + (x0 - x3) * (y - y0) > -1) then
result := true;
if ((y0 - y1) * (x - x1) + (x1 - x0) * (y - y1) < 1) and
((y1 - y2) * (x - x2) + (x2 - x1) * (y - y2) < 1) and
((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3) < 1) and
((y3 - y0) * (x - x0) + (x0 - x3) * (y - y0) < 1) then
result := true;
end; { function }
function GetNW(FromCell : TCellsCoord) : TCellsCoord;
begin
result.y := FromCell.Y -1;
if (FromCell.Y and 1)<>0 then Result.X := FromCell.x
else Result.X := FromCell.X-1;
end;
function GetNE(FromCell : TCellsCoord) : TCellsCoord;
begin
result.y := FromCell.Y -1;
if (FromCell.Y and 1)<>0 then Result.X := FromCell.x+1
else Result.X := FromCell.X;
end;
function GetSW(FromCell : TCellsCoord) : TCellsCoord;
begin
result.y := FromCell.Y +1;
if (FromCell.Y and 1)<>0 then Result.X := FromCell.x
else Result.X := FromCell.X-1;
end;
function GetSE(FromCell : TCellsCoord) : TCellsCoord;
begin
result.y := FromCell.Y +1;
if (FromCell.Y and 1)<>0 then Result.X := FromCell.x+1
else Result.X := FromCell.X;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -