2018-09-09 UPDATED THE APIGeneral.agc file as follows to fix some bugs, add a TColor type and to implement constants for the full range of known key codes:
// ***********************************************************************
// CONSTANT REFERENCES
// ***********************************************************************
#constant TRUE 1
#constant FALSE 0
#constant TRANSPARENCY_MODE_OFF 0
#constant TRANSPARENCY_MODE_ALPHA 1
#constant TRANSPARENCY_MODE_ADDITIVE 2
#constant KEY_LEFT 37
#constant KEY_A 65
#constant KEY_RIGHT 39
#constant KEY_D 68
#constant KEY_UP 38
#constant KEY_W 87
#constant KEY_DOWN 40
#constant KEY_S 83
#constant KEY_T 84
#constant KEY_E 69
#constant KEY_SPACE 32
#constant KEY_N 78
#constant KEY_ESC 27
#constant KEY_Z 90
#constant KEY_X 88
#constant KEY_C 67
#constant KEY_SHIFT 16
#constant KEY_ENTER 13
#constant KEY_1 49
#constant KEY_2 50
#constant KEY_3 51
#constant KEY_4 52
#constant KEY_5 53
#constant KEY_6 54
#constant KEY_F1 112
#constant KEY_F2 113
#constant KEY_F3 114
#constant KEY_F4 115
#constant KEY_BACK 8
#constant KEY_TAB 9
#constant KEY_CONTROL 17
#constant KEY_PAGEUP 33
#constant KEY_PAGEDOWN 34
#constant KEY_END 35
#constant KEY_HOME 36
#constant KEY_INSERT 45
#constant KEY_DELETE 46
#constant KEY_0 48
#constant KEY_7 55
#constant KEY_8 56
#constant KEY_9 57
#constant KEY_B 66
#constant KEY_F 70
#constant KEY_G 71
#constant KEY_H 72
#constant KEY_I 73
#constant KEY_J 74
#constant KEY_K 75
#constant KEY_L 76
#constant KEY_M 77
#constant KEY_O 79
#constant KEY_P 80
#constant KEY_Q 81
#constant KEY_R 82
#constant KEY_U 85
#constant KEY_V 86
#constant KEY_Y 89
#constant KEY_F5 116
#constant KEY_F6 117
#constant KEY_F7 118
#constant KEY_F8 119
#constant KEY_SEMI 186
#constant KEY_EQUAL 187
#constant KEY_COMMA 188
#constant KEY_HYPHEN 189
#constant KEY_PERIOD 190
#constant KEY_FSLASH 191
#constant KEY_SQUOTE 192
#constant KEY_LBRACK 219
#constant KEY_BSLASH 220
#constant KEY_RBRACK 221
#constant KEY_POUND 222
#constant KEY_TICK 223
// ***********************************************************************
// TYPES
// ***********************************************************************
type TVector2D
x as float
y as float
endtype
type TColor
r as float
g as float
b as float
a as float
endtype
// ***********************************************************************
// GENERAL FUNCTIONS
// ***********************************************************************
function InitDisplay(title as string, width as integer, height as integer, maxFrameRate as float, allowResize as integer, fullscreen as integer)
SetWindowTitle(title)
SetWindowSize(width, height, fullscreen)
SetWindowAllowResize(allowResize)
SetVirtualResolution(width, height)
SetOrientationAllowed(1, 1, 1, 1)
SetScissor(0,0,0,0)
UseNewDefaultFonts(1)
SetVSync(1)
if maxFrameRate > 0 then SetSyncRate(maxFrameRate, 0)
sync()
sync()
sleep(500)
endfunction
function MinF(value1 as float, value2 as float)
result as float
if value1 < value2
result = value1
else
result = value2
endif
endfunction result
function Min(value1 as integer, value2 as integer)
result as integer
if value1 < value2
result = value1
else
result = value2
endif
endfunction result
function MaxF(value1 as float, value2 as float)
result as float
if value1 > value2
result = value1
else
result = value2
endif
endfunction result
function Max(value1 as integer, value2 as integer)
result as integer
if value1 > value2
result = value1
else
result = value2
endif
endfunction result
function SgnF(value as float)
result as float
if value < 0
result = -1
elseif value > 0
result = 1
endif
endfunction result
function Sgn(value as integer)
result as integer
if value < 0
result = -1
elseif value > 0
result = 1
endif
endfunction result
function GetFormatedInteger(value as integer, totalLength as integer)
formatted as String
formatted = right("0000000000" + str(value), totalLength)
endfunction formatted
function SetColorType(color ref as TColor, r as float, g as float, b as float, a as float)
color.r = r
color.g = g
color.b = b
color.a = a
endfunction
// ***********************************************************************
// 2D VECTOR FUNCTIONS
// ***********************************************************************
function Vector2DGetRatios(v2d ref as TVector2D)
sgnX as integer
sgnY as integer
if v2d.x < 0
sgnX = -1
elseif v2d.x > 1
sgnX = 1
endif
if v2d.y < 0
sgnY = -1
elseif v2d.y > 1
sgnY = 1
endif
if v2d.x = 0
v2d.y = sgnY
exitfunction
endif
if v2d.y = 0
v2d.x = sgnX
exitfunction
endif
if abs(v2d.x) > abs(v2d.y)
v2d.y = v2d.y / abs(v2d.x)
v2d.x = sgnX
v2d.x = v2d.x
v2d.y = v2d.y
elseif abs(v2d.x) < abs(v2d.y)
v2d.x = v2d.x / abs(v2d.y)
v2d.y = sgnY
v2d.x = v2d.x
v2d.y = v2d.y
else
v2d.x = sgnX
v2d.y = sgnY
v2d.x = v2d.x
v2d.y = v2d.y
endif
endfunction
function Vector2DNormalize(v2d ref as TVector2D)
length as float
length = sqrt((v2d.x * v2d.x) + (v2d.y * v2d.y))
v2d.x = v2d.x / length
v2d.y = v2d.y / length
endfunction
// ***********************************************************************
// ANGLE FUNCTIONS
// ***********************************************************************
function AngleGetDistanceToAngle(fromAngle as float, toAngle as float)
distance as float
if fromAngle < 0 then inc fromAngle, 360
if toAngle < 0 then inc toAngle, 360
distance = toAngle - fromAngle
endfunction distance
function AngleGetShortestDistanceToAngle(fromAngle as float, toAngle as float)
distance as float
reverseDistance as float
shortest as float
distance = AngleGetDistanceToAngle(fromAngle, toAngle)
if distance < 0
reverseDistance = distance + 360
else
reverseDistance = distance - 360
endif
if abs(distance) <= abs(reverseDistance)
shortest = distance
else
shortest = reverseDistance
endif
endfunction shortest
function AngleIsWithin(testAngle as float, AngleToCompareTo as float, degrees as float)
result as integer
if abs(AngleGetShortestDistanceToAngle(testAngle, AngleToCompareTo)) <= degrees then result = 1
endfunction result
function AngleIsBetween(testAngle as float, Angle1 as float, Angle2 as float)
result as integer
if testAngle < 0 then inc testAngle, 360
testAngle = mod(testAngle, 360)
if Angle1 < 0 then inc Angle1, 360
Angle1 = mod(Angle1, 360)
if Angle2 < 0 then inc Angle2, 360
Angle2 = mod(Angle2, 360)
if Angle1 < Angle2
result = (Angle1 <= testAngle and testAngle <= Angle2)
else
result = (Angle1 <= testAngle or testAngle <= Angle2)
endif
endfunction result
function AngleAddWithLimits(angle as float, valueToAdd as float, angleMin as float, angleMax as float)
result as integer
newa as float
a1 as float
a2 as float
newa = angle
a1 = angleMin
a2 = angleMax
if newa < 0 then inc newa, 360
if a1 < 0
inc a1, 360
inc a2, 360
elseif a2 < 0
inc a1, 360
inc a2, 360
endif
inc newa, valueToAdd
if newa < a1
newa = angleMin
elseif newa > a2
newa = angleMax
endif
if newa >= 360
dec newa, 360
elseif newa < 0
inc newa, 360
endif
endfunction newa
// ***********************************************************************
// SPRITE FUNCTIONS
// ***********************************************************************
function SetSpriteFaceSprite(sprite as integer, SpriteToFace as integer)
SetSpriteAngle(sprite, ATan2(GetSpriteYByOffset(SpriteToFace)-GetSpriteYByOffset(sprite), GetSpriteXByOffset(SpriteToFace)-GetSpriteXByOffset(sprite)))
endfunction
function SetSpriteFacePosition(sprite as integer, targetX as float, targetY as float)
SetSpriteAngle(sprite, ATan2(targetY-GetSpriteYByOffset(sprite), targetX-GetSpriteXByOffset(sprite)))
endfunction
function SetSpriteFaceMouse(sprite as integer)
SetSpriteAngle(sprite, ATan2(GetRawMouseY()-GetSpriteYByOffset(sprite), GetRawMouseX()-GetSpriteXByOffset(sprite)))
endfunction
I am sure most of you do the same thing I do when developing continually writing little bits of code to provide functionality that is very useful and often needed yet is not included in the built-in API. Unfortunately, I often end up writing these same things again and again. So I decided to make a proper project of it creating an Extended API I can use in all projects going forward. It'd be awesome if it is was built in but this is the next best thing... include files.
Ultimately, I will have 3 include files... APIGeneral.agc, API2D.agc and API3D.agc which each holding the type of stuff their name implies. For now I am putting everything into APIGeneral.agc because there is not a lot to this yet and it is more convenient to mess with one external file inclusion instead of multiple at this point.
So far I have implemented the following...
** CONSTANT DECLARATIONS **
TRUE
FALSE
TRANSPARENCY_MODE_OFF
TRANSPARENCY_MODE_ALPHA
TRANSPARENCY_MODE_ADDITIVE
KEY_LEFT
KEY_A
KEY_RIGHT
KEY_D
KEY_UP
KEY_W
KEY_DOWN
KEY_S
KEY_T
KEY_E
KEY_SPACE
KEY_N
KEY_ESC
KEY_Z
KEY_X
KEY_C
KEY_SHIFT
KEY_ENTER
KEY_1
KEY_2
KEY_3
KEY_4
KEY_5
KEY_6
KEY_F1
KEY_F2
KEY_F3
KEY_F4
** TYPES **
TVector2D
** GENERAL FUNCTIONS **
InitDisplay(title as string, width as integer, height as integer, maxFrameRate as float, allowResize as integer, fullscreen as integer)
MinF(value1 as float, value2 as float)
Min(value1 as integer, value2 as integer)
MaxF(value1 as float, value2 as float)
Max(value1 as integer, value2 as integer)
SgnF(value as float)
Sgn(value as integer)
GetFormatedInteger(value as integer, totalLength as integer)
** 2D VECTOR FUNCTIONS **
Vector2DGetRatios(v2d ref as TVector2D)
Vector2DNormalize(v2d ref as TVector2D)
** ANGLE FUNCTIONS **
AngleGetDistanceToAngle(fromAngle as float, toAngle as float)
AngleGetShortestDistanceToAngle(fromAngle as float, toAngle as float)
AngleIsWithin(testAngle as float, AngleToCompareTo as float, degrees as float)
AngleIsBetween(testAngle as float, Angle1 as float, Angle2 as float)
AngleAddWithLimits(angle as float, valueToAdd as float, angleMin as float, angleMax as float)
** SPRITE FUNCTIONS **
SetSpriteFaceSprite(sprite as integer, SpriteToFace as integer)
SetSpriteFacePosition(sprite as integer, targetX as float, targetY as float)
SetSpriteFaceMouse(sprite as integer)
And I created a little demo illustrating most of these functions...
The top 5 lines on the screen are Angle tests where A0 to A2 are angle values.
The blue sprite rotates to face the yellow sprite by using the SetSpriteFaceSprite function.
The green sprite rotates to face the yellow sprite by using the SetSpriteFacePosition passing in the position of the yellow sprite.
The red sprite rotates to face the mouse pointer (that is not visible) by using the SetSpriteFaceMouse function.
I've also added this to the CodeBase
here.
And the project for this demo is attached to this post.
Anyway, just thought this might be useful to some of you.