Latest beta 0.2 release.
https://forumfiles.thegamecreators.com/download/2371773
Camera fx.
This is the Official thread for my work with the open source mode 7 engine.
History:
It all started with Apocolyp4 cool 19 line code snippet.
SetVirtualResolution(480, 320)
mapImageNumber = LoadImage("SuperMarioKartMapMushroomCup1.png")
mapSpriteNumber = CreateSprite(mapImageNumber)
SetSpritePosition(mapSpriteNumber, -15, -512)
SetViewZoomMode(1)
do
zoom# = 4.0
for i = 320 to 0 step -1
zoom# = zoom# - 0.0125
SetViewZoom(zoom#)
SetScissor(0, i, 480, i - 1)
Render()
next i
//scroll the map
SetSpriteY(mapSpriteNumber, GetSpriteY(mapSpriteNumber) + 0.1)
//rotate the map
SetSpriteAngle(mapSpriteNumber, GetSpriteAngle(mapSpriteNumber) - 0.1)
Sync()
loop
And after he posted it so have i worked alot on it and improved it a huge bit.
Why a new thread? :
I feelt that i can organise my updates alot easier this way and its mostly me working on it.
Goal:
Make an complete and working mario kart clone engine that users simply can make small changes and change the media for to make it there own.
Rules/copyright:
Dont use my media in your final app as it whil look foolish with a bundle of mario kart clones that look the same.
I have also planned to maybe release my own clone for free when the engine is finished.
Give credit to the ones that put down code snippets and work on the engine.
So far is the credits list.
Cliff MellangÄrd. ( Main code )
Apocolyp4. ( Basic track rendering function )
Baxlash. ( Sprite placement on the track function )
Sorry if i forgot someone?
There is also alot of people that have contributed with feedback and input on improvements .
You dont have to pay any royaltys and can earn how much money you want on your version.
But you are not allowed to sell this as a mode 7 engine or game maker.
Video History:
Apocolyp4 Original snippet.
My first changes.
My changes by rewritting baxslash spritetoworld function.
My beta 0.2 release.
Games in the works.
Death Cars by erebusman
F Zero clone By Apocalyp4 (pending)
When downloading the source keep in mind that they are.
Work in progress with alot of junk source and functions.
Alot of the source will change during the development.
Its written in
AGK Tier 1 Basic 1074.
Works with the current player in portrait mode only.
There is a bug in the landscape set scissor and get image commands that screws it up.
If you are new to agk.
Wath could you learn from this?
Organise the code in files.
Simple tile mapper.
Use agks various image manipulation.
Usage of types.
Usage of set sprite uv for backgrounds.
Using sprites fixed to the screen and in world space together to get various effects.
A good example of how a messy coder writes its code
ETC.
Drawbacks with the engine.
Iam a very slow programmer and it can be while in betwen updates.
Thats why its great that its open source
If you want to check the thread that started it all go here!
http://forum.thegamecreators.com/?m=forum_view&b=48&t=197576&p=0
Track editor controls.
1-3 selects grass,gravel or wather for the ground.
Simply hold down any of the keys and move the mouse over the track.
To place track tiles simply select one on the right side and draw with it.
But keep in mind to not use any of the last 3 tiles as this will screw up the map code.
If you click on an placed sprite so is it deleted.
Keep in mind that the editor is extremely basic.
And saves the track everytime you exit the editor.
//// Source code in plain text ///////////////////edited 12-07-09 //
Ok!
I have spent the day with cleaning up the source code
Wath a mess i released
In the future when i do small updates so will i post them like this instead.
Is it ok?
I thought that everyone dosent like to download unknown zip files.
Iam one of them
Could also be alot easier to get feedback from others on improvements.
And if you modify a file to the better post it like this and name wath file it is!
So is it alot easier to insert your code improvements and fixes
main.agc
rem
rem AGK Application
rem
rem Landscape App
setsyncrate(0,0)
REM // original snes mostly used 256x224
#Constant ScrWidth 320
#Constant ScrHeight 240
SetVirtualResolution( ScrWidth, ScrHeight )
global Render_Detail,Debugging
Gosub Initiate_Player
Gosub Initiate_AGKmode7
Gosub Initiate_Entitys
Gosub Initiate_Map
#include "AGKmode7.agc"
#include "Player.agc"
#include "Entitys.agc"
#include "Editor.agc"
#include "Misc.agc"
mode=0
Move_VRcamera(Player.X,Player.Y)
Map_File( "load" , "test.Map" )
Generate_Map_Image()
global GFT#
do
GFT# = GetFrameTime()
if mode=0
GameMode()
else
EditorMode()
endif
// tab key change engine mode
if GetRawKeyPressed(9)=1 then inc mode
if mode>1
mode=0
Hide_Show_Media(1)
Generate_Map_Image()
Map_File( "save" , "test.Map" )
endif
// escape on computer and back button on device
if GetRawKeyState(27)=1 then end
Sync()
loop
Function GameMode()
Current_Speed#=Player.Drive_Speed
// 34 is the value you get by dividing the track size with mapwidth and height
px=1+(floor(Player.X)/34)
py=1+(floor(Player.Y)/34)
if Map[px,py].Tile=0 or Map[px,py].Tile>48
if Map[px,py].Ground=0 then groundType$=" On Grass "
if Map[px,py].Ground=1 then groundType$=" On Gravel "
if Map[px,py].Ground=2 then groundType$=" On wather "
print("Get back on to the road!"+groundType$ )
Current_Speed#=Current_Speed#/2.2
endif
//scroll the world
if GetDirectionY() <-0.02
Player.X=Player.X + (cos(VRcamera.Angle) * (Current_Speed#*GFT#))
Player.Y=Player.Y + (sin(VRcamera.Angle) * (Current_Speed#*GFT#))
endif
if GetDirectionY() >0.02
Player.X=Player.X - (cos(VRcamera.Angle) * (Current_Speed#*GFT#))
Player.Y=Player.Y - (sin(VRcamera.Angle) * (Current_Speed#*GFT#))
endif
setspriteframe(Player.Sprite,1)
//rotate the map
if GetDirectionX() <-0.02
SetSpriteAngle(VRcamera.Ground, GetSpriteAngle(VRcamera.Ground) + (Player.Turn_Speed*GFT#))
UV_Scroller( VRcamera.Scroll-((Player.Turn_Speed*GFT#)/100) , VRcamera.Scroll2-((Player.Turn_Speed*GFT#)/140) )
VRcamera.Angle = VRcamera.Angle - (Player.Turn_Speed*GFT#)
setspriteframe(Player.Sprite,3)
endif
if GetDirectionX() >0.02
SetSpriteAngle(VRcamera.Ground, GetSpriteAngle(VRcamera.Ground) - (Player.Turn_Speed*GFT#))
UV_Scroller( VRcamera.Scroll+((Player.Turn_Speed*GFT#)/100) , VRcamera.Scroll2+((Player.Turn_Speed*GFT#)/140) )
VRcamera.Angle = VRcamera.Angle + (Player.Turn_Speed*GFT#)
setspriteframe(Player.Sprite,2)
endif
Move_VRcamera(Player.X,Player.Y)
for t=1 to MAX_Entitys
if Entity[t].X>1024.0 or Entity[t].Y>1024.0 then Entity[t].Angle=Entity[t].Angle+180
if Entity[t].X<0.0 or Entity[t].Y<0.0 then Entity[t].Angle=Entity[t].Angle-180
Entity[t].X = Entity[t].X + (cos(Entity[t].Angle) * ( Entity[t].Speed*GFT# ))
Entity[t].Y = Entity[t].Y + (sin(Entity[t].Angle) * ( Entity[t].Speed*GFT# ))
next t
REM // Call the track renderer
Setspritevisible(VRcamera.Ground,1)
Render_Track( ScrHeight , 90 )
if Debugging=0
SetSpriteTransparency( VRcamera.Ground , 0 )
Setspritevisible(VRcamera.Ground,0)
else
SetSpriteTransparency( VRcamera.Ground , 1 )
endif
print("Detail Track sprite " )
print("Fps = "+str( Screenfps() ) )
REM // Grabb the whole screen so we get the kart and all the text
SetScissor(0, ScrHeight, ScrWidth,0)
REM // various debugging buttons
if GetPointerPressed()
if GetPointerX()<32 and GetPointerY()<32 then inc Render_Detail
if GetPointerX()>ScrWidth-32 and GetPointerY()<32 then inc Debugging
if Render_Detail>1 then Render_Detail=0
if Debugging>1 then Debugging=0
endif
endfunction
AGKmode7.agc
Initiate_AGKmode7:
type sVRcamera
X As Float
Y As Float
Tilt As Integer
Angle As Float
Ground As integer
Back As Integer
Back2 As Integer
Scroll As Float
Scroll2 As Float
endtype
Global VRcamera As sVRcamera
VRcamera.X = ScreenToWorldX( ScrWidth/2 )
VRcamera.Y = ScreenToWorldY( ScrHeight )
REM // This is the default angle and points to the right side of the screen
REM // The same as agks default sprite angle.
VRcamera.Angle = 0.0
REM // Default is 56
VRcamera.Tilt = 52
REM ///////////////////////////////////////////////////
REM // Prepare the track sprite for the virtual camera
REM // Use an image in the size 1024x1024
REM ///////////////////////////////////////////////////
VRcamera.Ground = CreateSprite(0)
setspritesize( VRcamera.Ground , 1024 , 1024 )
SetSpritePosition(VRcamera.Ground, 0, 0)
SetSpriteAngle(VRcamera.Ground, -90)
REM // Set transparency off only for final build for best performance
SetSpriteTransparency( VRcamera.Ground , 0 )
SetSpriteActive ( VRcamera.Ground, 0 )
setspritedepth(VRcamera.Ground,100)
REM ////////////////////////////
REM // Virtual camera background
REM ////////////////////////////
// Parallax front
img = LoadImage( "para_front.png" )
SetImageMagFilter( img , 0 )
SetImageMinFilter( img , 0 )
REM // configure for Scrolling
SetImageWrapU( img , 1 )
SetImageWrapV( img , 1 )
VRcamera.Back = CreateSprite( img )
setspritesize( VRcamera.Back , ScrWidth , ScrHeight )
fixspritetoscreen( VRcamera.Back , 1 )
setspritedepth( VRcamera.Back ,1000 )
// Parallax back
img = LoadImage( "para_back.png" )
SetImageMagFilter( img , 0 )
SetImageMinFilter( img , 0 )
REM // configure for Scrolling
SetImageWrapU( img , 1 )
SetImageWrapV( img , 1 )
VRcamera.Back2 = CreateSprite( img )
setspritesize( VRcamera.Back2 , ScrWidth , ScrHeight )
fixspritetoscreen( VRcamera.Back2 , 1 )
setspritedepth( VRcamera.Back2 ,1001 )
return
REM // Simplified function for placing the camera on the track
REM // Usage = Move_VRcamera( 10.0 , 10.0 ) / Places the camera 10 pixels in to the track on x/y coords
REM ///////////////////////////////////////////////////////////////////////////////////////////////////
Function Move_VRcamera( X# , Y# )
SetViewOffset( X# - ScrWidth/2 , Y# - ScrHeight )
VRcamera.X = ScreenToWorldX( ScrWidth/2 )
VRcamera.Y = ScreenToWorldY( ScrHeight )
SetSpriteOffset( VRcamera.Ground, VRcamera.X , VRcamera.Y )
SetSpritepositionbyOffset( VRcamera.Ground, VRcamera.X , VRcamera.Y )
endfunction
REM // Based on steven holdings (baxslash) spritetoworld functions
REM //------------------------------------------------------------
REM // Simplified functions for placing sprites on the track like
REM // Rival karts,trees or other objects.
REM // Usage = SetSpritepositionbyOffset( test_sprite, Get_Ground_X(10.0,50.0) , Get_Ground_Y(10.0,50.0) )
REM //////////////////////////////////////////////////////////////////////////////////////////////////////
function Get_Ground_X(x#,y#)
x#= - VRcamera.X + x#
y#= - VRcamera.Y + y#
rem get sprite data
a# = getSpriteAngle(VRcamera.Ground)
ox# = getSpriteXbyOffset(VRcamera.Ground)
scaleX# = getSpriteWidth(VRcamera.Ground)/1024
scaleY# = getSpriteHeight(VRcamera.Ground)/1024
REM // calculate value
dx# = ( cos(a#)*(x# * scaleX#) ) - ( sin(a#)*(y# * scaleY#) )
wx# = ox# + dx#
endfunction wx#
function Get_Ground_Y(x#,y#)
x#= - VRcamera.X + x#
y#= - VRcamera.Y + y#
rem get sprite data
a# = getSpriteAngle(VRcamera.Ground)
oy# = getSpriteYbyOffset(VRcamera.Ground)
scaleX# = getSpriteWidth(VRcamera.Ground)/1024
scaleY# = getSpriteHeight(VRcamera.Ground)/1024
rem calculate value
dy# = ( sin(a#)*(x# * scaleX#) ) + ( cos(a#)*(y# * scaleY#) )
wy# = oy# + dy#
endfunction wy#
Function Set_Ground_XY(spr,x#,y#)
x#= - VRcamera.X + x#
y#= - VRcamera.Y + y#
rem get sprite data
a# = getSpriteAngle(VRcamera.Ground)
ox# = getSpriteXbyOffset(VRcamera.Ground)
oy# = getSpriteYbyOffset(VRcamera.Ground)
scaleX# = getSpriteWidth(VRcamera.Ground)/1024
scaleY# = getSpriteHeight(VRcamera.Ground)/1024
REM // calculate value
dx# = ( cos(a#)*(x# * scaleX#) ) - ( sin(a#)*(y# * scaleY#) )
dy# = ( sin(a#)*(x# * scaleX#) ) + ( cos(a#)*(y# * scaleY#) )
SetSpritepositionbyOffset( spr , (ox# + dx#) , (oy# + dy#) )
endfunction
Function Render_Track( Bottom , Top )
scalus = 1024*8
for t=1 to MAX_Entitys
x# = Entity[t].X
y# = Entity[t].Y
Set_Ground_XY( Entity[t].SPR , x# , y# )
oy# = getspriteybyoffset( Entity[t].SPR )
ys = worldtoscreeny(oy#)
setspritevisible( Entity[t].SPR , 0 )
Entity[t].Drawed = 1
if ys > 0-VRcamera.Tilt then if ys =< ScrHeight
Entity[t].Size = (64.0 / GetDistance( 0.0 , VRcamera.Y , 0.0 , oy# ) * 32.0 )
if Entity[t].Size > 64.0 then Entity[t].Size = 64.0
REM // This is a zimple z depth buffer ,the largest sprites overlapps the smaller ones
setspritedepth( Entity[t].SPR , 100 - Entity[t].Size )
setSpritesize( Entity[t].SPR , Entity[t].Size , Entity[t].Size )
Entity[t].Drawed = 0
endif
next t
Fade#=255.0
for i = Bottom to Top step -1
REM // Grabb the track stripe ///
setSpritesize(VRcamera.Ground,scalus,scalus)
SetSpriteColor( VRcamera.Ground , Fade#, Fade#, Fade#, 255 )
SetScissor(0, i, ScrWidth, i + 1)
DrawSprite(VRcamera.Ground)
REM // Position the sprite entitys on screen
for t=1 to MAX_Entitys
if Entity[t].Drawed=0
x#=Entity[t].X
y#=Entity[t].Y
SetSpriteColor( Entity[t].SPR , Fade#, Fade#, Fade#, 255 )
Set_Ground_XY( Entity[t].SPR , x# , y# )
ys=worldtoscreeny(getspriteybyoffset(Entity[t].SPR))
if ys>i
xs=worldtoscreenx(getspritexbyoffset(Entity[t].SPR))
if xs>0 then if xs<ScrWidth
REM // Simple backtrack to get it smooth
for t2=3 to VRcamera.Tilt Step 3
setSpritesize(VRcamera.Ground,scalus+t2,scalus+t2)
Set_Ground_XY( Entity[t].SPR , x# , y# )
ys=worldtoscreeny(getspriteybyoffset(Entity[t].SPR))
if ys=i then exit
next t2
setspritevisible(Entity[t].SPR,1)
setSpritesize(VRcamera.Ground,scalus,scalus)
endif
Entity[t].Drawed=1
endif
endif
next t
Fade#=i*1.8
scalus=scalus-VRcamera.Tilt
next i
scalus=1024
setSpritesize(VRcamera.Ground,scalus,scalus)
endfunction
Entitys.agc
REM // This is simply the other racer karts and pickups
Initiate_Entitys:
#constant MAX_Entitys 100
type sEnt
_Type As Integer
X As Float
Y As Float
Angle As Float
Speed As Float
Size As Float
Drawed As Integer
SPR As Integer
Node As Integer
Go As Integer
endtype
global dim Entity[MAX_Entitys] as sEnt
img = LoadImage("sign.png")
SetImageMagFilter( img , 0 )
SetImageMinFilter( img , 0 )
for t=1 to MAX_Entitys
Entity[t].SPR = CreateSprite(img)
SetSpriteOffset( Entity[t].SPR, 32 , 64 )
Entity[t].Angle = 45.0
Entity[t].X = random(10.0,1014.0)
Entity[t].Y = random(10.0,1014.0)
Entity[t].Speed = 60.0
setspritedepth( Entity[t].SPR ,0 )
next t
Return
Editor.agc
Initiate_Map:
global MapWidth = 30
global MapHeight = 30
type sMap
Tile As Integer
Ground As integer
endtype
global dim Map [ MapWidth,MapHeight ] As sMap
return
Function EditorMode()
SetViewOffset( 0.0 , 0.0 )
Hide_Show_Media(0)
REM // Draw map
for x=1 to MapWidth
for y=1 to MapHeight
setspriteposition(tile_spr,-Tile_Scale+x*Tile_Scale,-Tile_Scale+y*Tile_Scale)
if Map[x,y].Ground=0
setspriteframe(tile_spr,last_Tile_Frame)
else
if Map[x,y].Ground=1 then setspriteframe(tile_spr,last_Tile_Frame-1)
if Map[x,y].Ground=2 then setspriteframe(tile_spr,last_Tile_Frame-2)
endif
Drawsprite(tile_spr)
if Map[x,y].Tile>0
setspriteframe(tile_spr,Map[x,y].Tile)
Drawsprite(tile_spr)
endif
next y
next x
Rem // Draw tiles
for t=0 to 15
setspriteframe(tile_spr,t+1)
setspriteposition(tile_spr,ScrWidth-(Tile_Scale*4),t*Tile_Scale)
Drawsprite(tile_spr)
setspriteframe(tile_spr,t+2+15)
setspriteposition(tile_spr,ScrWidth-(Tile_Scale*3),t*Tile_Scale)
Drawsprite(tile_spr)
setspriteframe(tile_spr,t+3+15+15)
setspriteposition(tile_spr,ScrWidth-(Tile_Scale*2),t*Tile_Scale)
Drawsprite(tile_spr)
setspriteframe(tile_spr,t+4+15+15+15)
setspriteposition(tile_spr,ScrWidth-Tile_Scale,t*Tile_Scale)
Drawsprite(tile_spr)
next t
setspriteposition(tile_spr,-10000,-10000)
msx=1+floor(GetPointerX())/Tile_Scale
msy=1+floor(GetPointery())/Tile_Scale
if msx=<MapWidth
if GetPointerState()=0 then click=0
if GetPointerState()=1 then if click<>1
if Map[msx,msy].Tile=0 then click=2
Map[msx,msy].Tile=Selected_Tile
endif
if GetPointerState()=1 then if click<2
if Map[msx,msy].Tile>0 then click=1
Map[msx,msy].Tile=0
endif
// key 1
if GetRawKeyState(49)=1 then Map[msx,msy].Ground=0
// key 2
if GetRawKeyState(50)=1 then Map[msx,msy].Ground=1
// key 3
if GetRawKeyState(51)=1 then Map[msx,msy].Ground=2
else
selection=msy
if GetPointerX()>ScrWidth-(Tile_Scale*3) then inc selection,16
if GetPointerX()>ScrWidth-(Tile_Scale*2) then inc selection,16
if GetPointerX()>ScrWidth-Tile_Scale then inc selection,16
if GetPointerPressed() then if msy =< 16 then Selected_Tile = selection
endif
print(msx )
Endfunction
Function Generate_Map_Image()
if GetSpriteExists(tile_spr)=0
global Tile_Scale=8
global Selected_Tile=1
global click
global last_Tile_Frame = 64
Global Texture_Scale= 16
img = LoadImage("texture.png")
global tile_spr
tile_spr = CreateSprite( img )
fixspritetoscreen(tile_spr,1)
setspriteposition(tile_spr,-10000,-10000)
SetSpriteAnimation( tile_spr, Texture_Scale, Texture_Scale, last_Tile_Frame )
setspritesize(tile_spr,Tile_Scale,Tile_Scale)
endif
REM // Draw map
for x=1 to MapWidth
for y=1 to MapHeight
setspriteposition(tile_spr,-Tile_Scale+x*Tile_Scale,-Tile_Scale+y*Tile_Scale)
if Map[x,y].Ground=0
setspriteframe(tile_spr,last_Tile_Frame)
else
if Map[x,y].Ground=1 then setspriteframe(tile_spr,last_Tile_Frame-1)
if Map[x,y].Ground=2 then setspriteframe(tile_spr,last_Tile_Frame-2)
endif
Drawsprite(tile_spr)
if Map[x,y].Tile>0
setspriteframe(tile_spr,Map[x,y].Tile)
Drawsprite(tile_spr)
endif
next y
next x
setspriteposition(tile_spr,-10000,-10000)
img=GetSpriteImageID(VRcamera.Ground)
DeleteImage(img)
img=GetImage(0,0,240,240)
SetImageMagFilter( img, 0 )
SetImageMinFilter( img, 0 )
SetSpriteImage(VRcamera.Ground,img)
Endfunction
///////////////////////
///////////////////////
Function Map_File( state as string , file_io as string )
If GetFileExists( file_io )=0 and state = "load" then ExitFunction
If state = "load" then OpenToRead ( 1 , file_io )
If state = "save" then OpenToWrite ( 1, file_io, 0 )
For x = 0 to MapWidth
For y = 0 to MapHeight
If state = "load"
Map [ x,y ].Tile = ReadInteger ( 1 )
Map [ x,y ].Ground = ReadInteger ( 1 )
Endif
If state = "save"
WriteInteger ( 1 , Map [ x,y ].Tile )
WriteInteger ( 1 , Map [ x,y ].Ground )
Endif
Next y
Next x
CloseFile ( 1 )
EndFunction
//////////////////////////
//////////////////////////
NEW file!! simply create an blank file and name it the same as i wrote down under.
Player.agc
Initiate_Player:
type sPlayer
Sprite As integer
X As float
Y As float
Angle As Float
Drive_Speed As integer
Turn_Speed As float
endtype
global Player as sPlayer
Player.X = 0.0
Player.Y = 0.0
Player.Drive_Speed = 120.0
Player.Turn_Speed = 120.0
REM // Prepare our kart
img = LoadImage("kart.png")
SetImageMagFilter( img, 0 )
SetImageMinFilter( img, 0 )
Player.Sprite = CreateSprite(img)
fixspritetoscreen(Player.Sprite,1)
setspritesize(Player.Sprite,64,64)
SetSpriteAnimation( Player.Sprite, 32, 32, 4 )
SetSpritePosition(Player.Sprite, ( ScrWidth/2 )-32, ScrHeight-64)
Return
NEW file!! simply create an blank file and name it the same as i wrote down under.
Misc.agc
function Hide_Show_Media(state)
for t=1 to MAX_Entitys
setspritevisible( Entity[t].SPR , state )
next t
setspritevisible( VRcamera.Back , state )
setspritevisible( VRcamera.Back2 , state )
setspritevisible( Player.Sprite , state )
endfunction
Function UV_Scroller( Scroll1# , Scroll2# )
Rem // Parallax background //
VRcamera.Scroll = Scroll1#
if VRcamera.Scroll<0.0 then VRcamera.Scroll=VRcamera.Scroll+1.0
if VRcamera.Scroll>1.0 then VRcamera.Scroll=VRcamera.Scroll-1.0
SetSpriteUVOffset(VRcamera.Back,VRcamera.Scroll,0.0)
VRcamera.Scroll2=Scroll2#
if VRcamera.Scroll2<0.0 then VRcamera.Scroll2=VRcamera.Scroll2+1.0
if VRcamera.Scroll2>1.0 then VRcamera.Scroll2=VRcamera.Scroll2-1.0
SetSpriteUVOffset(VRcamera.Back2,VRcamera.Scroll2,0.0)
EndFunction
function WrapRotate(a#,v#)
a# = a# + v#
a# = a# - (floor(a#/360) * 360)
endfunction a#
function Point_TO(x#,y#,x2#,y2#)
new_angle# = atanfull(x2#-x#,y2#-y#)
new_angle# = new_angle# - (floor(new_angle#/360) * 360)
endfunction new_angle#
Function GetDistance( x#, y#, x2#, y2#)
d# = sqrt( ((x# - x2#)^2) + ((y# - y2#)^2) )
Endfunction d#