TGC Codebase Backup



2D Path Editor by fubarpk

11th Apr 2018 7:04
Summary

Creates paths for moving sprites



Description

Creates paths for moving sprites in a line or using a Bezier curve



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    // Project: Path Editor 
// Created: 2017-10-30

// show all errors
SetErrorMode(2)

#constant clearBtn=1
#constant test1Btn=2
#constant test2Btn=3
#constant closedBtn=4
#constant loadBtn=5
#constant saveBtn=6
#constant exitBtn=7
#constant spr=1
#constant xMax=1024
#constant yMax=768
#constant horizontalGrid=64
#constant verticalGrid=64

global renderImg=100
global closed=1 //whether or not to draw as open or closed curve

type object
	x as float
	y as float
endtype

type mySpr 
	id as integer
	x as float
	y as float
	xOffset as float
	yOffset as float
	closed as integer
endtype

global testSpr as mySpr
testSpr.id=2
testSpr.closed=closed
#include "include/Bezier Curve Library.agc"
Global dim stuff#[0]
global totalLength# = 0

gosub _bc_setup //this has to be called before any BC command, preferably before anything at all

// set window properties
SetWindowTitle( "Path Editor" )
SetWindowSize( xMax, yMax, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window

// set display properties
SetVirtualResolution( 1024, 768 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts

loadimage (1,"06.png")

CreateSprite (spr,0)
SetSpriteSize (spr,10,10)
//CreateSprite (testSpr.id,1)
CreateSprite (testSpr.id,1)
//SetSpriteSize (testSpr.id,200,200)
//SetSpriteColor (testSpr.id,0,255,0,255)
SetSpritePositionByOffset(testSpr.id,xMax/2,yMax/2)

AddVirtualButton(clearBtn,40,30,60) //make a button
SetVirtualButtonText( clearBtn, "Clear" ) //set to exit text 
SetVirtualButtonColor( clearBtn,200,200,200)  //grey colour 
AddVirtualButton(test1Btn,40,90,60) //make a button
SetVirtualButtonText( test1Btn, "Test Points" ) //set to music text 
SetVirtualButtonColor( test1Btn,200,200,200)  //grey colour 
AddVirtualButton(test2Btn,40,150,60) //make a button
SetVirtualButtonText( test2Btn, "Test Bezier" ) //set to music text 
SetVirtualButtonColor( test2Btn,200,200,200)  //grey colour 
AddVirtualButton(closedBtn,40,210,60) //make a button
if closed=1 
	SetVirtualButtonText( closedBtn, "Closed" ) //set to music text 
else
	SetVirtualButtonText( closedBtn, "Open" ) //set to music text
endif
SetVirtualButtonColor( closedBtn,200,200,200)  //grey colour 
AddVirtualButton(saveBtn,40,270,60) //make a button
SetVirtualButtonText( saveBtn, "Save" ) //set to music text 
SetVirtualButtonColor( saveBtn,200,200,200)  //grey colour 
AddVirtualButton(loadBtn,40,330,60) //make a button
SetVirtualButtonText( loadBtn, "Load" ) //set to music text 
SetVirtualButtonColor( loadBtn,200,200,200)  //grey colour 
AddVirtualButton(exitBtn,40,390,60) //make a button
SetVirtualButtonText( exitBtn, "Exit" ) //set to sound text 
SetVirtualButtonColor( exitBtn,200,200,200)  //grey colour 

CreateRenderImage (renderImg,xMax,yMax,0,0) 
CreateSprite(350,renderImg) 

dim path[100] as object
SetSpriteVisible(testSpr.id,0)
SetSpriteDepth(testSpr.id,9)
clearPoints():count=1
SetRenderToImage (renderImg,0) 
drawCrosshairAndGrid(horizontalGrid,verticalGrid)

repeat
    mx#=GetPointerX()
	my#=GetPointerY()
	SetSpritePositionByOffset(spr,mx#,my#) 
	if GetRawMouseLeftPressed() 
		path[count].x=mx#:path[count].y=my#
		SetRenderToImage (renderImg,0) 
		drawSprite(spr)
		bc_addcurvepoint(getrawmousex(),getrawmousey())
		if closed=0
			bc_calculateopencurvesegmentpoints()
		else
			bc_calculateclosedcurvesegmentpoints()
		endif
		//////////////////////////////////////////////////
        // Added these two lines here
        //////////////////////////////////////////////////
        a=bc_getcurvesegmentpointcount():dim stuff#[a]
        totalLength# = calculateLength()
		inc count
    endif
	if GetVirtualButtonPressed(clearBtn)
		clearPoints()
		count=1
		SetRenderToImage (renderImg,0) 
		drawCrosshairAndGrid(horizontalGrid,verticalGrid)
	endif
		
	Update(0)
	Render()
	setrendertoscreen () 
	
	SetSpriteSize(350,1024,768)

	Update(0)
	Render()
	swap()
	
	if GetVirtualButtonPressed(closedBtn)
		if closed=1 
			closed=0:testSpr.closed=closed
			SetVirtualButtonText( closedBtn, "Open" ) // 
		else
			closed=1:testSpr.closed=closed
			SetVirtualButtonText( closedBtn, "Closed" ) //
		endif
	endif
	
	if GetVirtualButtonPressed(test1Btn)
		testPaths()
	endif

	if GetVirtualButtonPressed(test2Btn)
		drawBezier()
		testBezierCurve()
		//Bezier2()
	endif
	
	if GetVirtualButtonPressed(saveBtn)
		saveArray(count)
	endif
	if GetVirtualButtonPressed(loadBtn)
		clearPoints()
		SetRenderToImage (renderImg,0) 
		drawCrosshairAndGrid(horizontalGrid,verticalGrid)
		count=loadArray()
	endif
		
until GetVirtualButtonPressed(exitBtn)
end

function drawCrosshairAndGrid(gridX, gridY)
	for y=0 to yMax step gridX
		drawline(0,y,xMax,y,0,255,0)
	next y
	for x=0 to xMax step gridY
		drawline(x,0,x,yMax,0,255,0)
	next x
    drawline(0,yMax/2,xMax,yMax/2,255,0,0)
	drawline(xMax/2,0,xMax/2,yMax,255,0,0)		
endfunction

function clearPoints ()
for t = 0 to 100
	path[t].x=0:path[t].y=0
next t
BC_RemoveCurvePoints()
DeleteSprite(350):DeleteImage(renderImg)
renderImg=CreateRenderImage (xMax,yMax,0,0) 
CreateSprite(350,renderImg) 
endfunction

function drawBezier()
if bc_getcurvesegmentpointcount()>0
	SetRenderToImage (renderImg,0) 
	for i=0 to bc_getcurvesegmentpointcount()-2 //normally use -1, but I want to stop 1 early of the end of the array
		drawline(bc_getcurvesegmentpointx(i),bc_getcurvesegmentpointy(i),bc_getcurvesegmentpointx(i+1),bc_getcurvesegmentpointy(i+1),255,0,0)
 	next i
endif
Update(0)
Render()
setrendertoscreen () 
Update(0)
Render()
swap()
	
endfunction

function testBezierCurve()
testSpr.xOffset=0:testSpr.yOffset=0
SetSpriteVisible(testSpr.id,1)
if bc_getcurvesegmentpointcount()>0
	for i=0 to bc_getcurvesegmentpointcount()-1 //normally use -1, but I want to stop 1 early of the end of the array
		
	//////////////////////////////////////////////////
    // Constant speed around the bezier curve
    //////////////////////////////////////////////////
		if bc_getcurvesegmentpointcount() > 0
        // Simply to control an even time update
			if timestamp <= getMilliseconds()
				// A point on the bezier curver lies between 0 and 1.
				t# = t# + 0.001
				// If time goes beyond 1, subtract 1. This will provide
				// a more even movement.
				if t# > 1 then t# = t# - 1
 
				// How far from the beginning of the curve are we
				seg# = totalLength# * t#
				// Find the point at the beginning of the line segment that we are currently on
				s = getCurveSegmentPointAtDistance(seg#)
				// Calculate the length of this line segment
				segLength# = stuff#[s+1] - stuff#[s]
				// Calculate how far along this single line segment we are
				partSegLength# = seg# - stuff#[s]
				n# = partSegLength# / segLength#
				print(n#)
				// Use some linear interpolation to determine the coordinates on this line segment
				x = bc_getcurvesegmentpointx(s) + (bc_getcurvesegmentpointx(s+1)-bc_getcurvesegmentpointx(s))*n#
				y = bc_getcurvesegmentpointy(s) + (bc_getcurvesegmentpointy(s+1)-bc_getcurvesegmentpointy(s))*n#
				// Position the sprite
				SetSpritePositionByOffset(testSpr.id,bc_getcurvesegmentpointx(i)+testSpr.xOffset,bc_getcurvesegmentpointy(i)+testSpr.yOffset)			
				// Update timer
				timestamp = getMilliseconds() + 20
			endif
		endif
 		
		//SetSpritePositionByOffset(testSpr.id,bc_getcurvesegmentpointx(i)+testSpr.xOffset,bc_getcurvesegmentpointy(i)+testSpr.yOffset)
		//add following to point to centre
		angle#=getAngle(bc_getcurvesegmentpointx(i),bc_getcurvesegmentpointy(i),bc_getcurvesegmentpointx(i+1),bc_getcurvesegmentpointy(i+1))
		SetSpriteAngle(testSpr.id,getAngle(GetSpriteXByOffset(testSpr.id),GetSpriteYByOffset(testSpr.id),xMax/2,yMax/2)):rem point to middle of screen
		sync()
 	next i
endif
SetSpriteVisible(350,1)
SetSpriteVisible(testSpr.id,0)
endfunction

function testPaths()
//testSpr.x=xMax/2:testSpr.y=yMax/2
testSpr.xOffset=0:testSpr.yOffset=0

testSpr.x=path[1].x+testSpr.xOffset:testSpr.y=path[1].y+testSpr.yOffset
count=1:speed#=5
//SetSpriteVisible(350,0)
SetSpriteVisible(testSpr.id,1)
rem move sprite X steps
repeat
	SetSpritePositionByOffset(testSpr.id,testSpr.x,testSpr.y)	
	//SetSpriteSize(testspr,200,200)
	while getDistance(testSpr.x,testSpr.y,path[count+1].x,path[count+1].y)>5
		angle#=getAngle(testSpr.x,testSpr.y,path[count+1].x,path[count+1].y)
		testSpr.x=testSpr.x-sin(angle#)*speed#:testSpr.y=testSpr.y+cos(angle#)*speed#
		SetSpritePositionByOffset(testSpr.id,testSpr.x+testSpr.xOffset,testSpr.y+testSpr.yOffset)
		SetSpriteAngle(testSpr.id,getAngle(GetSpriteXByOffset(testSpr.id),GetSpriteYByOffset(testSpr.id),xMax/2,yMax/2)):rem point to middle of screen
		//SetSpriteAngle(testspr,angle#):rem point to way point
		print( getDistance(testSpr.x,testSpr.y,path[count+1].x,path[count+1].y))
		sync()
		
	endwhile	
	//x=path[count+1].x:y=path[count+1].y
	inc count	
	
until path[count+1].x=0 and path[count+1].y=0
rem move sprite to first point if closed path
if testSpr.closed=1
	while getDistance(testSpr.x,testSpr.y,path[1].x,path[1].y)>5
		angle#=getAngle(testSpr.x,testSpr.y,path[1].x,path[1].y)
		testSpr.x=testSpr.x-sin(angle#)*speed#:testSpr.y=testSpr.y+cos(angle#)*speed#
		SetSpritePositionByOffset(testSpr.id,testSpr.x+testSpr.xOffset,testSpr.y+testSpr.yOffset)
		SetSpriteAngle(testSpr.id,getAngle(GetSpriteXByOffset(testSpr.id),GetSpriteYByOffset(testSpr.id),xMax/2,yMax/2)):rem point to middle of screen
		//SetSpriteAngle(testspr,angle#):rem point to way point
		print( getDistance(testSpr.x,testSpr.y,path[count+1].x,path[count+1].y))
		sync()
	endwhile	
endif	

SetSpriteVisible(350,1)
SetSpriteVisible(testSpr.id,0)

endfunction	

function getAngle(x1#, y1#, x2#, y2#)
    result# = ATanFull(x1# - x2#, y1# - y2#)
endfunction result#


function getDistance (x1#,y1#,x2#,y2#) 
	dx#=x1#-x2#
	dy#=y1#-y2#
	distance#=sqrt((dx#*dx#)+(dy#*dy#)):rem distance object to path point
endfunction distance#

function difference(x as float ,y as float)
diff as float
diff = (x-y)
endfunction diff


function saveArray(count as integer)
write = OpenToWrite("arrayPath.txt" ,0)
length=count 
String$ = Str(length-1)
WriteLine (write,String$)
WriteLine (write,Str(closed))
for num=1 to length
	StringX$ = Str(path[num].x-(xMax/2))
	StringY$ = Str(path[num].y-(yMax/2))
	WriteLine (write,StringX$)
	WriteLine (write,StringY$)
next num
Closefile(write)
write = OpenToWrite("arrayBezier.txt" ,0)
length=bc_getcurvesegmentpointcount()-1 
String$ = Str(length-1)
WriteLine (write,String$)
WriteLine (write,Str(closed))
if bc_getcurvesegmentpointcount()>0
	for i=1 to bc_getcurvesegmentpointcount()-2 //normally use -1, but I want to stop 1 early of the end of the array
		StringX$ = Str((bc_getcurvesegmentpointx(i)+testSpr.xOffset)-(xMax/2))
		StringY$ = Str((bc_getcurvesegmentpointy(i)+testSpr.yOffset)-(yMax/2))
		WriteLine (write,StringX$)
		WriteLine (write,StringY$)
 	next i
endif
Closefile(write)

endfunction

function loadArray()
for t = 0 to 100
	path[t].x=0:path[t].y=0
next t

If GetFileExists("arrayPath.txt")
	read = OpenToRead("arrayPath.txt")
	String1$ = ReadLine(read)
	length=val(String1$)
	String2$ = ReadLine(read)
	closed=val(String2$):testSpr.closed=closed
	BC_RemoveCurvePoints()
	//dim path[length] as object
	for num =1 to length
		StringX$ = ReadLine(read)
		StringY$ = ReadLine(read)
		path[num].x=((xMax/2)+val(StringX$))
		path[num].y=((yMax/2)+val(StringY$))	
		
		SetRenderToImage (renderImg,0) 
		SetSpritePosition(spr,path[num].x,path[num].y)
		drawSprite(spr)
		bc_addcurvepoint(path[num].x,path[num].y)
		if closed=0
			bc_calculateopencurvesegmentpoints()
		else
			bc_calculateclosedcurvesegmentpoints()
		endif
		
		//////////////////////////////////////////////////
        // Added these two lines here
        //////////////////////////////////////////////////
        a=bc_getcurvesegmentpointcount()
        dim stuff#[a]
        totalLength# = calculateLength()
		
		Update(0)
		Render()
		setrendertoscreen () 
	
		SetSpriteSize(350,1024,768)

		Update(0)
		Render()
		swap()
	next num
	Closefile(read)
	if closed=1 
		SetVirtualButtonText( closedBtn, "Closed" ) //set to music text 
	else
		SetVirtualButtonText( closedBtn, "Open" ) //set to music text
	endif
	count=length
	
endif
endfunction count

//////////////////////////////////////////////////
// Calculates the distance of each point from the
// beginning of the curve.
// Returns total length of the curve.
//////////////////////////////////////////////////
function calculateLength()
    total# = 0
    if bc_getcurvesegmentpointcount() > 0
        for i = 0 to bc_getcurvesegmentpointcount() - 2
            x# = (bc_getcurvesegmentpointx(i)-bc_getcurvesegmentpointx(i+1))^2
            y# = (bc_getcurvesegmentpointy(i)-bc_getcurvesegmentpointy(i+1))^2
            d# = sqrt(x# + y#)
            total# = total# + d#
            stuff#[i] = total#
        next i
    endif
endfunction total#
 
 
//////////////////////////////////////////////////
// Finds which line segment that 'd#' falls on.
// Since this array is technically a sorted list,
// it can be modified into a binary search for
// improved lookup speeds.
//////////////////////////////////////////////////
function getCurveSegmentPointAtDistance(d#)
    for i = 0 to bc_getcurvesegmentpointcount() - 2
        if d# >= stuff#[i] and d# < stuff#[i+1] then exitfunction i
    next i
endfunction 0