Scripting System - Basic Tutorial
---------------------------------
This scripting system is very flexible, and can be used for practically anything you like. What is does basically, is give the the ability to read external data into DBPro. The
data could be anything, it could be data to store what your level should look like, it might be a set of commands you might want to execute at a certain time (though it is not a
programming language in itself, something similar could be made).
For example, say you were building a text based game, and you got to a certain spot, you might want it to print to the screen "Well Done!", this is easily done, for example,
your script could look like this:
print(10,10,"Well Done!");
Maybe you might want it to center text to the center of the screen, with big red letters...
print(center text){
x = 512,
y = 384,
size = 26,
red = 255,
green = 0,
blue = 0,
text = "Well Done!",
}wdText;
This 'print' command isn't an actual command, but you can check your script for it, and make it a command of your own.
You will notice after the last brace } and before the semi-colon ; , there is a variable. This is the command return, which should be unique to all commands. It's good because
you may have lots of similar commands, but one of them has to special, for example, there may be lots of commands to make spheres, but one of them you might want to be a sky
sphere, you could check all the commands will you find "skySph" as the return.
You will notice on both examples I put a semi-colon ; at the end of the commands. These are needed so the commands can be recignised as seperate commands.
You will also notice on the first example I used parameters, and on the second one I used some form of data statements. The difference is not big, but it is much easier to work
with data statements, but parameters are quicker. The parameters are numbers, so you have to retrieve them by the number they are, i.e.
"makeCube(1,100,200,300)"
Parameter 3 would be "200".
With data statements, you call them by name, so it doesn't matter if you take one out, you'll still get the one you called.
Parameters always come first, and are between brackets (), you don't need data statements, but if you do, you have to use braces {}.
All parameters have to be split up using commas, and so do data statements, even if they are arranged in vertical order.
Using it in DBPro
Well first you have to actually copy and paste the functions into your project, or an include file (I will give you the updated functions at the bottom).
Then you have to call "startScript()", that basically sets up all the arrays and stuff.
To read a script is very easy.
sciprtNum = readScript(file$)
You call "readScript()", the parameter for this is the file name you want to read. It returns the script number. Since this can support multiple scripts, it will return the
number of the script. You refer to the script you want to get data from by using that variable.
Without giving a long boring explanation, here are the usefull functions there are:
- startScript() - Call once at the start of your project
- readScript(file$) - Returns the script number. Enter the filename you want to read.
- getCommandCount(script) - Returns the number of commands in a file. Enter the script number as a parameter.
- checkCommandCount(script,command$) - Returns the number of commands in a script that matches command$
- checkCommand(script, command number, command$) - Will check is a certain command is what you passed in (not case sensitive)
- getCommandLine(script, command) - Gets the whole command (including parameters and data)
- getCommand(script, command) - Returns just the command
- getCommandReturn(script, command) - Look above to see what the command return is.
- checkCommandReturn(script, ret$) - Will return the command number that returns the ret$ variable.
- getParameterCount(script, command) - Returns how many parameters a command has.
- getParameterType(script, command, parameter num) - Returns 2 if it's a string, otherwise returns 1.
- getParameter(script, command, parameter num) - Returns the value of a paramater, this will always be a string, even if in the script it's a number. Using val() you an get a
number.
- getCommandDataCount(script, command) - Returns how many data things there are in a command.
- getCommandData(script, command, data$) - Returns the value that somes after the = sign in a data statement. I.e. name="Zotoaster", if yu search for "name" it will return
"Zotoaster".
- getCommandDataNum(script, command, number) - Returns the command data, but this is called by number.
There's more, I have to first explain how the variables work on this
Variables - Not quite what you think
Variables in this are not like in DBPro, and there's no maths parser, so you can't use them exactly the same way.
Variables are actually just the data statements, but can be called by other data statements too.
For example, I declare the screen width and height:
screen(){
width = 1024,
height = 768,
}scr;
You first need a return value. You can then refer to the screen width and height in other command data, for example, to draw a line across the screen,
line(){
x1 = 0,
y1 = 0,
x2 = scr.width,
y2 = scr.height,
};
Do you see how that works? It's the return, a dot, and then the data you wish to use.
More Commands
- getVariable(script, var$) - Just like command data, but you need the return, and the dot. So this will scan all commands.
- getVariableCount(script) - Returns the amount all command data in the whole script
- getVariableNum(script, num) - Return the numbered variable - not very useful I must say
- getVariableVal(script, num) - Just like the above, but returns the actual value - still not too useful.
These commands are very pointless in DBPro, but I made them to make it easier to program the variables into the system. I don't see much use for these.
There are also other commands, but they aren't really needed.
Syntax
The way you can code in this is very flexible, and each command can be spead over as many lines as you like, so long as you have the semi-color at the end, then it's fine.
This is an example of making a box for example.
makeObjectBox(1,100,350,0.01)
{
red = 0,
green = 128,
blue = 250,
};
You could also do it like this:
makeObjectBox(1,100,350,0.01){red = 0,green = 128,blue = 250,};
Or like this:
makeObjectBox(
1,
100,
350,
0.01
)
{
red = 0,
green = 128,
blue = 250,
};
As I said, it's very flexible.
One thing that you can't miss out is remarks
Since this looks already very C#/C++-ish, I just made it so you can do remarks using two forward-slashes //Hello.
Examples
Here's a good example of a simple level I was making for my new game, 'Bad-Ball'.
//Level 1 - Test
setLevel("Test"){
grav = -1.3,
nograv = 0,
density = 0.02,
fog = 0,
backdrop = sky-blue,
draw = 12000,
ambience = 20,
};
light(0,1000,0,3000){
red = 0,
green = 255,
blue = 0,
};
create("Media\Levels\AST_01.x",0,1300,1000,0,0,0,500,500,500){
texture = "Media\Levels\AST_01.bmp",
};
create(cube,0,0,0,0,0,0,10000,10,10000){
red = 255,
green = 255,
blue = 255,
};
create(cone,0,300,0,0,45,0,3395,600,3395){
red = 128,
green = 128,
blue = 255,
};
create(sphere,0,0,0,0,0,0,-10000,-10000,-10000){
red = 0,
green = 128,
blue = 250,
};
create(cube,-55,400,55,0,45,0,50,800,3395){
red = 128,
green = 128,
blue = 255,
};
create(cube,55,400,-55,0,45,0,50,800,3395){
red = 128,
green = 128,
blue = 255,
};
create(sphere,0,400,1200,0,0,0,300,800,300){
red = 255,
green = 255,
blue = 0,
};
create(sphere,0,400,-1200,0,0,0,300,800,300){
red = 0,
green = 255,
blue = 0,
};
create(sphere,-1200,400,0,0,0,0,300,800,300){
red = 0,
green = 0,
blue = 255,
};
create(sphere,1200,400,0,0,0,0,300,800,300){
red = 255,
green = 0,
blue = 255,
};
The way to actually parse that is easy, I started by looping through all the commands, checking for a command, if found, get it's parameters and data, e.g.
for c=1 to getCommandCount(level1)
if checkCommand(level1,c,"create")
objtype$ = getParameter(level1,c,1)
posx = val(getParameter(level1,c,2))
etc...
endif
next c
It's relativelly simple to use.
Notes
Yep. It may sound like learning another language, but it would be your own language after all. I not dont have hundreds of commands for one level anymore, and to add another
level doesn't require any more commands in DBPro, and they are easy to change. I also use it to set sync rates, screen dimentions, and it keeps my project organised.
Here are the updates functions:
`Functions - Script
type zsScriptData
long as string
slong as string
endtype
function startScript()
dim zsScript(0) as zsScriptData
endfunction
function readScript(script$)
array insert at bottom zsScript() : num=array count(zsScript())
lines=getFileLines(script$)
open to read 1,script$
for l=1 to lines
read string 1,temp$
if left$(removeChar(temp$," "),2)="//" then temp$=""
if removeChar(temp$," ")<>"//"
zsScript(num).slong=zsScript(num).slong+temp$
endif
next l
close file 1
endfunction num
function checkCommandCount(num,com$)
for c=1 to getCommandCount(num)
if checkCommand(num,com,com$)=1
inc count
endif
next c
endfunction count
function checkCommand(num,com,com$)
if lower$(com$)=lower$( left$(getCommand(num,com),len(getCommand(num,com))-2) ) then exitfunction 1
endfunction 0
function getCommandCount(num)
count=getTokens(zsScript(num).slong,";")
endfunction count
function getCommandLine(num,com)
comline$=getToken(zsScript(num).slong,";",com)
endfunction comline$
function getCommand(num,com)
tcomline$=getToken(zsScript(num).slong,";",com)
for t=1 to len(tcomline$)
temp$=mid$(tcomline$,t)
if temp$="{" then onB=1
if onB=0
comline$=comline$+temp$
endif
next t
for l=1 to len(comline$)
temp$=mid$(comline$,l)
if temp$="(" or temp$=")" then oB=1-oB
if oB=0
command$=command$+temp$
endif
next l
new$=left$(command$,len(command$)-1)+"()"
endfunction new$
function getCommandReturn(num,com)
comline$=getCommandLine(num,com)
for c=1 to len(comline$)
cur$=mid$(comline$,c)
if cur$=chr$(34) then onC=1-onC
if onC=0
com$=com$+cur$
endif
next c
for c=1 to len(com$)
cur$=mid$(com$,c)
if cur$="}" then onB=1
if onB=1 then ret$=ret$+cur$
next c
ret$=removeChar(ret$,"}")
endfunction ret$
function checkCommandReturn(num,ret$)
for c=1 to getCommandCount(num)
if getCommandReturn(num,c)=ret$ then retn=c
next c
endfunction retn
function getParameters(num,com)
tcomline$=getToken(zsScript(num).slong,";",com)
for t=1 to len(tcomline$)
temp$=mid$(tcomline$,t)
if temp$=")" then endAdd=1
if endAdd=0
comline$=comline$+temp$
endif
next t
comline$=comline$+chr$(34)
command$=getCommand(num,com)
comlen=len(command$)
wholelen=len(comline$)
for a=comlen to wholelen-1
temp$=mid$(comline$,a)
param$=param$+temp$
next a
endfunction param$
function getParameterCount(num,com)
param$=getParameters(num,com)
plen=len(param$)
for p=1 to plen
temp$=mid$(param$,p)
if temp$=chr$(34) then oC=1-oC
if oC=1
if temp$<>"," then npar$=npar$+temp$
else
npar$=npar$+temp$
endif
next p
count=getTokens(npar$,",")
endfunction count
function getParameterType(num,com,par)
param$=getParameters(num,com)
plen=len(param$)
for p=1 to plen
temp$=mid$(param$,p)
if temp$=chr$(34) then oC=1-oC
if oC=1
if temp$<>"," then npar$=npar$+temp$
else
npar$=npar$+temp$
endif
next p
parc$=getToken(npar$,",",par)
if right$(parc$,1)=chr$(34) and left$(parc$,1)=chr$(34)
exitfunction 2
endif
endfunction 1
function getParameter(num,com,par)
par$=getParameters(num,com)
plen=len(par$)
for p=1 to plen
temp$=mid$(par$,p)
if temp$=chr$(34) then oC=1-oC
if oC=1
if temp$<>","
npar$=npar$+temp$
else
npar$=npar$+chr$(1)
endif
else
npar$=npar$+temp$
endif
next p
new$=getToken(npar$,",",par)
for n=1 to len(new$)
temp$=mid$(new$,n)
if temp$=chr$(1)
apar$=apar$+","
else
apar$=apar$+temp$
endif
next n
napar$=removeChar(apar$,chr$(34))
for v=1 to getVariableCount(num)
if getVariableNum(num,v)=napar$
napar$=getVariableVal(num,v)
endif
next v
endfunction napar$
function getAllCommandData(num,com)
tcomline$=getToken(zsScript(num).slong,";",com)
for t=1 to len(tcomline$)
temp$=mid$(tcomline$,t)
if temp$=chr$(34) then onC=1-onC
if temp$=")" and onC=0
getDat=1
endif
if getDat=1
tdat$=tdat$+temp$
endif
next t
for t=1 to len(tdat$)
cur$=mid$(tdat$,t)
if cur$="}" then stop=1
if stop=0 then ntdat$=ntdat$+cur$
next t
ndat$=right$(ntdat$,len(ntdat$)-1)
dat$=strSect(ndat$,2,len(ndat$))
endfunction dat$
function getCommandDataCount(num,com)
dat$=getAllCommandData(num,com)
dlen=len(dat$)
for p=1 to dlen
temp$=mid$(dat$,p)
if temp$=chr$(34) then oC=1-oC
if oC=1
if temp$<>"," then ndat$=ndat$+temp$
else
ndat$=ndat$+temp$
endif
next p
count=getTokens(ndat$,",")
endfunction count
function getCommandData(num,com,data$)
aldat$=getAllCommandData(num,com)
for d=1 to len(aldat$)
cur$=mid$(aldat$,d)
if cur$="=" then onEq=1
if cur$="," then onEq=0
if onEq=0
dat$=dat$+cur$
endif
next d
dat$=removeChar(dat$," ")
for d=1 to len(aldat$)
cur$=mid$(aldat$,d)
if cur$="=" then onEq=1
if cur$="," then onEq=0
if onEq=1
comp$=comp$+cur$
endif
next d
comp$=right$(comp$,len(comp$)-1)+"="
for t=1 to getTokens(dat$,",")
if getToken(dat$,",",t)=data$ then curTok=t
next t
tok$=removeChar(getToken(comp$,"=",curTok),chr$(34))
for v=1 to getVariableCount(num)
if getVariableNum(num,v)=removeChar(tok$," ")
tok$=getVariableVal(num,v)
endif
next v
endfunction tok$
function getCommandDataNum(num,com,dat)
comline$=getCommandLine(num,com)
for c=1 to len(comline$)
cur$=mid$(comline$,c)
if cur$="{" or cur$="}" then onB=1-onB
if onB=1
full$=full$+cur$
endif
next c
full$=removeChar(full$,"{")
full$=removeChar(full$,"}")
dat$=getToken(full$,",",dat)
endfunction dat$
function getVariable(num,var$)
com=checkCommandReturn(num,getToken(var$,".",1))
ret$=getCommandData(num,com,getToken(var$,".",2))
endfunction ret$
function getVariableCount(num)
for c=1 to getCommandCount(num)
if getCommandReturn(num,c)<>""
inc count,getCommandDataCount(num,c)
endif
next c
endfunction count
function getVariableNum(num,var)
for c=1 to getCommandCount(num)
if getCommandReturn(num,c)<>""
for d=1 to getCommandDataCount(num,c)
inc count
if count=var
ret$=getCommandReturn(num,c)+"."+removeChar(getToken(getCommandDataNum(num,c,var),"=",1)," ")
endif
next d
endif
next c
endfunction ret$
function getVariableVal(num,var)
for c=1 to getCommandCount(num)
if getCommandReturn(num,c)<>""
for d=1 to getCommandDataCount(num,c)
inc count
if count=var
ret$=removeChar(removeChar(getToken(getCommandDataNum(num,c,var),"=",2)," "),chr$(34))
endif
next d
endif
next c
endfunction ret$
`Functions - String
function getTokens(st$,sp$)
if left$(st$,1)<>sp$ then nst$=sp$+st$
if right$(st$,1)<>sp$ then nst$=nst$+sp$
for counter=1 to len(st$)
cur$=mid$(nst$,counter)
if cur$=sp$ then inc tokens
next counter
endfunction tokens
function getToken(st$,sp$,num)
if left$(st$,1)<>sp$ then nst$=sp$+st$
if right$(st$,1)<>sp$ then nst$=nst$+sp$
for nc=1 to len(st$)
inc counter
cur$=mid$(nst$,counter)
if cur$=sp$ then inc splits
if splits=num then exit
next nc
for nc=1 to len(st$)
inc counter
cur$=mid$(nst$,counter)
if cur$<>sp$ then token$=token$+cur$ else exit
next nc
endfunction token$
function removeChar(st$,ch$)
for l=1 to len(st$)
cur$=mid$(st$,l)
if cur$<>ch$ then mes$=mes$+cur$
next l
endfunction mes$
function strSect(st$,a,b)
for l=a to b
temp$=mid$(st$,l)
sect$=sect$+temp$
next l
endfunction sect$
function linSearch(st$,sch$,cnt)
for p=1 to len(st$)
if strSect(st$,p,p+len(sch$))=sch$ then inc count
if count=cnt then pos=p
next p
endfunction pos
function removeSpaces(ent$)
if left$(ent$,1)=" "
for i=1 to len(ent$)
if mid$(ent$,i)=" "
inc spaces
else
i=999
endif
next i
for i=spaces+1 to len(ent$)
ret$=ret_$+mid$(ent$,i)
next i
endif
endfunction ret$
function isLetter(text$)
if asc(text$)>=asc("a") and asc(text$)<=asc("z") then alpha=1
if asc(text$)>=asc("A") and asc(text$)<=asc("Z") then alpha=1
endfunction alpha
function isNum(text$)
if asc(text$)>=asc("0") and asc(text$)<=asc("9") then num=1
endfunction num
function isLetNum(text$)
if isLetter(text$) and isNum(text$) then isLetNum=1
endfunction isLetNum
`Functions - File
function getFileLines(file$)
local lines as integer
open to read 1,file$
repeat
read string 1,null$
inc lines
until file end(1)
close file 1
endfunction lines
You will see all the string and file functions underneath. The system relies on these, so they have to be here. You can use them too if you like
Happy coding