(http://underwaredesign.com/PlayBasicSig.png)
PlayBASIC V1.64K (Work In Progress) Gallery (October 19, 2009)
This thread documents the changes being made for the PlayBASIC 1.64 revision K.
For newer upgrade work in progress see,
See [plink]PlayBASIC V1.64P (http://www.underwaredesign.com/forums/index.php?topic=4089.0)[/plink] - Convert PlayBASIC To Machine Code Dll's (http://www.underwaredesign.com/?l=PlayBASIC-To-DLL-Development-Blog)
See [plink]PlayBASIC V1.64O (http://www.underwaredesign.com/forums/index.php?topic=3988.0)[/plink] (9th,Aug,2013)
See PlayBASIC V1.64N2/N3 (http://www.underwaredesign.com/forums/index.php?topic=3833.0)
See PlayBASIC V1.64N (http://www.underwaredesign.com/forums/index.php?topic=3651.0)
See PlayBASIC V1.64M (http://www.underwaredesign.com/forums/index.php?topic=3440.0)
See PlayBASIC V1.64L Learning Edition History (http://www.underwaredesign.com/forums/index.php?topic=3405.0) (Building learning Edition Thread)
See PlayBASIC V1.64L (http://www.underwaredesign.com/forums/index.php?topic=3364.0)
PlayBasic V1.64k WIP Gallery This thread will document the changes being made to the PlayBasic 1.64K upgrade...
Math Short Cuts The compiler/parser now supports various C styled math short cuts in assignments. Including ++, -- , +=, -=, *=, /=
[pbcode]
Dim Table(2000)
Table(110)+=1000
Table(110)-=2222
print Table(110)
Dim Table#(1000)
Table#(10)=1000
Table#(10)/=50
print Table#(10)
Dim Table$(200)
Table$(10)="Yeah"
Table$(10)+="Dude"
print Table$(10)
a$="Cool"
print a$
c$="DUDEDDD"
b$="YESAH"
A$=C$+b$
print a$
a$++
print a$
Type Test
Aaa
X
Y#
z$
EndType
Dim Dude as test
Dude.x +=100
Dude.x +=100
Dude.x +=100
Print Dude.x
Dude.y +=200
Dude.y +=200
Print Dude.y
Dude.z +="aaa"
Dude.z +="bbb"
Print Dude.z
Dim Qrr(10,5) as test
print "Typed Array"
Qrr(10,5).x =45
Qrr(10,5).x +=100
Qrr(10,5).x +=100
Qrr(10,5).x +=100
Print Qrr(10,5).x
Sync
waitkey
[/pbcode]
Extended the Math short cuts so they can be applied to Typed Arrays/Variables and Pointer Writes
[pbcode]
Type Test
Aaa
X
Y#
z$
EndType
Dim Dude as test
Dude.x +=100
Dude.x +=100
Dude.x +=100
Print Dude.x
Dude.y +=200
Dude.y +=200
Print Dude.y
Dude.z +="aaa"
Dude.z +="bbb"
Print Dude.z
Dim Qrr(10,5) as test
print "Typed Array"
Qrr(10,5).x =45
Qrr(10,5).x +=100
Qrr(10,5).x +=100
Qrr(10,5).x +=100
Print Qrr(10,5).x
Dim You2 as integer pointer
Dim You as integer pointer
Bank=NewBank(1000)
addr=GetBankPtr(Bank)
You= addr
*You = 45
*You += 100
*You *=2
*You /=10
print *You
Dim Me as test pointer
Me = new test
me.x =13
print me.x
me.x *=4
print me.x
me.x /=13
print me.x
print "Y test"
me.y +=22
print me.y
me.y *=4
print me.y
me.y /=13
print me.y
me.z +="HellO"
me.z +="HellO"
me.z +="HellO"
print me.z
Sync
waitkey
[/pbcode]
I should point out that shorts cuts are to help simplify user code, your unlikely to gain any runtime performance over the equivalent long hand syntax.
Bench mark(Requires PB1.64K)
[pbcode]
Dim Table(1000)
Max=10000
BumpValue=10
Do
Cls 0
frames++
T=timer()
Table(pos)=0
for lp=1 to max
Table(pos)=Table(pos)+BumpValue
next
tt1#+=(Timer()-t)
print Table(pos)
print "long Hand:"+str$(TT1#/frames)
T=timer()
Table(pos)=0
for lp=1 to max
// use the +=
Table(pos)+=BumpValue
next
tt2#+=(Timer()-t)
print Table(pos)
print "Short Cut:"+str$(TT2#/frames)
pos =mod(pos+1,1000)
Sync
loop
[/pbcode]
Both loops run at identical speeds.
THANK YOU! This will really help shorten code lines!
PlayBasic V1.64k - Byte + Word Fields in Types
I've moved onto adding support from some more field types in UDT structures. Starting with BYTE and WORD data types. While internally PB has no concept of anything as small as a byte or word, supporting byte & word fields in UDTs will let us communicate better with 3rd party structures. Which can be handy when calling windows functions or your own dll's perhaps. You could of course use them in your programs, but the PB runtime is optimized for 32bit integers. So it's often best to keep things as integers or floats, rather than mixing the datatypes.
Sample
[pbcode]
Type TestType
a as integer
b as float
c as byte
d as byte
EndType
DIm me as TestType
me.a =12345678
me.b =123.456
me.c= $aa
me.d =$bb
print me.a
print me.b
print hex$(me.c)
print hex$(me.d)
print Sizeof(TestType)
sync
waitkey
[/pbcode]
Outputs
12345678
123.456
$000000AA
$000000BB
10
PlayBasic V1.64k Beta 5 - Math Short Cuts Cont.
While the new math operation shorts cut can used on the majority of the datatypes/structures in PB, there's still a few structures that they couldn't be applied to. Namely array fields in user defined type structures. However this ommission has been implemented in the BETA 5 of V1.64k.
Accessing array fields requires PB to resolve multiple levels to actually get to the element you require, as such, these are the slowest types of data to access. However math short cuts and certainly help improve the performance of operations between them.
[pbcode]
Type TestType
a as integer
b as float
c as byte
z as word
d as byte
Stuff(100)
Stuff2#(100)
yeah$
EndType
Dim me(100) as TestType
Max=10000
BumpValue=1
Do
Cls 0
frames++
T=timer()
Me(50).stuff(pos)=0.0
for lp=1 to max
Me(50).stuff(pos)=me(50).stuff(pos)+BumpValue
next
tt1#+=(Timer()-t)
print Me(50).stuff(pos)
print "long Hand:"+str$(TT1#/frames)
T=timer()
Me(50).stuff(pos)=0
for lp=1 to max
// use the +=
Me(50).stuff(pos)+=BumpValue
next
tt2#+=(Timer()-t)
print Me(50).stuff(pos)
print "Short Cut:"+str$(TT2#/frames)
pos =mod(pos+1,100)
Sync
loop
[/pbcode]
In this example we're adding a value to a nested integer array. This time using the new += operator gives up about as %30 speed boost over the long hand version.
PlayBASIC V1.64k Beta 5b - Bit wise operator Math Short Cuts.
Added support for bit AND (&=), OR(|=) and XOR(~=) as short cuts, as well as fixing a few casting issues short cuts in the previous beta.
[pbcode]
a=$aabb
a&=$ff
print hex$(a)
Dim Test(1)
Test(1)= $aabbccdd
Test(1)&=$ff0000ff
print hex$(Test(1))
Sync
waitkey
[/pbcode]
PlayBASIC V1.64k Beta 5b - Cont.
This is just some test/bench code to see if there's any extra operations (casts) creeping into math shorts operations upon variables, when they're not the same data type.. But thankfully there's not now. If there was, there'd be a performance penalty for using the short cut in this case..
[pbcode]
Max=10000
BumpValue#=10
Do
Cls 0
frames++
T=timer()
IntVar=0
for lp=1 to max
IntVar=IntVar+BumpValue#
next
tt1#+=(Timer()-t)
print IntVar
print "long Hand:"+str$(TT1#/frames)
T=timer()
IntVar=0
for lp=1 to max
IntVar+=BumpValue#
next
tt2#+=(Timer()-t)
print IntVar
print "Short Cut:"+str$(TT2#/frames)
Sync
loop
[/pbcode]
PlayBASIC V1.64k Beta 6 - Cont.
If you're read the blog in the maintenance area you'll have no doubt noticed that i wanted to make a few more tweaks to VM1's performance, namely with how some the low level opcodes we're set up.. So this afternoon i've been going through the rather laborious process of restructuring how the VM executes the pointer and stack opcodes.
The results have been fairly pleasing, with approximately a 10% speed improvement on function calls and around a %40 speed improvement on writing into array fields.. More tweaks to come
[pbcode]
Type Stuff
a
b#
c$
Array(1000)
EndType
Dim me as stuff
Tests=10000
Do
cls 0
inc frames
print "Writing to Typed Fields Performance Test"
// ===================================
// USer Functions VS Projected Subroutines
// ===================================
// ==========
// Test #1
// ==========
T=timer()
For LP=0 to Tests
me.a=255
next
tt1#=tt1#+(timer()-t)
Print "Write Integer Average Time:"+Str$(tt1#/frames)
T=timer()
For LP=0 to Tests
me.b=255
next
tt2#=tt2#+(timer()-t)
Print "Write Float Average Time:"+Str$(tt2#/frames)
T=timer()
For LP=0 to Tests
me.c="255"
next
tt3#=tt3#+(timer()-t)
Print "Write String Average Time:"+Str$(tt3#/frames)
T=timer()
For LP=0 to Tests
me.array(10)=255
next
tt4#=tt4#+(timer()-t)
Print "Integer Array Average Time:"+Str$(tt4#/frames)
Sync
loop
[/pbcode]
I'm pleased with this. : )
Maybe you can add multi-dimensional support to arrays in types?
Multi dimensional array fields are a possibility, and It's something that'd id like to add at some point.. The problem now is, that this type addressing comes with a lot more runtime overhead.. The more dimensions you have, that more work it requires to locate the field being addressed.
For Example.
[pbcode]
Type Stuff
x,y,z
SomeArray(20,40)
SomeOtherArray(20,40)
EndType
Dim Obejcts(100) as stuff
Objects(50) = new stuff
Objects(50).SomeArray(10,5) = 45
Objects(50).SomeOtherArray(10) = 12
[/pbcode]
To actually read/write into this a field, we've first got to locate the structure first within the object array (ie mult and peek it out), then work the filed offset within this structure. To get the field offset (the element within the array) we multiply the first (or second field) by what the number of elements is, then add the other field..
FieldOffset = (FirstDim * 41) + SecondDim
So to access one field there's possibly as many of 5/6 (low and high level) opcodes that need to pass through the VM. So the cost operating upon such fields would be rather high.
Often it's best to export a pointer from the sub field and write directly into that parent structure yourself, which removes the need for the parent to be constantly dereferenced. Which pretty much emulates what the With / EndWith statement pairs do in Visual Basic for example.
The best solution really is to make the embedded array a reference. But the way the current parser works, this isn't really practical in PB atm. What this would mean is that you could have fields that allow to attach arrays (dynamically sized) to them.. These could then be passing into handler functions that can receive this data type.. So rather and access the nested fields through the parent constantly, you could dim the array, then pass it to a handler.
NOTE: This is CONCEPT ONLY sample code...
Type Stuff
x,y,z
SomeArray()
SomeOtherArray()
EndType
Dim Obejcts(100) as stuff
Objects(50) = new stuff
Dim Objects(50).SomeArray(20,40) // alloc this field and set it up as a 2d array
Dim Objects(50).SomeOtherArray(105) // alloc this field and set it up as a 1d array
Fill1DArray(Object(50).SomeOtherArray(),666)
Function Fill1DArray(Me(),Value)
for lp=0 to getarrayelements(me(),1)
me(lp)=Value
next
EndFunction
Due to how arrays work in VM1 (PB runtime), adding this type of functionality PB isn't so easy. However, such functionality is supported in the VM2 runtime ( PBFX) , which is designed to allow such controls and more.
Well, Alright. I understand. And it's not terribly hard to find array indices for a 1D array, so multi-dimensional arrays aren't really needed. I didn't know how much work would be put into adding them.
Is there a possibility of making classes in PB, like C++ does? The only reason I ask is because sometimes I'd like functions not to be global, but rather inside of an object, preferably a type.
[pbcode]
constant NORTH = 1
constant EAST = 2
constant SOUTH = 3
constant WEST = 4
type t_player
x#
y#
Function Move(dir)
...
Endfunction
endtype
Dim Player as t_player
Player.Move(WEST)
[/pbcode]
QuoteIs there a possibility of making classes in PB, like C++ does?
Yes & No. Eventually some limited
Object Orientation will appear, but this is really isn't practical in PB today. Comparably, implementing OO support makes multi dimensional arrays look like a cake wake. So it's not something you can just drop in quickly here.
Alrighty. But that's nice that OO support is going to be supported. I mean, I write code in such a way that it presents itself in an OO manner, but it's not the same as some other languages out there. Usually I make types and Dimension them right after, and then in a separate tab create the functions or "events" that the object uses.
PlayBASIC V1.64k Beta 7 - Stacks opt's = Better recursion speed.
Been working on the stack controls the past couple of days, made a few improvements in previous beta's, which turned out to be hindrances also, but ya get that ! - The stack is really a hidden bottle neck in how various parts of PB runtime (VM1) perform. So improving the stack functionality can make the overall runtime performance that little bit snappier. Which means your programs can run faster.
The current changes have been mostly relating to how a change of scope occurs (function calling). The old version is very polite and includes a wealth of error trapping and type matching that isn't always needed (however, some times it is!) - So, what I've been doing is restructuring the call function stack usage , to remove as much of nanny code as possible.
It's taken a lot longer than i'd originally expected to get working, but finally the scope change caller is yielding almost universally better results. For a simple function calls (small functions) it's only slightly faster though. In fact, BEta 7 is slower than previous betas in this regard. However, previous beta's relies upon a few too many assumptions, in others words, they don't actually work correctly :)
Beta 7 is quicker than previous PBV1.64j retail editions and thats what matters, but only marginally (by a couple of %), where it starts to shine is in calling larger scopes (big fat functions with lots of locals) and in particular recursive function calls.
In the example bellow we have a parent/child structure that's designed to use recursion. V1.64k Beta 7 runs this example approximately %30 faster then V1.64J Retail. Which is nothing to sneeze at..
[pbcode]
Constant MaxChildren=255
Type tObjectParent
x#,y#
TranslatedX#,TranslatedY#
Angle#
ScaleX#
ScaleY#
Colour
Size
Parent
ChildCount ; max kids
Children(MaxChildren) // This obejct can have a 255 children attached to it
EndType
Type tObjectChild as TobjectParent
Endtype
// This array holds the entire data structure of parents and their children
Dim Ball(0) as tobjectParent
TestParent=CreateParent(100,200,45)
// Append Child to the parent
Child2=AddChildToParent(testParent,100,100,00)
// append a bunch of kids to the Child
Kids=50
Dim Children(Kids)
for lp=1 to Kids
angle#=(360.0/Kids)*lp
x#=cos(angle#)*150
y#=sin(angle#)*150
Children(lp)=AddChildToParent(Child2,x#,y#,0)
next
; setfps 100
Do
cls $204080
TurnObject(TestParent,2.25)
PositionObject(TestParent,mousex(),mousey())
sangle#=wrapangle(sangle#,1)
s#=2+cos(sangle#)*1
s#=1
ScaleObject(Child2,s#,s#)
// loop through and process all the parent objects
lockbuffer
t=timer()
for lp=1 to GetArrayElements(Ball(),1)
if TypeOf(Ball(lp))=tObjectParent
// process a parent object
ParentX#=Ball(lp).x#
ParentY#=Ball(lp).y#
Angle# =Ball(lp).angle#
ScaleX# =Ball(lp).scalex#
ScaleY# =Ball(lp).scaley#
circlec parentx#,parenty#,Ball(lp).size,true,Ball(lp).colour
// DRaw it's kids
DrawChildren(lp,ParentX#,ParentY#,angle#,scaleX#,scaleY#)
endif
next
tt#=tt#+(Timer()-t)
unlockbuffer
inc frames
print tt#/frames
Sync
loop
Function CreateParent(X#,y#,angle#)
Index=GetFreeCell(Ball())
Ball(index).x#=x#
Ball(index).y#=y#
Ball(index).ScaleX# =1
Ball(index).ScaleY# =1
Ball(index).Angle#=angle#
Ball(index).size =20
Ball(index).colour =$ff0000
EndFunction Index
Function TurnObject(Index,AngleStep#)
Ball(index).angle#=wrapangle(Ball(index).angle#,AngleStep#)
EndFunction Index
Function ScaleObject(Index,ScaleX#,scaley#)
Ball(index).ScaleX# =ScaleX#
Ball(Index).ScaleY# =ScaleX#
EndFunction
Function PositionObject(Index,X#,y#)
Ball(index).x#=x#
Ball(index).y#=y#
EndFunction Index
Function AddChildToParent(ParentIndex,X#,y#,angle#)
ChildIndexInParent=FindFreeChildInPArent(ParentIndex)
if ChildIndexInParent
ChildIndex=GetFreeCell(Ball())
Ball(Parentindex).ChildCount=Ball(Parentindex).ChildCount+1
// store the index of this child in the parents local array
Ball(Parentindex).Children(ChildIndexInParent) =ChildIndex
// create the child. The child is local to the parent
Ball(childIndex) = new tObjectChild
Ball(Childindex).Parent =ParentIndex
Ball(Childindex).x# =x#
Ball(Childindex).y# =y#
Ball(Childindex).Angle# =angle#
Ball(Childindex).ScaleX# =1
Ball(Childindex).ScaleY# =1
Ball(Childindex).size = 10
Ball(Childindex).colour =255
endif
EndFunction ChildIndex
Function DrawChildren(ThisParent,ParentX#,ParentY#,Angle#,ScaleX#,ScaleY#)
ca#=Cos(angle#)
sa#=Sin(angle#)
for lp=1 to MaxChildren-1
ThisChild=Ball(ThisParent).Children(lp)
if ThisChild
Colour=Ball(ThisChild).Colour
Size =Ball(ThisChild).size
X#=Ball(ThisChild).x#*ScaleX#
Y#=Ball(ThisChild).y#*ScaleY#
rotatedX#=ParentX#+( (ca#*x#)-(sa#*y#))
rotatedY#=ParentY#+( (ca#*y#)+(sa#*x#))
Ball(ThisChild).TranslatedX#=RotatedX#
Ball(ThisChild).TranslatedY#=RotatedY#
circlec RotatedX#,RotatedY#,size,true,colour
endif
next
// draw children
if Ball(ThisParent).ChildCount
for lp=1 to MaxChildren-1
ThisChild=Ball(ThisParent).Children(lp)
if ThisChild
x# =Ball(ThisChild).TranslatedX#
y# =Ball(ThisChild).TranslatedY#
DrawChildren(ThisChild,X#,Y#,wrapangle(Ball(ThisChild).Angle#,Angle#),Ball(ThisChild).ScaleX#,Ball(ThisChild).ScaleY#)
endif
next
endif
EndFunction
function LocateAbsoluteParentOffset(ThisChild)
repeat
parent =Ball(ThisChild).Parent
x#=x#+Ball(ThisChild).x#
y#=y#+Ball(ThisChild).y#
until Parent=0
EndFunction x#,y#
Function FindFreeChildInPArent(ThisParent)
for lp=1 to MaxChildren
ChildIndex=Ball(ThisParent).Children(lp)
if ChildIndex=0
exitfunction lp
endif
next
EndFunction Index
[/pbcode]
PlayBASIC V1.64k Beta 8 - Mismatched Assignment Casting.
hadn't noticed this before, but PB doesn't seem to like assigning pointers to integer/float variables. From the parsers perspective this is perfectly legal, but the runtime doesn't actually feature the require opcodes. So in older version of PB you'll get a unknown opcode error. As such I've dropped in some support for this. Seems to work ok..
eg.
[pbcode]
; declare pointer (generic)
Dim a as pointer
; assign the Integer variable PTR the integer value of 5
ptr=5
// move integer to pointer
a = ptr
// move pointer to integer
i=a
print i
// Add pointer to integer
i+=a
print i
sync
waitkey
[/pbcode]
Edit: Should work on all the main structures now.
[pbcode]
// declare pointer (generic)
Dim a as pointer
// assign the Integer variable PTR the integer value of 5
ptr=5
// move integer to pointer
a = ptr
// move pointer to integer
i=a
print i
// Add pointer to integer
i+=a
print i
Dim Stuff(100)
Dim Stuff#(100)
Stuff(1) +=a
Stuff(1) +=a
Stuff(1) +=a
print Stuff(1)
Stuff#(1) +=a
print Stuff#(1)
Type SomeData
x,y,z
f#
endtype
Dim Y as SomeData
Dim W(10) as somedata
y.x +=a
y.f +=a
y.x +=a
y.f +=a
print "typed variable"
print y.x
print y.f
w(1).x =a
w(1).f =a
w(1).x *=a
w(1).f *=a
print "typed array"
print w(1).x
print w(1).f
sync
waitkey
[/pbcode]
PlayBASIC V1.64k Beta 9 - Array operators / Assignments.
Currently working my way through adding some more array functionality in the way of operators. So far this beta has some (limited) support for array handle assignments. In case you didn't know (if so, you might want to read the Helps->About tutorials at some point!), when we use handle in PB we're talking about about the entire array, be it a Integer array, Float array ,String array, Typed array or Typed variable . The container is basically the housing the around the elements inside the array structure. So these operations are not applied upon individual elements inside the array, but the entire arrays contents.
So far, all we can do is copy the right side to the left. Ie. DestArray() = SrcArray(), which at this point is really only a short cut for CopyArray command. I've a few other ideas that might be handy also, but it'll keep those under wraps for the time being.
Anyway, here's a example.
[pbcode]
// dim two 1d arrays
Dim Array(1)
Dim Array2(20)
// fill array2 with some random values
For lp=1 to 20
Array2(lp)=rnd(100)
next
// show the current state of both arrays
print "Arrays Before Assignment"
print ShowArray(Array())
print ShowArray(Array2())
// __COPY___ Array2 into Array()
Array() = Array2()
// show the current state of both arrays
print "Arrays After Assignment"
print ShowArray(Array())
print ShowArray(Array2())
// refresh display and wait for keypress
Sync
WaitKey
Function ShowArray(Me())
for lp=1 to getarrayelements(me(),1)
s$=s$+digits$(me(lp),3)+","
next
s$=trimright$(s$,",")
EndFunction s$
[/pbcode]
Outputs
Arrays Before Assignment
000
078,099,042,026,083,064,094,028,081,088,005,031,086,046,084,099,084,024,042,087
Arrays After Assignment
078,099,042,026,083,064,094,028,081,088,005,031,086,046,084,099,084,024,042,087
078,099,042,026,083,064,094,028,081,088,005,031,086,046,084,099,084,024,042,087
[plink]See developers blog for more on new features concerning arrays (http://www.underwaredesign.com/forums/index.php?topic=3627.75)[/plink]
PlayBASIC V1.64k Beta 10 - Returning UDT's from Functions.
Today I've been looking into the best way to insert such functionality into PlayBasic V1.64k. Implementing this today is basically about bridging the gaps, and trying not to leak memory in the process. While it's not currently working, I'm reasonably sure that VM1 includes enough control to wedge such an ability into it. Might not be most elegant solution internally, but it should work ok.
I should point out here, that we're talking about returning a single UDT pointer instance, not a container (array/list etc)..
[pbcode]
Type Vector2D
x#,y#
stuff(20000)
Endtype
Dim Cool as Vector2D
Cool = TestUDTFunction(4444,555)
print Cool.x#
print Cool.y#
Sync
WaitKey
Function TestUDTFunction(x#,y#)
LocalType = new Vector2D
LocalType.x#=x#
LocalType.y#=y#
print LocalType.x#
print LocalType.y#
print "This:"+STR$(Int(LocalType))
EndFunction LocalType as Vector2D
[/pbcode]
PlayBASIC V1.64k Beta 10b - Returning UDT's from Functions (Continued) .
It's been a pretty creative and productive couple of days code wise. Thus far, every thing seems to have come together to fairly well, which is surprising. It hasn't all gone to script with the odd WTF moment, but most things on my to do are getting ticked off fairly quickly this time, and i'm happy to say that Returning User Defined Types is now one of them.
Lets not get too far ahead ourselves though, currently you can only return a single new instance of TYPE from a FUNCTION (NOT a PSUB). This type is accessible through a UDT pointer inside the function, then exported as new type bank from the function. So what's returned from the function call is virtually the same as what the NEW operator returns. Which is the 'buffer' this type structure is stored within, and not an array/list container. Therefore PB will expect you to write this buffer handle into a container such as typed variable/array or list. If you don't, you'll leak this memory !
Now since the return type is a UDT pointer inside the function, we actually need to initialize this using the NEW operator. If you don't do this, it'll crash anytime you read/write to the field. I could possibly do this for you (init it as the types declared parent type), but then you'd lose some control, since types can be inherited in PB. So what you could is Dim the return type as the general parent, but actually allocate one of it's siblings. Which is perfectly legal.
Anyway, here's a bit of a working example..
[pbcode]
setfps 60
// declare our type structure
Type MyObject
x#,y#
radius
deathtime
colour
EndType
// declare & create our global LIST conatiner to hold all our ships
Dim Ship as MyObject list
// ==========================================
// main loop
// ==========================================
Do
Cls 0
lockbuffer
CurrentTime=Timer()
for each Ship()
if CurrentTime<Ship.DeathTime
circlec Ship.x#,Ship.y#,Ship.Radius,true,ship.colour
else
Ship=Null
endif
next
unlockbuffer
if Rnd(1000)>250
// add 5 to the list container
for lp=1 to 5
Ship= SpawnNewObject()
next
endif
Sync
loop
Function SpawnNewObject()
// NOTE!! - You MUST NEW the return type prior to reading or writing to it
This = New MyObject
This.x#=rnd#(getscreenwidth())
This.y#=rnd#(getscreenHeight())
This.Radius=rndrange(10,50)
This.Colour =rndrgb()
This.DeathTime=Timer()+rndrange(1000,2000)
EndFunction This as MyObject
[/pbcode]
PlayBASIC V1.64k Beta 11 - Improving 'As Datatype' support in function declarations.
I don't really see this as a feature, it's one of those additions that will make declarations a little more uniform with the outside world. Currently, I've only added 'As integer" trapping in EndFunction declarations (see example bellow). But will extend this to Floats and Strings also at least. It's here we start to run into some problems. PlayBASIC, like traditional BASIC languages is Multi instance. Where as the majority of modern languages (including most modern BASICs) are single instance.
What does this mean ? - Well it means that each keyword is unique and always associated with a particular object/data type regardless. In multi instances dialects, the same keyword can be used to represent various data types, the language differentiates between the instances by looking at the postfix symbols. So in PlayBASIC we can the have a variables (and even arrays) called XPOS, XPOS#, XPOS$ etc etc.
Now in most declarations in PB we can generally use the postfix shortcuts, Local/Static/Global/Declaration/EndDeclaration blocks ie Local A, B# (declares A an integer and B# as float)
The same applies to type declarations, for example you can create a pair of float fields in two ways..
#1 - Using post fix as short cuts
Type Vector2D
X#
y#
EndType
#2 or as data type method (long hand)
Type Vector2D
X as float
y as float
EndType
You'll notice that X & Y "as float" overrides the fields X & Y from integers (default) to become floats. Which is the same as if you use dim to declare a float long hand.
ie.
[pbcode]
Explicit on
Dim X as float
X# = 123.456
Print X#
Sync
Waitkey
[/pbcode]
However, just because the declaration doesn't use the postfix, that doesn't mean you can drop it during operations upon this variable. If you do, the parser with assume you mean the Integer instance. So If you're running in explicit mode, you'll get the a declaration error. Like so,
[pbcode]
Explicit on
Dim X as float
X = 123.456
Print X#
Sync
Waitkey
[/pbcode]
Notice the dropped # when accessing the X variable. Since no integer X has been previously declared this will pop a compile time error. This is the intended behavior !
The point i'm getting at here, is that this same behavior will occur in Function/EndFunction & Psub/EndPsub declarations.
Anyway, here's a sample of what's currently running..
[pbcode]
explicit on
Dim a as integer
Dim b as integer
a,b=Cool()
print a
print b
Sync
waitkey
Function Cool()
result=45.4
dude=666
EndFunction Result as integer,dude as integer
[/pbcode]
PlayBASIC V1.64k Beta 11 - Improving 'As Datatype' support in function declarations (continued).
The success of yesterdays initial session implementing such parser changes, was soon soured upon running into a rather awkward logical issue to resolve. In fact, it's taken most of the day to come up with something that even works.. grrrr
Anyway, so what this all means is that you can use the as datatype declarations in your Function/EndFunction headers. (They'll also work in Psub/EndPSub too) .
Here's today's (Thrilling :) )example...
[pbcode]
explicit on
Dim a as integer
Dim b as integer
Dim c as float
; a,b=Cool()
; print a
; print b
Dim MyPtr as pointer
a,c#=Cool_Floats(MyPtr)
print a
print c#
Sync
waitkey
Function Cool()
result=45.4
dude=666
EndFunction Result as integer,dude as integer
Psub Yeah()
EndPsub Testing as float
Function Cool_Floats(x as pointer)
result=45.4
dude#=int(666.4)
EndFunction Result as integer,dude as float
Function Cool_Floats2(X)
result=45.4
; dude#=666.66
EndFunction Result as integer,dude$ as string
Function Cool_Strings(X)
result=45.4
dude$="Yeah"
EndFunction dude$,Result as integer
[/code]
And here's some more test code with AS Datatype screen in FUNCTION/PSUB headers. Equally thrilling, but it's there if you want it..
[code]
explicit on
Dim a as integer
Dim b as integer
Dim c as float
; a,b=Cool()
; print a
; print b
Dim MyPtr as pointer
a,c#=Cool_Floats(MyPtr)
print a
print c#
Sync
waitkey
Function Cool()
result=45.4
dude=666
EndFunction Result as integer,dude as integer
Psub Yeah()
EndPsub Testing as float
Function Cool_Floats(x as pointer)
result=45.4
dude#=int(666.4)
EndFunction Result as integer,dude as float
Function Cool_Floats2(X)
result=45.4
; dude#=666.66
EndFunction Result as integer,dude$ as string
Function Cool_Strings_Input(InputString$ as string,SecondInputString as string)
result$="45.4"
dude$="Yeah"
EndFunction dude$,Result$ as string
Function Cool_Floats_Input(InputFloat# as float,AnotherInputFloat as float)
result$="45.4"
dude$="Yeah"
EndFunction dude$,Result$ as string
[/pbcode]
I like it. It's not really necessary, but you have to fill in all the holes if you intend to make a solid programming language, right?
I look forward to this new release, as it hardens the core of the code's syntax.
QuoteI like it. It's not really necessary
Well, that depends upon who you ask.
Quotebut you have to fill in all the holes if you intend to make a solid programming language, right?
Support for the optional "as datatype" syntax, is due to this convention becoming common place over the past years, so it makes sense to adopt such things into PlayBasic also. So there's
some universal similarities for people who come from a programming background.
QuoteI look forward to this new release, as it hardens the core of the code's syntax.
Rather than waiting for the finally upgrade to be released, you should be running the beta's as they're posted. Other wise the final, will be a beta!
PlayBASIC V1.64k Beta 12 - Passing Individual User Defined Types Into Functions .
With the addition of being able to return individual UDT's from functions, then it makes sense to add the ability to pass Individual User Defined Types into Functions also. This gives us two methods to move data between scopes. You have the original container methods and now you can pass individual type buffers.
To declare an input param as individual UDT we use the VARIABLE as UDT declaration. When you call this function, PB expects this field to be a UDT bank. The bank is then resolved to a pointer and pass through to the function internally. So the UDT variable inside the function is actually UDT pointer. So the local UDT has no container. You're writing directly into this type data. However, When you pass a Typed array/Typed variable in, your moving the entire array/list structure.
[pbcode]
Type SomeObject
x#,y#
name$
Endtype
Dim Cool as SomeObject
Cool = TestReturnUDTFromFunction(4444,555,"Bill")
print "------------------------------"
print "Show returned contents"
print "------------------------------"
print Cool.x#
print Cool.y#
print Cool
Test_Pass_UDT_To_Function(Cool)
Sync
WaitKey
Function TestReturnUDTFromFunction(x#,y#,name$)
LocalType = new SomeObject
LocalType.x#=x#
LocalType.y#=y#
LocalType.name=Name$
print "------------------------------"
print "Created Data"
print "------------------------------"
print LocalType.x#
print LocalType.y#
print LocalType.Name$
print "This:"+STR$(Int(LocalType))
EndFunction LocalType as SomeObject
Function Test_Pass_UDT_To_Function(LocalType as SomeObject)
// Manually chekc if this thing exists or not..
if int(LocalType)
; Yep so, display the fields
print "------------------------------"
print "passed UDT bank"
print "------------------------------"
print int(localType)
print LocalType.x#
print LocalType.y#
print LocalType.Name
endif
EndFunction
[/pbcode]
Here's a quick reworking of the previous example, this version features passing individual types in and out of user defined functions.
[pbcode]
setfps 60
// declare our type structure
Type MyObject
x#,y#
radius
deathtime
colour
EndType
// declare & create our global LIST container to hold all our ships
Dim Ship as MyObject list
// ==========================================
// main loop
// ==========================================
Do
Cls 0
lockbuffer
CurrentTime=Timer()
for each Ship()
if CurrentTime<Ship.DeathTime
DrawShip(ship)
else
Ship=Null
endif
next
unlockbuffer
if spacekey() ;Rnd(1000)>250
// add 5 to the list container
for lp=1 to 5
Ship= SpawnNewObject()
next
endif
print "Object count:"+Str$(getListSize(Ship()))
Sync
loop
Function DrawShip(ThisShip as MyObject)
circlec ThisShip.x#,ThisShip.y#,ThisShip.Radius,true,Thisship.colour
EndFunction
Function SpawnNewObject()
// NOTE!! - You MUST NEW the return type prior to reading or writing to it
This = New MyObject
This.x#=rnd(getscreenwidth())
This.y#=rnd(getscreenHeight())
This.Radius=rndrange(10,50)
This.Colour =rndrgb()
This.DeathTime=Timer()+rndrange(1000,2000)
EndFunction This as MyObject
[/pbcode]
Here a version that uses array handles/containers. This is functionally the same as the version above, expect one Key difference. The version above is passing the individual TYPEs in and OUT of the functions, so inside the SpawnNewObject/drawMe functions, we can only access stuff in this stucture, we can't acccess the list that came from.
However in the version bellow, we're passing the entire array (LIST) container. This allows us to perform operations upon the passed LIST inside the , rather than just upon the single passed instance.
[pbcode]
setfps 60
// declare our type structure
Type MyObject
x#,y#
radius
deathtime
colour
EndType
// declare & create our global LIST container to hold all our ships
Dim Ship as MyObject list
// ==========================================
// main loop
// ==========================================
Do
Cls 0
lockbuffer
CurrentTime=Timer()
for each Ship()
// pass the SHIP list into the function as well as the death time
UpdateAndDrawShip(Ship(),CurrentTime)
next
unlockbuffer
if spacekey() ;Rnd(1000)>250
// add 5 to the list container
for lp=1 to 5
// pass the Ship LIST into this function, so we can add stuff to it
SpawnNewObject(Ship())
next
endif
print "Object count:"+Str$(getListSize(Ship()))
Sync
loop
Function UpdateAndDrawShip(ThisShip.MyObject,CurrentTime)
if CurrentTime<ThisShip.DeathTime
circlec ThisShip.x#,ThisShip.y#,ThisShip.Radius,true,Thisship.colour
else
ThisShip=Null
endif
EndFunction
Function SpawnNewObject(This.MyObject)
This = New MyObject
This.x#=rnd(getscreenwidth())
This.y#=rnd(getscreenHeight())
This.Radius=rndrange(10,50)
This.Colour =rndrgb()
This.DeathTime=Timer()+rndrange(1000,2000)
EndFunction
[/pbcode]
PlayBASIC V1.64k Beta 12b - Returning Local Arrays from Functions (Maybe).
This afternoon I've been continuing my work on the Function Parser. Now that most of the big issues are resolved, it should be possible to export a locally created array (an array dimmed inside a function), and return and assign it to another array(). Those with a keen eye will no doubt see why I was messing around with Array() operators a few days back :) - Anyway, while it doesn't currently work, ideally this could mean that you can dynamically create arrays.
However, there's a catch (isn't there always), exported arrays will be returned as their underlying bank handles, these are use plain integer values. Since the return isn't strongly typed (for flexibility here), it's going to be possible for you to leak arrays if you're not careful.
Anyway, here's the current WIP snippet. So far this parses correctly, but doesn't generate the runtime code for the array exporting.
[pbcode]
Dim Table(0)
; Table() = MakeTable(Size)
print "Yep, i'm not dead"
Sync
waitkey
Function MakeTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray(Size)
EndFunction LocalArray() ; Export local array from function
[/pbcode]
PlayBASIC V1.64k Beta 12c - Returning Local Arrays from Functions (continued).
Well, we can tick off another feature. I thought this might take a little longer to get working, but it's really gone fairly seamlessly this time. The implementation isn't complete mind you (only currently supports return integer arrays) but the frame work is in now working. Hopefully, there's no hidden drama's awaiting the implementation of the other array types. But, anyway..
So here's a basic functionality example... Not too exciting, but it shows the concept.
[pbcode]
Dim Table(0)
// show the initial array state
print ConvertArrayToString(Table())
// Make and return a array 15 elements in size.. The returned array
// is written back into the Table() array. When you make and assignment
// like this, it first undims the data in the destination array, then
// stores the arrays bank in the dest.
Table()=MakeTable(15)
// show the initial array state
print ConvertArrayToString(Table())
// Make and return a array 25 elements in size.. The returned array
// is written back into the Table() array.
Table()=MakeTable(25)
print ConvertArrayToString(Table())
Sync
waitkey
Function MakeTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray(Size)
for lp =0 to size
LocalArray(lp)=rnd(50)
next
EndFunction LocalArray() ; Export local array from function
Function ConvertArrayToString(Me())
for lp=0 to getarrayelements(Me(),1)
s$=s$+digits$(me(lp),2)+","
next
s$=trimright$(S$,",")
EndFunction s$
[/pbcode]
Outputs..
00
19,14,06,19,44,17,35,47,49,47,48,19,33,22,33,01
07,45,45,46,39,22,29,20,33,46,01,45,06,46,37,06,00,46,05,50,49,40,31,40,00,03
Here's another example. This one is using a 1D array, to store 1D array handles in. So we're conceptually creating functionality to resembles the 'arrays within arrays'. To access the dynamically created arrays here we're using a manually declared redirection array via MakeArray. So before we can access any array handles within TABLE() we need to, copy the array bank into our redirect array. Once that's done, the array appears like any other.
[pbcode]
setfps 100
// ----------------------------------
// Conceptual Array of Arrays
// ----------------------------------
Dim Table(100)
// make a redirection array. We'll use this it access the 'array banks' stored
// with the TABLE() array. We need this in this example since, Table is just
// an integer array.
MakeArray ints()
EndTime=timer()+1000*10
do
Cls 0
if spacekey() or (rnd(100)>20) and (Timer()<EndTime)
Index=GetFreeCell(Table())
Table(Index)=MakeTable(rndRange(10,20))
; Flushkeys
endif
// press enter to randomly create an array and then store it's bank
// table() array. So we're making an 'lose' associate
if EnterKey()=true or (rnd(100)>10)
//
index=Rndrange(1,GetArrayElements(Table(),1))
if Table(Index)
ints()=Table(index)
Table(index) = 0 ;clear this handle from the array we used to remember them in
Ints()=0 ; free this array buffer
; Flushkeys
endif
endif
// Display the arrays
for Index=1 to getarrayelements(Table(),1)
if Table(Index)
ints()=Table(index)
print ConvertArrayToString(Ints())
endif
next
Sync
loop
Sync
waitkey
Function MakeTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray(Size)
// Fill it full of stuff
for lp =0 to size
LocalArray(lp)=rnd(50)
next
EndFunction LocalArray() ; Export local array from function
// Convert array to
Function ConvertArrayToString(Me())
for lp=0 to getarrayelements(Me(),1)
s$=s$+digits$(me(lp),2)+","
next
s$=trimright$(S$,",")
EndFunction s$
[/pbcode]
It now supports returning Integer/Float and String Arrays
[pbcode]
print "Integers -----------------------------------------------"
Dim Table(0)
// show the
print ConvertArrayToString(Table())
Table()=MakeIntegerTable(15)
print ConvertArrayToString(Table())
print "Floats -----------------------------------------------"
Dim Table#(0)
// show the
print ConvertArrayToStringF(Table#())
Table#()=MakeFloatTable(5)
print ConvertArrayToStringF(Table#())
print "Strings -----------------------------------------------"
Dim Table$(0)
// show the
print ConvertArrayToStringS(Table$())
Table$()=MakeStringTable(7)
print ConvertArrayToStringS(Table$())
Sync
waitkey
Function MakeIntegerTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray(Size)
for lp =0 to size
LocalArray(lp)=rnd(50)
next
EndFunction LocalArray() ; Export local array from function
Function ConvertArrayToString(Me())
for lp=0 to getarrayelements(Me(),1)
s$=s$+str$(me(lp))+","
next
s$=trimright$(S$,",")
EndFunction s$
Function MakeFloatTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray#(Size)
for lp =0 to size
LocalArray#(lp)=rnd#(50)
next
EndFunction LocalArray#() ; Export local array from function
Function ConvertArrayToStringF(Me#())
for lp=0 to getarrayelements(Me#(),1)
s$=s$+str$(me#(lp))+","
next
s$=trimright$(S$,",")
EndFunction s$
Function MakeStringTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray$(Size)
for lp =0 to size
LocalArray$(lp)="Text:"+Str$(rnd(50))
next
EndFunction LocalArray$() ; Export local array from function
Function ConvertArrayToStringS(Me$())
for lp=0 to getarrayelements(Me$(),1)
s$=s$+(me$(lp))+","
next
s$=trimright$(S$,",")
EndFunction s$
[/pbcode]
PlayBASIC V1.64k Beta 13 - Returning Typed Arrays & Lists from Functions.
Well well, this is getting a lot more interesting than just being able to return integer arrays dynamically. Now we can return locally created float/string/ typed arrays and even Typed lists from within functions also.
When an local array is exported it's exported as the databank that represents this item in memory. We can assign the bank indexes to a receiver array (MyArray() = SomeFunction() ), or we can store them in an integer fields (as per the example above).
If we do this, we can't access the data directly, we need to first create an array stub using MakeArray. Then any time we want to access the data, we assign the array stub our bank index and hey presto, we're able to read write to the array. It's not the prettiest solution, but it's something that works today!
Here's a simple example.
[pbcode]
Type Vector2D
x#,y#
EndType
print "[Pass Typed Array============================]"
Dim Dude(0) as vector2D
MakeVectorTable2(Dude(),200)
print "[Return Typed Array============================]"
Dim Dude2(0) as vector2D
Dude2().vector2d= MakeNewVectorTable(45)
print "[Return Link List==============================]"
Dim MyList as vector2D list
MyList()= MakeNewVectorList(10)
for each MyList()
s$=str$(mylist.x#) +", " +str$(mylist.y)
print s$
next
Sync
Waitkey
Function MakeNewVectorTable(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray(Size) as Vector2D
for lp =0 to size
LocalArray(lp).x=rnd(50)
LocalArray(lp).y=rnd(50)
next
EndFunction LocalArray().Vector2D ; Export local typed array from function
Function MakeNewVectorList(Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray as Vector2D list
for lp =0 to size
LocalArray = new Vector2D
LocalArray.x=rnd(50)
LocalArray.y=rnd(50)
next
EndFunction LocalArray.Vector2D ; Export local typed array from function
Function MakeVectorTable2(LocalArray().Vector2D,Size)
// Declare and create our local array. You'll need to DIM this manually
Dim LocalArray(size) as Vector2D
for lp =0 to size
LocalArray(lp).x=rnd(50)
LocalArray(lp).y=rnd(50)
next
EndFunction ; Export local typed array from function
[/pbcode]
Here's a much more practical example that uses attached typed lists to store character inventories in. So each character has it's own typed linked list attached. This can go as deep as you like really and gets rid of the ugly dereferencing issues mentioned earlier in this thread...
[pbcode]
; PROJECT : Inventory
; AUTHOR : Kevin Picone
; CREATED : 11/7/2009
; EDITED : 11/7/2009
; ---------------------------------------------------------------------
SetFps 60
type tInventory
itemname$
EndType
// Declare a game object called of SHIP
type tShip
x#,y#
speedx#,speedy#
radius
colour
InventoryArray
EndType
Dim Ship as tship list
// throw some ships randomly into the list so we're someting to look at
for lp =1 to 20
ship = new tship
ship.x=rndrange(100,700)
ship.y=rndrange(100,500)
angle#=rnd#(360)
ship.speedx=cos(angle#)
ship.speedy=sin(angle#)
ship.radius =rndrange(10,20)
ship.colour =rndrgb()
// Store the inventory arrays bank index, for later use
Ship.InventoryArray =CreateShipsInventory()
next
// This the items that characters can pick up.
type tItem
x#,y#
Starttime,DeathTime
Name$ ; name of the pick up item characters can pick up
BoundingBoxShape
endtype
Dim Item as tItem list
// create an array to hold the names of the inventory items that game character can pick up
Dim ItemNames$(0)
s$="Gold Bar, Silver Bar, Cricket Bat,20 cents,Commodore 64"
NumberOfItems=SplitToArray(s$,",",ItemNames$(),0)
; ---------------------------------------------------------
Do // game LOOP
; ---------------------------------------------------------
Cls 0
; ---------------------------------------------------------
; Show Items
; ---------------------------------------------------------
CurrentTime=timer()
if CurrentTime>SpawnNewItem
SpawnNewItem=CurrentTime+rndrange(50,250)
Item = new tItem
Item.x = Rnd(GetScreenWidth())
Item.y = Rnd(GetScreenHeight())
Item.StartTime=CurrentTime
Item.DeathTime=CurrentTime+2500
Item.name =ItemNames$(int(rnd#(NumberOfItems-1)))
width=gettextwidth(item.name)
height=gettextheight(item.name)
x1=-(Width/2)
x2=(Width/2)
y1=0
y2=(Height)
Item.BoundingBoxShape =NewBoundingBoxShape(x1,y1,x2,y2)
endif
for each Item()
timepast#=currenttime-item.StartTime
scaler#=(TimePast#/(item.DeathTime-item.StartTime))
Scaler#=1-cliprange#(scaler#,0,1)
ink rgbfade($ffffff, scaler#*100)
centertext item.x, item.y, Item.name
if CurrentTime>Item.DeathTime
item=Null
endif
next
ink $ffffff
; ---------------------------------------------------------
; Move Ships
; ---------------------------------------------------------
for each Ship()
x#=ship.x#+ship.speedx#
y#=ship.y#+ship.speedy#
if x#<10 then x#=10 : Ship.SpeedX*=-1
if x#>790 then x#=790 : Ship.SpeedX*=-1
if y#<10 then y#=10 : Ship.Speedy*=-1
if y#>590 then y#=590 : Ship.Speedy*=-1
ship.x=x#
ship.y=y#
; chekc if ship hit an inventory item
ShipHitItem(Ship())
circlec x#,y#,ship.radius,true,ship.colour
ShowShipInventory(ship())
next
Sync
loop
Function CreateShipsInventory()
Dim MyInventory as tInventory list
EndFunction MyInventory.tInventory
Function ShowShipInventory(ThisShip.tship)
Makearray Inventory.tInventory
Inventory() =ThisShip.InventoryArray
x#=thisShip.x#
y#=thisShip.y#
th=gettextheight("Y")
ink $ff0000
for each Inventory()
centertext x#,y#,Inventory.itemname
y#+=th
next
ink $ffffff
EndFunction
// Check if this ship hit any of the inventory items
Function ShipHitItem( ThisShip.tship)
Makearray Inventory.tInventory
x#=thisShip.x#
y#=thisShip.y#
radius#=thisShip.radius
// Seed the Inventory array with this objects List
Inventory.tInventory =ThisShip.InventoryArray
// run through and global ITEMS list and see if this ship hit it
for each item()
if circlehitshape(x#,y#,Radius#,Item.BoundingBoxShape,item.x,item.y)
// Add a new item to this objects inventory
inventory =new tInventory
// set it's name
inventory.itemname$=Item.name$
// release this item
FreeCurrentItem(Item())
continue
endif
next
EndFunction
Function NewBoundingBoxShape(x1,y1,x2,y2)
ThisShape=NewShape(4,4)
SetShapeVertex ThisShape,0,x1,y1
SetShapeVertex ThisShape,1,x2,y1
SetShapeVertex ThisShape,2,x2,y2
SetShapeVertex ThisShape,3,x1,y2
SetShapeEdge ThisShape,0,0,1
SetShapeEdge ThisShape,1,1,2
SetShapeEdge ThisShape,2,2,3
SetShapeEdge ThisShape,3,3,0
refreshshape ThisShape
EndFunction ThisShape
Function FreeCurrentItem(ThisItem.tItem)
if GetshapeStatus(ThisItem.BoundingBoxShape)
deleteshape ThisItem.BoundingBoxShape
endif
ThisItem=null
EndFunction
[/pbcode]
PlayBASIC V1.64k Beta 14 - Post Fix Support On User Defined Functions.
This additions bring user functions into line with the internally bound & native VM operations. In other words you can declare a user function name and use the # and $ symbols at the end. The parser doesn't use this are the return prototype though, the return type still comes from the what exported after the EndFunction statement.
[pbcode]
Print Yeah$(45)
print SomeOtherFunction#(11.22)
Sync
waitkey
Function Yeah$(A)
This$="Yeah Function="+str$(a)
EndFunction This$
Function SomeOtherFunction#(ThisFloat#)
Print Thisfloat#
This#=Thisfloat#*10
EndFunction This#
[/pbcode]
Note: Function name matching is explicit. So if the function is declared with the post fix, then you can't just drop it, at least not now anyway.
This also works on LinkDLL functions now..
[pbcode]
linkDll "Some.Dlll"
TestFunction#(Param) alias "Something" as float
TestFunction$(Param) alias "Something" as string
EndlinkDll
[/pbcode]
PlayBASIC V1.64k Beta 15 - Yet Another Asteroid Clone.
Been busy today with other real world stuff, so tonight I thought i'd knock up a demo rather than tinker with parser/compiler. This one is yet another asteroids demo, it's really just the first thing that came to mind (that didn't require artwork :) ) . The Interesting thing is, that Asteroids is a game that's often discussed (ie. a common question I get) but I don't really recall seeing too many people get a demo up and running. So I knocked this up.
The demo doesn't actually use anything new in terms of rendering, it's just some alpha additive shapes on depreciated buffer (image blurring). The only thing that makes it a 1.64K program is in the code. Which just uses some of the new features here and there. It could be made to run it in V1.64I/V1.63LE but then there's no point posting it here.. :)
So far the demo features player controls, basic asteroids and player firing, collisions and some particles. Looks ok when running...
YAAC - (Yet Another Asteroids Clone) Blog (http://www.underwaredesign.com/forums/index.php?topic=3258.0)
PlayBASIC V1.64k Beta 16 - Exporting Pointers from PSubs.
Functions and Psubs might look very similar on the surface, but internally they're very different. Originally PlayBasic was only ever designed to be support the three basic data types, Integer,Floats & Strings. So a lot of PB runtime internals we're built around this assumption. However, later on during development, Pointer support was added internally, then later (partly) exposed to the user. Of course, when we tack new functionality in, this has habit of creating some potential issues with older parts of the core parser & code generation.
One such omission was that even though PSUB declarations allow pointer fields to be declared, internally the code generator couldn't meaningfully resolve such operations. So the generator would spit out opcodes that didn't make sense to the runtime, resulting in a Unknown Opcode error upon execution. While here we're focusing upon export pointers, importing them and also cause similar issues.
So resolving these situation is the my current focus. So far, basic pointers can be exported with 'type mismatching' applied.
[pbcode]
explicit true
Dim Cool as integer
Cool =Test_Sub_PointerReturns()
Dim MyPtr as pointer
MyPtr =Test_Sub_PointerReturns()
print Cool
print Int(MyPtr)
Sync
waitkey
Psub Test_Sub_PointerInputs(A as integer pointer)
print int(a)
EndPsub
Psub Test_Sub_PointerReturns()
a=45554
print int(a)
EndPsub A as integer pointer
[/pbcode]
PlayBASIC V1.64k Beta 16 - Pointer & Buffer support from PSubs.
Today's update continues on from the last update. These changes allow pointers to be passed into Psubs. Beyond that that support for importing and exports type and array buffers has been added.
[pbcode]
Type Vector2D
x#,y#
EndType
Dim Cool as Vector2D
Cool.x#=11.22
Cool.y#=22.33
Dim Buffer1(50)
Dim Buffer2(50)
print "return array from sub"
for lp=0 to 1000
buffer1()=TestArrayReturnFromSub(100)
next
print "return array from function"
for lp=0 to 1000
buffer2()=TestArrayReturnFromFunction(200)
next
TestUDFPassToFunction(cool)
TestUDFPassToSub(cool,9999)
Sync
waitkey
Function TestArrayReturnFromFunction(size as integer)
Dim MyArray(size)
Dim lp as integer
for lp=0 to size
MyArray(lp)=1000+lp
next
EndFunction MyArray()
psub TestArrayReturnFromSub(size as integer)
Dim MyArray(size)
Dim lp as integer
for lp=0 to size
MyArray(lp)=1000+lp
next
EndPsub MyArray()
function TestUDFPassToFunction(this as vector2d)
print "Passed UDT buffer into function"
print THis.x
print THis.x
;
EndFunction
Psub TestUDFPassToSub(this as vector2d,qqqq as integer)
print "Passed UDT buffer into sub"
print THis.x
print THis.x
print qqqq
EndPsub
[/pbcode]
Download BETA
[plink]Get PlayBasic V1.64k Beta 16 (http://www.underwaredesign.com/forums/index.php?topic=1150.msg21493#msg21493)[/plink]
PlayBASIC V1.64k - Debugger Syntax Highlighting Tech Test
While this is currently not a built in feature, Here I'm just prototyping a new approach for doing 'Syntax Highlighting', with the hope that it'll make it's way into PB in the not too distant future. The prototype is actually written in PlayBasic V1.64k beta 16.
The goal of this test, is to see how fast I can get the parsing and rendering in pure PlayBasic. The current results are very pleasing, with the loader being able to process over 5000 lines of source in around 250 milliseconds. And the render being able to render basic page of text as between 200->300 FPS, and in some cases even higher.
I don't imagine it'll stay this quick as I introduce more features, but this is light years ahead of the previous approach. Although it's nowhere near as refined atm.. :)
PlayBASIC V1.64k - Debugger Syntax Highlighting Tech Test (continued)
Worked pretty much through the night and most of the day trying to get the tech demo to a point where it incorporates all the main features found in the IDE without costing the earth. So this version pays more attention to the formatting and support multi line comment segments, which the original tech didn't.
Performance wise it's really no slower than it was, at yet as least. Obviously the more aware it is, the more work it has to do at runtime. And by aware I mean it's knowledge of what the code actially is. Ideally an IDE version could be aware of the data type of things you type and help you as you enter code. Much like the current IDE does, but just taking that to a higher lever. But I digress, at the moment what i'm looking at first is building a version that could used in the debugger view. Hopefully with some type of 'hover' support. So you can see the contents of variables, just by hovered over them... But, lets not get too far ahead of ourselves.
Anyway, here's the second piccy of the bare bone tech demo running in PB1.64k. This time i've doubled the size of the test source to over 10000 lines.. Which as expected doubles the parse time to around 525 milliseconds, but it's still running in the 200->300fps range. (approximately 3 to 5 millisecond refresh)), which is nothing compared to some of these tools..
PlayBASIC V1.64k Beta 17 - Fixes Array Passing Inside With PSUBS.
It seems that with the updated condensed function compiler in Beta #16 (and prior I think), there's been an omission with the importing array buffers into PSUB's. But this has been fixed in beta #17.
[pbcode]
Type That
x,y,z
EndType
Dim Dude as That
Dim DudeArray(0) as That
Dude.x=666
DudeArray(0).x=7777
print dude.x
Test1(11,Dude())
Test1(11,DudeArray())
Dim IntArray(100)
Dim FloatArray#(100)
Dim StringArray$(100)
IntArray(0)=44
FloatArray#(0)=11.22
StringArray$(0)="CCOOL"
TestInteger(a,IntArray())
TestFlt(a,FloatArray#())
TestStr(a,StringArray$())
Sync
waitkey
Psub Test1(a,This.That)
print "Exists"
print This.x
EndPsub
Psub TestInteger(a,This())
print "Exists"
print This(0)
EndPsub
Psub TestFlt(a,This#())
print "Exists"
print This#(0)
EndPsub
Psub TestStr(a,This$())
print "Exists"
print This$(0)
EndPsub
[/pbcode]
it's good to see this was picking up by all the diligent beta testers out there .. :)
PlayBASIC V1.64k Beta 18 - Tweaks For Geeks
Starting work on this revision a couple of days back, the objective is to bring some environmental functions into the user command set. So ideally you'll be able query the runtime (VM) environment (about your programs state), which in turns means being able to write routines that are more generic. This presents a few problems I hadn't bargained for. From the how these things will appear to the user and the core implementation. So rather than progressing at a steady pace, work has been revolved around following the instruction set chain down the rabbit hole. Which has uncovered a few issues that need to be altered in order to progress.
Long story short, so rather than focusing on what i'd intended upon doing, i've been revisiting some of the core instructions trying to wedge in the needed functionality. This can presents some bigger than expected problems. Generally if you add more instructions , this often adds more weight to the execution. It's not as cut and dry and one operation does one thing. As the general purpose opcodes are used throughout the language. So adding a bit of weight to this hardly used operation (or so you assumed), can end effecting something you didn't really expect..
To counter this i've been trying to reduce the instruction set, but without removing functionality. This means quickly rethinking the implementation of a number of embedded core operations. What i've been looking for is effectively ways to remove/short cut some existing opcodes, to make space for needed additions. Unfortunately, this sounds easy in principal, but getting it working, just isn't going smoothly. So far, all i've succeeded in doing in either making it much slower, or making it die in bizarre ways.
erm.. what fun...
PlayBASIC V1.64k Beta 18 - Tweaks For Geeks (Cont.)
Had a rather lovely evening of tweaking/removing/rewriting some 5 or 6 year old code fragments. The good news is that Beta 18 is working again, but i'm not too sure I can fit what I actually need into the instruction set without making some really major changes :( .
Given we're talking about working on VM#1 here, i'm really not too fond of the idea of giving a major overhaul now, given the VM2 runtime makes it completely obsolete.. While my objective at start of the 1.64K upgrade was to give PB1.64K as much functionality as possible, but there are limits to how far i'm willing to go with it..
The changes thus far have given Beta 18 a little more bite for you buck though. A good example of this can be seen when running the Debugger Syntax Highlight prototype (http://www.underwaredesign.com/forums/index.php?topic=3264.0) in Beta 18, as compared with Beta 17. Beta 18 can load & parse the 20000 plus lines of source 200 milliseconds faster than beta 17... Same program, but only difference is the revisited runtime.
PlayBASIC V1.64k Beta 18 - CallFunction (Dynamic Function Calling)
All of the recent work has been edging towards adding more operations that allow greater freedoms in user code. What CallFunction does, is it allows you to call a function in your code by name. While it's early days as yet (i've only just got a simplified version working in fact) this functionality will hopefully allow users to write routines that can dynamically call other routines, without the user having to explicitly code it.
This type of functionality tends to pop up when we need to write code that's going to be used between many projects, while still remaining generic. A good example that comes to mind, would be a GUI library. Where the GUI could be written to call a particular user defined action(s). For example, if the GUI detected a button click, the GUI could check if the button has an associated function (something the designer could to do at design time). This function be the code that react to this button click. So the programmer wouldn't have to explicitly add code to react to the button click
Another situation could be in collision detection. If each object had a user associated 'destroy function', then the collision code could be simplified into a more generic version. This would allow the programmer to add more object types and destroy methods, without having to patch them into all the collision routines. So basically it's going to be used a call back mechanism.
Anyway, so far all that's working is calling simple subs without and parameters or returns.. In the example bellow it's calling Psubs, in the future I hope to be able to support user defined functions/psubs and bound functions. But first things first...
This example randomly calls either the functions bellow by name.
[pbcode]
Print "Dynamic Function Calling"
Dim FunctionNames$(1)
FunctionNames$(0)="Test"
FunctionNames$(1)="ThisOtherTest"
Do
Cls 0
for lp=0 to 10
Index=Rnd(1)
CallFunction FunctionNames$(Index)
next
Sync
loop
Psub Test()
Print "Callled Test Sub"
EndPsub
Psub ThisOtherTest()
Print "Called The Other Test Sub"
EndPsub
[/pbcode]
PlayBASIC V1.64k Beta 18 - CallFunction (Dynamic Function Calling) (cont.)
While it's only a few hours later, but the implementation has progressed a bit further already. The current version supports user defined functions and Psubs. Moreover function calls support basic parameter passing. I suspect that only Integer/Float & strings will work (at this point), but I haven't actually tested anything else. Arrays certainly won't work, but pointers and individuals types may work. It doesn't returns though.
Given the function is called by NAME, this means function name has to be resolved back to it's internal pointer. This process was pretty slow in the initial version. With the following benchmark (bellow) taking some 750 milliseconds to execute 10,000 times. However, with a bit of a rethink i've been able to trim this back to a much more respectable 22.8 milliseconds for 10,000 calls.
In the final you'll be able to call functions by name, or by index, which gets rids of the need to search for the function by name. So that'll be a fair be quicker I'd imagine.
[pbcode]
Print "Dynamic Function Calling"
Dim FunctionNames$(3)
FunctionNames$(0)="Test"
FunctionNames$(1)="ThisOtherTest"
FunctionNames$(2)="Test"
FunctionNames$(3)="ThisOtherTest"
MaxTests=10000
Do
Cls 0
frames++
t=timer()
for lp=0 to MaxTests
CallFunction FunctionNames$(lp &3)
next
tt1#+=(timer()-t)
print tt1#/frames
CallFunction "Yeah",45
Sync
loop
Psub Test()
; Print "Callled Test Sub"
EndPsub
Psub ThisOtherTest()
; Print "Called The Other Test Sub"
EndPsub
Function Dude()
; ink $ff0000
; Print "Called The Other Test Sub"
; ink $ffffff
EndFunction
Function Yeah(x)
ink $ff0000
print "Running Function"
Print x
ink $ffffff
EndFunction
[/pbcode]
Quickly tested calling via Function Index.. And it'll execute the equivalent loop in about 3.8 milliseconds. So clearly, if via index will be the best of the options, If speed is a concern. CallFunction will always be slower than native function call though.
PlayBASIC V1.64k Beta 18 - CallFunction (Calling Bound DLLs)
Still working on getting this feature to work as robustly as possible. Which means being able to call the all thenative function types, those being Psubs, Functions and bound (via linkDll) functions.
There's a few big issues that need error trapping, in particular with calling bound (dll) functions. Namely the issues resolve around there being no way to really screen the CallFunction parameters at compile time. So this stuff can get lightly sanitized at run time. So if you try and shovel the wrong parameters types into a function call, then there's not too much I can do about it. So in this case you should expect it die... There's some type matching but that's about it.
The other drama is managing whats returned from the various types of function calls. Which of course all work differently and return data differently also. Which is further compounded by not actually knowing the return type of the function. Since this can't be resolve during compliation.. Which is turning out to be a tricky one. My gut feeling is that it'll only returning Integer/Floats and Strings though, unless something magical happens.
PlayBASIC V1.64k Beta 19 - CallFunction (Dynamic Function Calling)
As of BETA 19, the call function command works with User defined Functions, User Defined Psubs and Linking DLL's - However the implementation in this version can only pass basic parameters (Integers/Floats & Strings), and can not return anything from the called function.
Here's a basic example..
[pbcode]
Print "Dynamic Function Calling"
Dim FunctionNames$(3)
FunctionNames$(0)="Yeah"
FunctionNames$(1)="SubYeah"
Do
Cls 0
for lp=0 to 1
Name$=FunctionNames$(lp)
CallFunction Name$,Rnd(100),rnd#(200),Name$
next
Sync
loop
Function Yeah(x,y#,Name$)
ink $ff0000
print "Running Function ["+Name$+"]"
Print x
Print y#
ink $ffffff
EndFunction
Psub SubYeah(x,y#,Name$)
ink $00ff00
print "Running Psub ["+Name$+"]"
Print x
Print y#
ink $ffffff
EndPsub
[/pbcode]
PlayBASIC V1.64k Beta 20 - FunctionExist /FunctionIndex
These couple of functions are just to round off the CallFunction operation above. I'd hope hope what they do is pretty self explanatory, but just in case... FunctionExist allows us to check if a Function Name exists, FunctionIndex lets us pre-calc the internal index of the function. The latter is so that you can store the index to the function rather than it's name.
Calling by name is fine if you're only calling the function a small amount, but the 'name searching' overhead sure adds up with you call them lot (1000's of times). So in those situations it'd better to pre-calc the functions index, then call it using the index,rather than it's name..
[pbcode]
print "function Exist"
print FunctionExist("Yeah")
print FunctionIndex("Yeah")
CallFunction FunctionIndex("Yeah"),222,333.44,"This is working"
Sync
Waitkey
Function Yeah(x,y#,z$)
ink $ff0000
print "Running Function"
Print x
Print y#
Print z$
ink $ffffff
EndFunction
[/pbcode]
PlayBASIC V1.64k Beta 20 - limited Optional Parameter Support For Command Calls
Optional parameter support is one of those features that's been on the design doc for what seems like years, so it's long overdue. This feature, allows us to drop from the trailing parameter(s) from certain internal commands calls. When you drop the parameter, the command uses the 'internal default' for this parameter. These will be the mostly settings for a command.
At this point, it only supports commands and not internal functions. But obviously that'll come after i've weeded the bumps out. The main issue with adding it is how the internal parameter matching and moreover how the parameter passing works in vm. So it's a little messy getting it work and there are a number limitations, but it should be ok for the most part.
Bellow is a tiny example of new change. Spot the difference ? - it's pretty subtle.. Notice the CLS commands parameter is now optional. If left out, the command defaults to BLACK (rgb(0,0,0)).. Which reminds a very long winded discussion we had with somebody about what the 'default' colour of Cls should be. But anyway..
[pbcode]
Do
Cls
print "Optional CLS "
box 100,100,200,200,true
Sync
loop
[/pbcode]
PlayBASIC V1.64k Beta 20 - limited Optional Parameter Support For Command Set Function Calls
Continuing on from where the last post left off, now we have optional parameter support in both internal commands and internal functions. So far there's only one function with a optional and that's the MID$() function. The Length parameter is now optional in this function, if you leave it out it'll default to a length of 1.
So it's like the MID() function (they are different !) except MID$(String$,pos) returns a single character as a string. Where MID(String,pos) returns the single character (it's ASCII value) as an integer. So MID() is the equivalent of asc(mid$(String$,pos,1)) in old school BASIC.
[pbcode]
Do
Cls
print "Optional Parameters in Commands"
box 100,100,200,200
circle 400,400,50
print "Optional Parameters in Functions"
a$="Hello"
for lp=1 to len(a$)
print mid$(a$,lp) ; notice the length is missing, it defaults to one now
next
Sync
loop
[/pbcode]
Benchmark
Does dropping an optional parameter wins us some speed ? - Well, lets check...
[pbcode]
MaxTests=10000
a$=" Hello "
Do
Cls 0
frames++
t=timer()
for lp=0 to MaxTests
b$=trim$(a$," "+chr$(9))
next
tt1#+=(timer()-t)
print tt1#/frames
t=timer()
for lp=0 to MaxTests
b$=trim$(a$)
next
tt2#+=(timer()-t)
print tt2#/frames
Sync
loop
[/pbcode]
Both loops execute at virtually identical speeds. So no... Why ? - Well, just because the parameter is optional, this doesn't mean nothings being passed into the function. While you may not have explicitly sent anything in, behind the scenes the compiler is outputting the code to pass the 'default' parameter for you. So the operation is the same in the output code.
PlayBASIC V1.64k Beta 21 - Optional Parameter For User Defined Functions
I doubt this comes as any great surprise, as it's a bit of no brainer that I'd be adding optional parameter support to User Defined Functions (& Psubs) next. Adding this one requires a little more tinkering than the internal stuff. Mainly because the pre-parser has to decipher the input parameters (and what they mean), beyond that, it's just matter tweaking up the user function matching to generate the optional parameters in the function call.
So far the first stage (the parsing) is basically working, ie
[pbcode]
MyFunction(100,200,300)
Sync
waitkey
; Declare A,B and C as an optional that defaults to 1
Function MyFunction(a,b,c=1)
print a
print b
print c
EndFunction
[/pbcode]
PlayBASIC V1.64k Beta 21 - Optional Parameter For User Defined Functions (Continued) Well, we can just about tick another feature off the to do list. The current version has optional integer parameter support up and running for user defined functions. Currently the parser only supports the
explicit syntax in the function header, rather than the 'As Datatype" method. Bit it's at least working..
To declare a parameter as being optional, this parameter uses the equals sign to declare this parameters default value(or string) in the function header.
ie.
[pbcode]
Function IncreaseVariable(ThisVariable, IncreaseAmount = 1)
Result =ThisVariable +IncreaseAmount
EndFunction Result
[/pbcode]
In the example, this user defined function is basically the equivalent of the INC operation. If the user calls this function and omits the second param, then PB uses the functions default value for this parameter (which is 1). So calling it with only one parameter, will add one to the input variable. but if you use two params, then it's use what value you passed in for
IncreaseAmount Limitations,
* optional parameters can only be simple types. (Integers, floats and strings)
* optional parameters must be the last parameters. So you can't currently mix optional parameters in between fixed parameters. So this
Function Dostuff(A , B=10 , C) is not supported.
Sample,
[pbcode]
print Add() ; Use all the optionals
print Add(10) ; u8se last 2 optionals
print Add(10,20) ; use last optional
print Add(10,20,30) ; no optional parameters, so all parameters are manually sent
Sync
WaitKey
Function Add(a=50,b=100,c=200)
A+=b+c
EndFunction a
[/pbcode]
Outputs,
Quote
350
310
230
60
Samples Had few issues adding float + string support, but the follow examples of what's currently running in the latest build of beta 21
[pbcode]
print TestStrings("Hello")
Sync
WaitKey
Function TestStrings(a$,b$="World")
result$=a$+" "+b$
EndFunction Result$
[/pbcode]
Outputs
Hello World Here's a version testing floats.
[pbcode]
print TestFloats("Flt")
print TestFloats2("Flt")
Sync
WaitKey
Function TestFloats(a$,b#=123.456)
result$=a$+"="+str$(b#)
EndFunction Result$
; Notice the mismatched assignment in the cast (B# = integer constant)
Function TestFloats2(a$,b#=123)
result$=a$+"="+str$(b#)
EndFunction Result$
[/pbcode]
outputs
Quote
Flt=123.456
Flt=123.0
The pre-parser had to be updated to handle both of these cases... but they're working ok now..
PlayBASIC V1.64k Beta 22 - Optional Parameters In User Defined Functions/Command Calls
This addresses an omission in the previous beta, where functions that didn't return a result couldn't use optional parameters, which has since been addressed. The only thing missing now (off the top of my head) is Psub support for optional parameters.
[pbcode]
Dude 10,20,30
Dude 10,20
a=MyFunction(100,200)
Sync
WaitKey
Function Dude(a,b,c=55)
print "DUDE"
print a
print b
print c
EndFunction
; Declare A,B and C as an optional that defaults to 1
Function MyFunction(a,b,c=234,f$="Yeah",g=true)
print "My Function"
print a
print b
print c
print f$
aa=a+b+c
EndFunction aa
[/pbcode]
Psub Support
[pbcode]
SubDude 10,20
SubDude 10,20,30
SubDude 10,20
a=MyFunction(100,200)
Sync
WaitKey
Function Dude(a,b,c=55)
print "DUDE"
print a
print b
print c
EndFunction
Psub SubDude(a,b,c=55)
print "DUDE as a SUB"
print a
print b
print c
EndPsub
; Declare A,B and C as an optional that defaults to 1
Function MyFunction(a,b,c=234,f$="Yeah",g=true)
print "My Function"
print a
print b
print c
print f$
aa=a+b+c
EndFunction aa
[/pbcode]
PlayBASIC V1.64k Beta 22 - SortArray (string)
Dropped this old chestnut back in. While it works, it's not particularly quick.
[pbcode]
Size=10
Dim name$(Size)
for lp=0 to size
name$(lp)=ReadData$()
next
SortArray name$(),0,size
for lp=0 to size
print name$(lp)
next
Sync
waitkey
Data "zack","wolf","kev","andy","michelle","dogs","tess","c64","zynaps","dudes","Alpha"
[/pbcode]
PlayBASIC V1.64k Beta 24 - More As DataType Support in Function/Psub Declarations
Since we've added support for the As DataType convention in function declarations for Variables/Pointers/Types it stands to reason that some people will want to declare Arrays in such a fashion also. While this is a little problematic given how the prototyping pass works in PB, it should be doable. But the solution just isn't pretty.
Sample,
[pbcode]
Dim Stuff(100)
RandomizeIntegerArray(Stuff(), 100)
Sync
waitkey
Function RandomizeIntegerArray(Me() as integer, Max as integer)
For lp =0 to Getarrayelements(me())
Me(lp) =rnd(Max)
next
EndFunction
[/pbcode]
Continued
Due to running into a few catch 22's lately in how the pre-pass #1 prototyping and Pass#2 used to work, I've ended up biting the bullet and making the prepass that little bit smarter. Turned out to be fairly straight forward as virtually all the code have been previously written, it just need to be unified better. Which just means that the pass#2 doesn't need to bother about the parameters anymore, so expression solver won't have a fit with the extra info in the function declaration.
[pbcode]
Dim Stuff(100)
RandomizeIntegerArray(Stuff(), 100)
Dim Stuff#(100)
RandomizeFloatArray(Stuff#(), 100)
Dim Stuff$(100)
RandomizeStringArray(Stuff$(), 100)
Sync
waitkey
Function RandomizeIntegerArray(Me() as integer, Max as integer)
For lp =0 to Getarrayelements(me())
Me(lp) =rnd(Max)
next
EndFunction
Function RandomizeFloatArray(Me() as float, Max as integer)
For lp =0 to Getarrayelements(me#())
Me#(lp) =rnd(Max)
next
EndFunction
Function RandomizeStringArray(Me() as string, Max as integer)
For lp =0 to Getarrayelements(me$())
Me$(lp) =str$(rnd(Max))
next
EndFunction
[/pbcode]
Lists
Updated the Function parameter parser to support the As UDT LIST convention. So you can declare the parameter as a Typed LIST the same way as it's created. The function doesn't really need to known it's a LIST, it's more for the user. Internally a typed variable and typed list are the same structure underneath. So they're interchangeable, it's just doesn't make list management enabled. Moreover, a typed variable is really a 1D typed array.
List Declaration Example.
[pbcode]
Type Pos
iValue
fValue#
EndType
Dim Numbers1 as pos list
Dim Numbers2 as pos list
AddValuesToLIst_LH(Numbers1(),10,2000)
AddValuesToLIst_LH(Numbers2(),10,2000)
print getlistsize(Numbers1())
print "Size:"+Str$(getlistsize(Numbers1()))
for each numbers1()
print numbers1.ivalue
next
print "Numbers #2"
print "Size:"+Str$(getlistsize(Numbers2()))
for each numbers2()
print numbers2.ivalue
next
Sync
waitkey
; Long hand declarations using AS DataType LIST
Function AddValuesToLIst_LH(Me as pos list, Count as integer, Max as integer)
For lp =0 to Count-1
me = new pos
Me.ivalue =rnd(Max)
next
EndFunction
; short hand declarations, same as above!
Function AddValuesToLIst_SH(Me.pos, Count, Max)
For lp =0 to Count-1
me = new pos
Me.ivalue =rnd(Max)
next
EndFunction
[/pbcode]
PlayBASIC V1.64k Beta 24b - Optional Parameter Tweaks
Optional parameters can now use either literal constants or language constants. Although, you can't use User Defined constants at this time.
[pbcode]
TestOptionalStringConstant("Testing")
TestOptionalStringConstant()
Sync
waitkey
Function TestOptionalStringConstant(Yeah$=PlayBasic$)
print Yeah$
EndFunction
[/pbcode]
PlayBASIC V1.64k Revision 2 - Beta 2 - Function Prototype Tweaks
For the next few days/week I'll be working on a tweaking up revision #2 of the V1.64K package. Namely trying to address some issues that should been discovered during the beta testing, but weren't.. So here we are again..
Anything not solved during this testing phase, won't be looked at until the next major update 1.64L
Function Prototyping
[pbcode]
Dim Array(1)
Dim Array#(1)
Dim Array$(1)
Type Pos
x,y,z
EndType
; Yeah=1
Global State=true
for State=0 to 1
print "Test:State="+str$(State)
print Stuff_int()
print Stuff_int2()
print Stuff_float()
print Stuff_float2()
print Stuff_Str()
print Stuff_Str2()
next
Sync
waitkey
waitnokey
cls 0
for State=0 to 1
print "Test:State="+str$(State)
Array()=Stuff_intarray()
print GetArrayElements(Array())
Array$()=Stuff_Strarray()
print GetArrayElements(Array$())
#break
next
Sync
waitkey
waitnokey
Function Stuff_INtArray()
if State
Dim TestArray(100)
exitfunction TestArray()
else
Dim TestArray(200)
endif
EndFunction TestArray()
Function Stuff_FltArray()
if State
Dim TestArray#(100)
exitfunction TestArray#()
else
Dim TestArray#(200)
endif
EndFunction TestArray() as float
Function Stuff_StrArray()
if State
Dim TestArray$(102)
exitfunction TestArray$()
else
Dim TestArray$(202)
endif
EndFunction TestArray() as string
Function Stuff_INt()
a=1
Yeah=2
if State
exitfunction a
endif
EndFunction Yeah
Function Stuff_INt2()
a=1
Yeah=2
if State
exitfunction a
endif
EndFunction Yeah as integer
Function Stuff_Float()
a#=1
Yeah#=2
if State
exitfunction a#
endif
EndFunction Yeah#
Function Stuff_Float2()
a#=1
Yeah#=2
if State
exitfunction a#
endif
EndFunction Yeah as float
Function Stuff_Str()
a$="1$"
Yeah$="2$"
if State
exitfunction a$
endif
EndFunction Yeah$
Function Stuff_Str2()
a$="1$"
Yeah$="2$"
if State
exitfunction a$
endif
EndFunction Yeah as string
[/pbcode]
PlayBASIC V1.64k Revision 2 - Beta 3 - Final Clean Up
Well, given there hasn't been a single bit of user feedback, it looks like Beta 3 will be the release version. Apart from correcting a bug with constant floats as optional parameters, this one has a few tiny changes. Namely this version adds the ability to enable Vsync in windowed modes.
A couple of points though, if you enable it, then the refresh rate will be whatever the users desktop refresh rate is. So don't assume it'll be the same as yours, and secondly, the users machine might not be able to vsync.. ie card doesn't support it or user has disabled it in the driver..
[pbcode]
img= MakeGridPatternImg(32,4,32,4,10,rgb(120,130,140),rgb(150,150,150),rgb(210,200,200))
//
StartTime=Timer()
Do
TileIMage img,Xpos,0,false
TimePast=Timer()-StartTime
Xpos-=1
if spacekey()
ScreenVsync 1-getScreenVsync()
flushkeys
endif
Text 0,0,"Vsync:"+Str$(GetScreenVsync())
Sync
loop
Function MakeGridPatternImg(GridWidth,GridWidthStepX,GridHeight,GridHeightStepY,Segs, BG_RGB, SubDiv_RGB, HighLight_RGB)
oldRgb=Getink()
oldSurface=GetSurface()
w =GridWidth *Segs
h =GridHeight *Segs
ThisIMage=NewImage(w,h)
RenderToImage thisimage
Cls BG_RGB
ink SubDiv_RGB
lockbuffer
For Ylp=0 to H-1 step GridWidthStepX
For Xlp=0 to w-1 step GridHeightStepY
line 0,ylp,w,ylp
line xlp,0,xlp,h
next
next
unlockbuffer
ink HighLight_RGB
lockbuffer
For Ylp=0 to H-1 step GridHeight
For Xlp=0 to w-1 step GridWidth
line 0,ylp,w,ylp
line xlp,0,xlp,h
next
next
unlockbuffer
; restore old surface and ink colour
RenderToImage OldSurface
ink oldrgb
EndFunction ThisImage
[/pbcode]
Hi Kevin
QuoteNamely this version adds the ability to enable Vsync in windowed modes
now that sounds good to me , did try a few things in window mode in previous PB versions and seem to be quite glitchy ,
so this will be a great help i think
mick :)
yes & no. It's nice to have a vsync'd window.. But, this comes with a cost.
to kev
thanks for vsync in window mode.
i avoided using vsync in my game because i wanted full screen & window to run the same. i experimented for a while to figure out the smoothest comprimise, but now i can run both in vsync. i am very happy.
was it difficult to impliment this into playbasic? could you have done this in older versions?
what is the 'cost' of having vsync in window mode? my computer shows no difference in speed in fullsceen to window mode (i mean calc speed, not fps).
thanks stevmjon
[plink]Read Here (http://www.underwaredesign.com/forums/index.php?topic=1182.45)[/plink]