PlayBasicFX (from version 1.65 + above) Screen Shot Updates
This thread is (will be) a collection of screen shots / demo tidbits during the development of PBFX. Since PBFX now features hardware 3D acceleration, the pics in this thread will mostly be old demos quickly updated to use some of the new benefits of 3D.
Z Rotater demo This pic of the z rotater example in the PB demo. The main change are the textures were loaded as 3D images (load3DIMage) and then the front plan of the textures are drawn using the inkmode 1+32 (alpha 50).
Textured Cube Demo The texture is loaded as 3d image, than rendered with inkmode 32
Texture Mapped Terrain
[plink] Read Here (http://www.underwaredesign.com/forums/index.php?topic=1509.msg12965#msg12965)[/plink]
UW3D ( 3D engine written in PlayBASIC )
Read Here (http://www.underwaredesign.com/forums/index.php?topic=490.msg12956#msg12956)
Basic Sprite Draw Modes in PB1.67 The replacement sprite engine is partly working again. Sprites can be positioned, scaled, transparent, have handles, some draw modes (static, rotated, alpha, alha50, Alpha Addition) , vertex colours (in some draw modes) and that's about it for the time being.
another pic.. all using alpha add
Those are two of the most beautiful PB screenies to date. Excellent work :)
Sprite Entities The following 4 pics represent a new feature in PB, Sprite Entities. What are they you ask ? They're a new type of sprite that contains a mesh, each with it's own set of vertex and face definitions. This allows a sprites to built in more complex shapes / structures than a traditional quad allows.
Bellow each sprite is set up with it's standard frame plus 10 each faces attached + offset from it. So each sprite entity is basically the equivalent (in terms of drawing) of 11 old sprites. You can have as many faces in the sprite as you like.
pic#1 = 1 sprites with 11 faces (22 polygons)
pic#2 = 100 sprites with 11 faces (2200 polygons)
More of the same but with alpha addtion.
pic#3 = 250 sprites with 11 faces (5500 polygons)
pic#4 = 500 sprites with 11 faces (11000 polygons)
This effect is made from 100 entity sprites, each with 250 faces (32*32 in size). The faces are 2 pixels apart, so that they overlap each over, creating a laser effect when drawn using the spark particle image + alpha addition.
That's 100*250*2 =50k triangles
Sprite Entities Cont Entities allow you to take the sprite and build more complex meshes from it. In this tiny example, we're taking single frame sprite and adding a bunch of frames to form a ring of sprites out of 1 sprite . These can then be rotated, scaled, moved and ultimately even collided with !
The main benefit of entities is their batch friendly, so the entire sprite drawn, is only
one draw call. Where, normally you'd have to draw each face separately.
load3Dimage "animal.jpg",1
load3dimage "particle_white.bmp",2
; Create the foreground sprite + mesh around with it's mesh
CreateSprite 1
positionsprite 1,400,300
SpriteDrawmode 1,2
SpriteImage 1,1
centerspritehandle 1
SpriteVertexQuantity 1,8
SpriteFaceQuantity 1,8
PokeSpriteVertex 1, 4, 200,0,0
PokeSpriteVertex 1, 5, 300,0,0
PokeSpriteVertex 1, 6, 300,300,0
PokeSpriteVertex 1, 7, 200,300,0
PokeSpriteFaceVerts 1,1,4
PokeSpriteface 1,1,0,4,0,0,$ffff00
PokeSpriteface 1,1,1,5,1,0,$ffff00
PokeSpriteface 1,1,2,6,1,1,$ffffff
PokeSpriteface 1,1,3,7,0,1,$ff00ff
; deform the vertex 0 and 2 top left and bottom right
pokespritevertex 1,0,-30,-40,0
pokespritevertex 1,2,130,290,0
; POke Face 0 of this Sprite
PokeSpriteface 1,0,2,2,1.0,1.0,$ff00ff
; Create a bunch of entity sprites. These create rings of sprite frames
For lp=0 to 100
me= MakeParticleSprite(2,rnd(800),rnd(600),rndrange(10,20))
next
Do
Cls 0
drawallsprites
turnsprite 1,0.05
turnsprite me,0.15
scalesprite 2,1+cos(angle#)
print Fps()
angle#=angle#+1
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDRawMOde ThisSprite, 2+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Sprite Entities cont.. This one is mixture of scrolling back drop and sprite entity/particles. The values on the top left of the display are FPS, Sprite Count & Face Count
load3dimage "D:\Play_Basic\PlayBasic\Projects\GFX\particle_white.bmp",2
loadimage "D:\Play_Basic\PlayBasic\Projects\GFX\Tree.jpg",1
Type tParticle
Sprite
X#
Y#
ScaleX#
ScaleY#
Time
MaxTime
Colour
EndType
Dim Parts(1) as tParticle
; setfps 60
Do
; Cls rgb(30,40,50)
Tileimage 1,Xpos,0,false
Xpos=mod(Xpos-1,GetIMageWidth(1))
SpriteCount=0
SpriteFaceCount=0
For lp=1 to GetArrayelements(Parts(),1)
if Parts(lp)
if Parts(lp).time<Parts(lp).Maxtime
Parts(lp).time=Parts(lp).time+1
x#=parts(lp).x
y#=parts(lp).y
sx#=parts(lp).Scalex+0.50
sy#=parts(lp).Scaley+0.50
Spr=parts(lp).Sprite
ScaleSpriteXY Spr,SX#,Sy#
TurnSprite Spr,0.25
;Angle#
parts(lp).Scalex=sx#
parts(lp).Scaley=sy#
inc SpriteCount
SpriteFaceCount=SpriteFaceCount+GetSpriteFaceQuantity(Spr)
else
DeleteParticles(lp)
endif
endif
next
DrawAllSprites
if Nexttime=0
x#=rnd(GetScreenWidth() )
y#=rnd(GetScreenHeight() )
; For lp=1 to 10
; AddParticles(2,x#,y#,rndrange(10,50))
; next
nexttime=2+rnd(3)
endif
dec nexttime
if Mousebutton()
x#=mousex()
y#=mousey()
AddParticles(2,x#,y#,rndrange(10,50))
endif
ink $ff0000
text 10,10,fps()
text 10,30,SpriteCount
text 10,50,SpriteFaceCount
Sync
loop
Function DeleteParticles(index)
DeleteSprite Parts(index).Sprite
Parts(Index)=null
EndFunction
Function AddParticles(ThisIMage,x#,y#,POints)
index=GetFreeCell(Parts())
Parts(index).x=x#
Parts(index).y=y#
Parts(index).scalex=1
Parts(index).scaley=1
Parts(index).colour=rndrgb()
Parts(index).Maxtime=50
Parts(index).time=0
Parts(index).Sprite=MakeParticleSprite(ThisIMage,X#,Y#,points)
EndFunction
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDRawMOde ThisSprite, 2+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=4
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=rndrange#(1,50)
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Hi!
This all sounds very very interesting!
Does this mean you can use those "faces" for independent particles
let's say 1 sprite with 1000 faces and you can place every face separatly on screen?
Or are the faces more for spriteanimation?
Greetings
stef
QuoteDoes this mean you can use those "faces" for independent particles
let's say 1 sprite with 1000 faces and you can place every face separatly on screen?
You can position the vertex are place you want, however their local to their sprites origin point (their offset from the sprites position)
However See Sprite Particles (http://www.underwaredesign.com/forums/index.php?topic=338.msg13074#msg13074)
Sprite Perspective The following pic's are an extension of the previous entity demos, but this time the sprites are rotating in 3D (XYZ) and being projected and rendered in perspective.
load3Dimage "animal.jpg",1
load3Dimage "particle_white.bmp",2
CreateSprite 1
positionspritexyz 1,400,300,1000
SpriteDrawmode 1,2
SpriteImage 1,1
centerspritehandle 1
SpriteVertexQuantity 1,8
SpriteFaceQuantity 1,8
PokeSpriteVertex 1, 4, 200,0,0
PokeSpriteVertex 1, 5, 300,0,0
PokeSpriteVertex 1, 6, 300,300,0
PokeSpriteVertex 1, 7, 200,300,0
PokeSpriteFaceVerts 1,1,4
PokeSpriteface 1,1,0,4,0,0,$ffff00
PokeSpriteface 1,1,1,5,1,0,$ffff00
PokeSpriteface 1,1,2,6,1,1,$ffffff
PokeSpriteface 1,1,3,7,0,1,$ff00ff
max=1000
For lp=0 to max
me= MakeParticleSprite(2,rnd(800),rnd(600),rndrange(15,25))
positionspritexyz me,rndrange(-800,800),_
rndrange(-800,800),_
rndrange(200,5000)
facecount=facecount+getSpriteFaceQuantity(me)
next
;' SetFps 30
Do
Cls 200
For lp=1 to max
TurnspriteXYZ lp,0.1*(lp/100),0.2,0.15
angle2#=angle#+(lp*5)
SpriteAlphaLevel lp,cosnewvalue(0.5,angle2#,0.5)
z#=GetSpriteZ(lp)-1
if z#<200
z#=5000
endif
PositionspriteZ lp,z#
drawsprite lp
next
; DrawOrderedSprites
; drawallsprites
ink $ffffff
; Scalesprite 2,1+cos(angle#)
f=fps()
print f
angle#=angle#+1
print Screen3dstate()
print FaceCount
print FaceCount*f
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2+16
SpriteVertexQuantity thisSprite,(Points)*4
SpriteFaceQuantity thisSprite,(Points)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Psub SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset+lp,X#,y#,z#
Rotation=wrapangle(Rotation,90)
next
EndPsub
Psub SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndPsub
NOTE: I doubt this code will functin the same in future versions (versions above PB1.68c) as the pespective calc's are currently hard coded into the mesh translation.
These are some higher poly count versions.
Sprites as Terrains perhaps ? The following thrown together picture is rendering something resembling a test scene. In the scene we have a scrolling tiled animal images, 500 alpha addition/rotating perspective sprites entities plus a sprite built into something more like a terrain segment.
load3Dimage "animal.jpg",1
load3Dimage "particle_white.bmp",2
load3Dimage "face.jpg",3
scaleimage 3,2048,2048,1 ; << Huge TEXTURE SIZE
CreateSprite 1
positionspritexyz 1,400,300,1000
SpriteDrawmode 1,2
SpriteImage 1,1
centerspritehandle 1
SpriteVertexQuantity 1,8
SpriteFaceQuantity 1,8
PokeSpriteVertex 1, 4, 200,0,0
PokeSpriteVertex 1, 5, 300,0,0
PokeSpriteVertex 1, 6, 300,300,0
PokeSpriteVertex 1, 7, 200,300,0
PokeSpriteFaceVerts 1,1,4
PokeSpriteface 1,1,0,4,0,0,$ffff00
PokeSpriteface 1,1,1,5,1,0,$ffff00
PokeSpriteface 1,1,2,6,1,1,$ffffff
PokeSpriteface 1,1,3,7,0,1,$ff00ff
max=1000
For lp=0 to max
me= MakeParticleSprite(2,rnd(800),rnd(600),rndrange(10,25))
facecount=facecount+(getSpriteFaceQuantity(me)*2)
positionspritexyz me,rndrange(-1000,1000),_
rndrange(-1000,1000),_
rndrange(150,10000)
SpriteRotationMode me,1
next
terrain= MakePlainSprite(3,rnd(800),rnd(600),64)
SpriteRotationMode terrain,1
positionspritexyz terrain,0,00,10500
spritehandle terrain,0,0
turnspritexyz terrain,30,0,0
TerrainFacecount=getSpriteFaceQuantity(Terrain)
facecount=(facecount)+getSpriteFaceQuantity(Terrain)
Do
tileImage 1,ix,-100,false
ix=mod(ix+1,getimagewidth(1))
For lp=1 to max+2
TurnSpriteXYZ lp,1.11*(lp/(1.0*max)),0,1
z#=GetSpriteZ(lp)-100
if z#<150
z#=10000
endif
PositionspriteZ lp,z#
next
turnspriteXyz terrain,0,0.1,0
DrawAllSprites
ink $ffffff
setcursor 0,0
f=fps()
print f
angle#=angle#+1
print Screen3dstate()
print FaceCount
print FaceCount*f
print TerrainFacecount
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2+16
SpriteVertexQuantity thisSprite,(Points)*4
SpriteFaceQuantity thisSprite,(Points)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Psub SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset+lp,X#,y#,z#
Rotation=wrapangle(Rotation,90)
next
EndPsub
Psub SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndPsub
Function MakePlainSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2
SpriteTransparent ThisSprite,on
turnspritexyz thissprite,00,00,00
Points2=(points+1)
Dim Matrix#(POints2,points2)
RadomizeHeightMap(Matrix#(),10000)
SmoothHeightMap(Matrix#(),4)
SpriteVertexQuantity thisSprite,(Points2*POints2)
SpriteFaceQuantity thisSprite,(Points2*Points2)*2
Size=512
HandleX#=-(((points+1.0)/2.0)*size)
HandleZ#=-(((points+1.0)/2.0)*size)
; init vertex
for Ylp=0 to Points
Zpos#=ylp*Size
for Xlp=0 to Points
Xpos#=Xlp*Size
ThisVertex=(Ylp*(points+1))+xlp
ypos#=Matrix#(xlp,ylp)
PokeSpriteVertex ThisSprite,ThisVertex,Xpos#+HandleX#,1000+Ypos#,Zpos#+HandleZ#
next
next
ThisColour=rgb(255,255,255)
; init faces (UV points U=X in texture space, V = Y in texture space)
TUstep#=1.0/(points+1)
Tvstep#=1.0/(points+1)
For Ylp=0 to points-1
For Xlp=0 to points-1
CurrentVertexRow =(Ylp*(points+1))+Xlp
NextVertexRow =CurrentVertexRow+(points+1)
PokeSpriteFaceVerts ThisSprite,ThisFace,3
u1#=Xlp*TUstep#
v1#=Ylp*TVstep#
u2#=(Xlp+1)*TUstep#
v2#=Ylp*TVstep#
u3#=(Xlp+1)*TUstep#
v3#=(Ylp+1)*TVstep#
u4#=(Xlp+0)*TUstep#
v4#=(Ylp+1)*TVstep#
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,CurrentVertexRow+1 ,u2#,v2#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow+1 ,u3#,v3#,ThisColour
inc ThisFace
PokeSpriteFaceVerts ThisSprite,ThisFace,3
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,NextVertexRow+1 ,u3#,v3#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow ,u4#,v4#,ThisColour
inc ThisFace
next
next
EndFUnction ThisSPrite
` *=----------------------------------------------------------------=*
` >> Randomize HeightMap Array <<
` *=----------------------------------------------------------------=*
Function RadomizeHeightMap(Matrix#(),Height)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
For Zlp=1 to Depth-2
For Xlp=1 to Width-2
Matrix#(xlp,zlp)=rnd#(Height)
next xlp
next zlp
Endfunction
` *=----------------------------------------------------------------=*
` >> Average Matrix Height <<
` *=----------------------------------------------------------------=*
Function SmoothHeightMap(Matrix#(),passes)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
Dim Temp_HeightMap_Yvalues#(Width,Depth)
For ThisPass=0 To Passes
CopyArray Matrix#(),Temp_HeightMap_Yvalues#()
For Zlp=1 to Depth-1
ZlpF=zlp-1
ZlpB=zlp+1
Width2=Width-1
For Xlp=1 to Width2
xlpL=Xlp-1
xlpR=Xlp+1
yb#=Temp_HeightMap_Yvalues#(xlp,zlp)
yt#=Temp_HeightMap_Yvalues#(xlp,zlpF)
yb#=Temp_HeightMap_Yvalues#(xlp,zlpB)
yl#=Temp_HeightMap_Yvalues#(xlpL,zlp)
yr#=Temp_HeightMap_Yvalues#(xlpR,zlp)
ytl#=Temp_HeightMap_Yvalues#(xlpL,zlpF)
ytr#=Temp_HeightMap_Yvalues#(xlpR,zlpF)
ybl#=Temp_HeightMap_Yvalues#(xlpL,zlpB)
ybr#=Temp_HeightMap_Yvalues#(xlpR,zlpB)
matrix#(xlp,zlp)=(yb#+yt#+yb#+yL#+yr#+ytl#+ytr#+ybl#+ybr#)/9
next xlp
next zlp
next ThisPass
unDim Temp_HeightMap_Yvalues#()
endfunction
Note: This code as written for the PB 1.68 alpha's, it's unlikely to work in future versions of PB.
Perspective Sprite Terrain This shot creates a 3D terrain using a single entity sprite. The Sprite scene is being rendered with a new test command
DrawPerspectiveSprites. Currently this test command requires the user to build and pass in a camera (viewer) structure, since that's the easiest way to test it. In the future it'll just be built in.
Type PBposition
x#,y#,z#
EndType
Type PBProjection
x#,y#
EndType
Type PBCamera
Status
pos as PBPosition
angle as PBPosition
scale as PBPosition
RotationMode
ProjectionMode
Projection as PBProjection
ViewPoint as PBPosition
EndType
Dim Camera as PBCamera Pointer
Camera = new PBCamera
Camera.pos.X=0
Camera.pos.y=0
Camera.pos.z=0
Camera.Projection.x=400.0
Camera.Projection.Y=300.0
Camera.ViewPoint.X=GetScreenWidth()/2.0
Camera.ViewPoint.y=GetScreenHeight()/2.0
load3Dimage "animal.jpg",1
load3Dimage "particle_white.bmp",2
load3Dimage "face.jpg",3
; load3Dimage "particle_white.bmp",3
; scaleimage 3,256,256,1
; scaleimage 2,1024,1024,1
scaleimage 3,2048,2048,1
CreateSprite 1
positionspritexyz 1,400,300,1000
SpriteDrawmode 1,2
SpriteImage 1,1
centerspritehandle 1
SpriteVertexQuantity 1,8
SpriteFaceQuantity 1,8
PokeSpriteVertex 1, 4, 200,0,0
PokeSpriteVertex 1, 5, 300,0,0
PokeSpriteVertex 1, 6, 300,300,0
PokeSpriteVertex 1, 7, 200,300,0
PokeSpriteFaceVerts 1,1,4
PokeSpriteface 1,1,0,4,0,0,$ffff00
PokeSpriteface 1,1,1,5,1,0,$ffff00
PokeSpriteface 1,1,2,6,1,1,$ffffff
PokeSpriteface 1,1,3,7,0,1,$ff00ff
max=100
For lp=0 to max
; if lp<(Max/2)
; me= MakePlainSprite(3,rnd(800),rnd(600),32)
; else
me= MakeParticleSprite(2,rnd(800),rnd(600),rndrange(10,25))
facecount=facecount+(getSpriteFaceQuantity(me)*2)
; endif
;
positionspritexyz me,rndrange(-1000,1000),_
rndrange(-1000,1000),_
rndrange(150,10000)
SpriteRotationMode me,0
; SpriteHandle me,0,0
next
terrain= MakePlainSprite(3,rnd(800),rnd(600),50)
SpriteRotationMode terrain,1
positionspritexyz terrain,0,2000,10500
spritehandle terrain,0,0
turnspritexyz terrain,30,0,0
TerrainFacecount=getSpriteFaceQuantity(Terrain)
facecount=(facecount)+getSpriteFaceQuantity(Terrain)
Do
Cls 200
; tileImage 1,ix,-100,false
ix=mod(ix+1,getimagewidth(1))
For lp=1 to max+2
TurnSpriteXYZ lp,1.11*(lp/(1.0*max)),0,1
z#=GetSpriteZ(lp)-100
if z#<150
z#=10000
endif
PositionspriteZ lp,z#
next
turnspriteXyz terrain,0,0.1,0
; DrawOrderedSprites
; drawallsprites
DrawPerspectiveSprites Camera
ink $ffffff
; Scalesprite 1,1+cos(angle#)
if LeftKey() Then Camera.Pos.X=Camera.Pos.X-10
if RightKey() Then Camera.Pos.X=Camera.Pos.X+10
setcursor 0,0
f=fps()
print f
angle#=angle#+1
; print Screen3dstate()
print FaceCount
print FaceCount*f
print TerrainFacecount
; print getspritex(1)
; print getspritey(1)
print Camera.pos.x
print Camera.pos.y
print Camera.Projection.x
print Camera.Projection.y
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2+16
SpriteVertexQuantity thisSprite,(Points)*4
SpriteFaceQuantity thisSprite,(Points)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Psub SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset+lp,X#,y#,z#
Rotation=wrapangle(Rotation,90)
next
EndPsub
Psub SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndPsub
Function MakePlainSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2
SpriteTransparent ThisSprite,on
turnspritexyz thissprite,00,00,00
Points2=(points+1)
Dim Matrix#(POints2,points2)
RadomizeHeightMap(Matrix#(),15000)
SmoothHeightMap(Matrix#(),3)
SpriteVertexQuantity thisSprite,(Points2*POints2)
SpriteFaceQuantity thisSprite,(Points2*Points2)*2
Size=1024
HandleX#=-(((points+1.0)/2.0)*size)
HandleZ#=-(((points+1.0)/2.0)*size)
; init vertex
for Ylp=0 to Points
Zpos#=ylp*Size
for Xlp=0 to Points
Xpos#=Xlp*Size
ThisVertex=(Ylp*(points+1))+xlp
ypos#=Matrix#(xlp,ylp)*-1
PokeSpriteVertex ThisSprite,ThisVertex,Xpos#+HandleX#,2000+Ypos#,Zpos#+HandleZ#
next
next
ThisColour=rgb(255,255,255)
; init faces (UV points U=X in texture space, V = Y in texture space)
TUstep#=1.0/(points+1)
Tvstep#=1.0/(points+1)
For Ylp=0 to points-1
For Xlp=0 to points-1
CurrentVertexRow =(Ylp*(points+1))+Xlp
NextVertexRow =CurrentVertexRow+(points+1)
PokeSpriteFaceVerts ThisSprite,ThisFace,3
u1#=Xlp*TUstep#
v1#=Ylp*TVstep#
u2#=(Xlp+1)*TUstep#
v2#=Ylp*TVstep#
u3#=(Xlp+1)*TUstep#
v3#=(Ylp+1)*TVstep#
u4#=(Xlp+0)*TUstep#
v4#=(Ylp+1)*TVstep#
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,CurrentVertexRow+1 ,u2#,v2#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow+1 ,u3#,v3#,ThisColour
inc ThisFace
PokeSpriteFaceVerts ThisSprite,ThisFace,3
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,NextVertexRow+1 ,u3#,v3#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow ,u4#,v4#,ThisColour
inc ThisFace
next
next
EndFUnction ThisSPrite
` *=----------------------------------------------------------------=*
` >> Randomize HeightMap Array <<
` *=----------------------------------------------------------------=*
Function RadomizeHeightMap(Matrix#(),Height)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
For Zlp=1 to Depth-2
For Xlp=1 to Width-2
Matrix#(xlp,zlp)=rnd#(Height)
next xlp
next zlp
Endfunction
` *=----------------------------------------------------------------=*
` >> Average Matrix Height <<
` *=----------------------------------------------------------------=*
Function SmoothHeightMap(Matrix#(),passes)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
Dim Temp_HeightMap_Yvalues#(Width,Depth)
For ThisPass=0 To Passes
CopyArray Matrix#(),Temp_HeightMap_Yvalues#()
For Zlp=1 to Depth-1
ZlpF=zlp-1
ZlpB=zlp+1
Width2=Width-1
For Xlp=1 to Width2
xlpL=Xlp-1
xlpR=Xlp+1
yb#=Temp_HeightMap_Yvalues#(xlp,zlp)
yt#=Temp_HeightMap_Yvalues#(xlp,zlpF)
yb#=Temp_HeightMap_Yvalues#(xlp,zlpB)
yl#=Temp_HeightMap_Yvalues#(xlpL,zlp)
yr#=Temp_HeightMap_Yvalues#(xlpR,zlp)
ytl#=Temp_HeightMap_Yvalues#(xlpL,zlpF)
ytr#=Temp_HeightMap_Yvalues#(xlpR,zlpF)
ybl#=Temp_HeightMap_Yvalues#(xlpL,zlpB)
ybr#=Temp_HeightMap_Yvalues#(xlpR,zlpB)
matrix#(xlp,zlp)=(yb#+yt#+yb#+yL#+yr#+ytl#+ytr#+ybl#+ybr#)/9
next xlp
next zlp
next ThisPass
unDim Temp_HeightMap_Yvalues#()
endfunction
Perspective Sprite Terrain #2 This shot is logical extension of the previous example and demos a more updated edition of rendering pipeline. This time we not only have the sprite terrain object we also have
3000 sprite entities objects as well. Giving us 100K polygons scene and approximately a 3 million polygon fill rate.
Type PBposition
x#,y#,z#
EndType
Type PBProjection
x#,y#
EndType
Type PBCamera
Status
pos as PBPosition
angle as PBPosition
scale as PBPosition
RotationMode
ProjectionMode
Projection as PBProjection
ViewPoint as PBPosition
EndType
Dim Camera as PBCamera Pointer
Camera = new PBCamera
Camera.pos.X=0
Camera.pos.y=0
Camera.pos.z=0
Camera.Projection.x=400.0
Camera.Projection.Y=300.0
Camera.ViewPoint.X=GetScreenWidth()/2.0
Camera.ViewPoint.y=GetScreenHeight()/2.0
load3Dimage "animal.jpg",1
load3Dimage "particle_white.bmp",2
load3Dimage "face.jpg",3
; load3Dimage "particle_white.bmp",3
; scaleimage 3,256,256,1
; scaleimage 2,1024,1024,1
scaleimage 3,2048,2048,1
CreateSprite 1
positionspritexyz 1,400,300,1000
SpriteDrawmode 1,2
SpriteImage 1,1
centerspritehandle 1
SpriteVertexQuantity 1,8
SpriteFaceQuantity 1,8
PokeSpriteVertex 1, 4, 200,0,0
PokeSpriteVertex 1, 5, 300,0,0
PokeSpriteVertex 1, 6, 300,300,0
PokeSpriteVertex 1, 7, 200,300,0
PokeSpriteFaceVerts 1,1,4
PokeSpriteface 1,1,0,4,0,0,$ffff00
PokeSpriteface 1,1,1,5,1,0,$ffff00
PokeSpriteface 1,1,2,6,1,1,$ffffff
PokeSpriteface 1,1,3,7,0,1,$ff00ff
max=3000
For lp=0 to max
me= MakeParticleSprite(2,rnd(800),rnd(600),rndrange(10,25))
facecount=facecount+(getSpriteFaceQuantity(me)*2)
positionspritexyz me,rndrange(-1000,1000),_
rndrange(-1000,1000),_
rndrange(150,10000)
SpriteRotationMode me,1
next
terrain= MakePlainSprite(3,rnd(800),rnd(600),25)
SpriteRotationMode terrain,1
positionspritexyz terrain,0,2000,20500
spritehandle terrain,0,0
turnspritexyz terrain,30,0,0
TerrainFacecount=getSpriteFaceQuantity(Terrain)
facecount=(facecount)+getSpriteFaceQuantity(Terrain)
Do
Cls rgb(30,40,140)
ix=mod(ix+1,getimagewidth(1))
For lp=1 to max+2
TurnSpriteXYZ lp,1.11*(lp/(1.0*max)),0,1
z#=GetSpriteZ(lp)-100
if z#<150
z#=10000
endif
PositionspriteZ lp,z#
next
TurnspriteXyz terrain,0,0.1,0
; DrawOrderedSprites
; drawallsprites
DrawPerspectiveSprites Camera
ink $ffffff
if LeftKey() Then Camera.Pos.X=Camera.Pos.X-10
if RightKey() Then Camera.Pos.X=Camera.Pos.X+10
if upKey() Then Camera.Pos.z=Camera.Pos.z+10
if downKey() Then Camera.Pos.z=Camera.Pos.z-10
setcursor 0,0
f=fps()
print f
angle#=angle#+1
print FaceCount
print FaceCount*f
print TerrainFacecount
print Camera.pos.x
print Camera.pos.y
print Camera.Projection.x
print Camera.Projection.y
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2+16
SpriteVertexQuantity thisSprite,(Points)*4
SpriteFaceQuantity thisSprite,(Points)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Psub SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset+lp,X#,y#,z#
Rotation=wrapangle(Rotation,90)
next
EndPsub
Psub SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndPsub
Function MakePlainSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2+8
SpriteTransparent ThisSprite,on
turnspritexyz thissprite,00,00,00
Points2=(points+1)
Dim Matrix#(POints2,points2)
RadomizeHeightMap(Matrix#(),15000)
SmoothHeightMap(Matrix#(),3)
SpriteVertexQuantity thisSprite,(Points2*POints2)
SpriteFaceQuantity thisSprite,(Points2*Points2)*2
Size=2048
HandleX#=-(((points+1.0)/2.0)*size)
HandleZ#=-(((points+1.0)/2.0)*size)
; init vertex
for Ylp=0 to Points
Zpos#=ylp*Size
for Xlp=0 to Points
Xpos#=Xlp*Size
ThisVertex=(Ylp*(points+1))+xlp
ypos#=Matrix#(xlp,ylp)*-1
PokeSpriteVertex ThisSprite,ThisVertex,Xpos#+HandleX#,2000+Ypos#,Zpos#+HandleZ#
next
next
ThisColour=rgb(255,255,255)
; init faces (UV points U=X in texture space, V = Y in texture space)
TUstep#=1.0/(points+1)
Tvstep#=1.0/(points+1)
For Ylp=0 to points-1
For Xlp=0 to points-1
CurrentVertexRow =(Ylp*(points+1))+Xlp
NextVertexRow =CurrentVertexRow+(points+1)
PokeSpriteFaceVerts ThisSprite,ThisFace,3
u1#=Xlp*TUstep#
v1#=Ylp*TVstep#
u2#=(Xlp+1)*TUstep#
v2#=Ylp*TVstep#
u3#=(Xlp+1)*TUstep#
v3#=(Ylp+1)*TVstep#
u4#=(Xlp+0)*TUstep#
v4#=(Ylp+1)*TVstep#
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,CurrentVertexRow+1 ,u2#,v2#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow+1 ,u3#,v3#,ThisColour
inc ThisFace
PokeSpriteFaceVerts ThisSprite,ThisFace,3
PokeSpriteface ThisSprite,ThisFace,0,CurrentVertexRow+0 ,u1#,v1#,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,NextVertexRow+1 ,u3#,v3#,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,NextVertexRow ,u4#,v4#,ThisColour
inc ThisFace
next
next
EndFUnction ThisSPrite
` *=----------------------------------------------------------------=*
` >> Randomize HeightMap Array <<
` *=----------------------------------------------------------------=*
Function RadomizeHeightMap(Matrix#(),Height)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
For Zlp=1 to Depth-2
For Xlp=1 to Width-2
Matrix#(xlp,zlp)=rnd#(Height)
next xlp
next zlp
Endfunction
` *=----------------------------------------------------------------=*
` >> Average Matrix Height <<
` *=----------------------------------------------------------------=*
Function SmoothHeightMap(Matrix#(),passes)
Width=getarrayelements(Matrix#(),1)
Depth=getarrayelements(Matrix#(),2)
Dim Temp_HeightMap_Yvalues#(Width,Depth)
For ThisPass=0 To Passes
CopyArray Matrix#(),Temp_HeightMap_Yvalues#()
For Zlp=1 to Depth-1
ZlpF=zlp-1
ZlpB=zlp+1
Width2=Width-1
For Xlp=1 to Width2
xlpL=Xlp-1
xlpR=Xlp+1
yb#=Temp_HeightMap_Yvalues#(xlp,zlp)
yt#=Temp_HeightMap_Yvalues#(xlp,zlpF)
yb#=Temp_HeightMap_Yvalues#(xlp,zlpB)
yl#=Temp_HeightMap_Yvalues#(xlpL,zlp)
yr#=Temp_HeightMap_Yvalues#(xlpR,zlp)
ytl#=Temp_HeightMap_Yvalues#(xlpL,zlpF)
ytr#=Temp_HeightMap_Yvalues#(xlpR,zlpF)
ybl#=Temp_HeightMap_Yvalues#(xlpL,zlpB)
ybr#=Temp_HeightMap_Yvalues#(xlpR,zlpB)
matrix#(xlp,zlp)=(yb#+yt#+yb#+yL#+yr#+ytl#+ytr#+ybl#+ybr#)/9
next xlp
next zlp
next ThisPass
unDim Temp_HeightMap_Yvalues#()
endfunction
Perspective Sprite Terrain #3 (3D version) This is another logical step forward from the previous demo. Except this time rather than viewing the sprite space down the Z axis (which can be Z rotated now also), we can view the sprites from any vantage point within 3d space. Which is a crude was of saying this gives now gives PB basic 3D support.
Just Pic
Particle Sprites This rather basic looking picture shows the introduction of the Particle manager. Currently the manager is only loosely attached to the sprite system. So loosely in fact the actual drawing/emitting functionality is hacked into draw sprite frame work. Obviously, that's just for test purposes however.
Particles Sprites will be attached to sprites face controls. You'll either init their behavior from built in emitter types or pass them a control structure where you'll set the required fields. Probably both, not sure yet. At the moment each particle has it's own position, speed, rotation, time, colour etc etc but that will expand over time.
In this picture we have 50 sprites each emitting a max of 250 particles.
Please Note: The particles are rendered as Dots here for demonstration purposes only.
Particle Sprites Cont In this shot we're still seeing the particles being rendered as circles&dots in this case, but the engine frame work in now embedded into PB. This means that the user can now create / add and update the particle sprites.
Type PBposition
x#,y#,z#
EndType
; -------------------------------------------------------------------------------
; >> PB Particle Structure <<
; -------------------------------------------------------------------------------
Type PB_Particle_Modifier
Mode
x#,y#,z#
Accel as PBPosition
Min as PBPosition
Max as PBPosition
endtype
Type PB_Particle
TypeID
FrameCounter
MaxFrameCounter
Pos as PBPosition
Speed as PB_Particle_Modifier
Force as PB_Particle_Modifier
Scale as PB_Particle_Modifier
Angle as PBPosition
Colour
EndType
Dim Part as PB_Particle POinter
Part = new PB_Particle
load3dimage "D:\Play_Basic\PlayBasic\Projects\GFX\ship.bmp",100
max=50
For lp=1 to max
Spr=lp
CreateParticleSprite lp,250
PositionSprite lp,rnd(800),rnd(600)
SpriteImage lp,100
SpriteHandle Spr,GetIMageWidth(100)/-2,GetImageHeight(100)*-0.78
PositionSpriteZ spr,10
SpriteDrawmode spr,2
next
Do
cls rgb(20,40,100)
Print Fps()
PositionSprite Spr,MouseX(),MouseY()
Part.FrameCounter=0
Part.MaxFrameCounter=100
Part.Pos.z=10
Part.Colour=rndRgb()
Lockbuffer
For lp=1 to Max
Xpos#=getSpriteX(lp)
Ypos#=getSpriteY(lp)
Part.Pos.x=Xpos#
Part.Pos.y=Ypos#
Angle#=GetSpriteAngle(lp)+70+Rnd(40)
Part.Speed.X=CosRadius(Angle#,2)
Part.Speed.Y=SinRadius(Angle#,2)
AddSpriteParticle lp,Part
UpdateSpriteParticles lp
turnSprite lp,0.1
next
unlockbuffer
DrawOrderedSprites
Sync
loop
Note: This code is presented as a sample only. While compatiblele with the PlayBasic V1.68h alpha, it's unlikely to work in future editions.
Particle Sprites Cont In this pair of shots you can see that particle->mesh creation has been implemented. Shot one has a single 1000 particle sprite, where shot #2 has 10 of them on screen.
Each particle has it's own local speed & force modifiers. but you'll also be able to set the size / UV mapping + rotation of each particle (2D&3D).
With rotation, the particle fragments can spin locally. This will make for some very interesting results. The down side of lots of contols is that Initializing particles becomes a little more complex, plus there's more overhead per particle. But it'll certainly be worth the effort.
;setfps 75
Type PBposition
x#,y#,z#
EndType
; -------------------------------------------------------------------------------
; >> PB Particle Structure <<
; -------------------------------------------------------------------------------
Type PB_Particle_Modifier
Mode
x#,y#,z#
Accel as PBPosition
Min as PBPosition
Max as PBPosition
endtype
Type PB_Particle
TypeID
FrameCounter
MaxFrameCounter
Pos as PBPosition
Speed as PB_Particle_Modifier
Force as PB_Particle_Modifier
Scale as PB_Particle_Modifier
Angle as PBPosition
Colour
EndType
Dim Part as PB_Particle POinter
Part = new PB_Particle
load3dimage "LENS03.JPG",100
scaleimage 100,32,32,1
max=10
Dim ColourTable(Max)
NumbOfParticles=1000
For lp=1 to max
Spr=lp
CreateParticleSprite lp,NumbOfParticles
PositionSprite lp,0,0 ;rnd(400),rnd(300)
SpriteImage lp,100 ;+(lp&1)
PositionSpriteZ spr,10
SpriteDrawmode spr,2+16
ColourTable(lp)=rndrgb()
SpriteFAceQuantity lp,NumbOfParticles ;+100
For ThisPart=0 to NumbOfParticles
SetFace(lp,ThisPart,ThisPart*4,rndrgb())
next thispart
next
Do
Cls rgb(20,40,60)
Print Fps()
For lp=1 to max
Edges=rndRange(5,10)
Part.FrameCounter =0
Part.MaxFrameCounter =200
Part.Pos.z =10
Part.Colour =ColourTable(lp)
AngleStep#=360.0/Edges
BaseAngle#=rnd(360) ;GetSpriteAngle(lp)+70+Rnd(40)
Part.Force.X =0.0
Part.Force.Y =0.0
Part.Force.Z =0.0
SetPos(Part.Force.Accel,0,0.015,0)
SetPos(Part.Force.Max,0,20,0)
SetPos(Part.Force.Min,0,0,0)
MaxSpeed#=15
Part.Speed.Min.X =-(MaxSpeed#/2)
Part.Speed.Min.Y =-MaxSpeed#
Part.Speed.Max.X =MaxSpeed#/2
Part.Speed.Max.Y =MaxSpeed#
For MakeParts=0 to Edges-1
Part.Colour=rndrgb()
angle#=rnd#(360)
Xpos#=mousex()
Ypos#=Mousey()
Part.Pos.x=Xpos#
Part.Pos.Y=Ypos#
Speed#=rndrange#(1,6)
Part.Speed.X=CosRadius(Angle#,Speed#)
Part.Speed.Y=SinRadius(Angle#,Speed#)
Angle2#=angle#+180
Speed2#=Speed#/Part.MaxFrameCounter
Part.Speed.Accel.X=CosRadius(Angle2#,Speed2#)
Part.Speed.Accel.Y=SinRadius(Angle2#,Speed2#)
AddSpriteParticle lp,Part
next
; circle GetSpriteX(lp),GetSpriteY(lp),50,0
UpdateSpriteParticles lp
next
DrawOrderedSprites
FaceCount=0
For lp=1 to Max
FaceCount=FaceCount+GetSpritefaceQuantity(lp)
next
print FaceCount
Sync
loop
Function SetPos(me as PBposition Pointer,x#,y#,z#)
me.x=x#
me.y=y#
me.z=z#
EndFunction
Psub SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndPsub
Note: This is sample code written for the current PB1.68h alpha, it's highly unlikely to the work in the future editions.
Particle Sprites Cont #4 This new shot shows that particles can be locally coloured, locally rotated (3D XYZ) and scaled. Since they have scaling, then we don't really need modifiers for the size. You'll have to init the scale/size of the particle though (otherwise you won't see it!). Particle size doesn't necessarily have to correspondent with the image dimensions however.
Rotating on all 3 Axis
Here's another pic, this time I'm messing around with Scale + Rotation + Speed + Force modifiers.
Particles in 3D These shots view the particle sprite in 3D space. The first shot is taken from deep inside the volume and the second is from far outside of it.
Particle Sprites Cont - UV Mapping In this shot you can see that each individual particle can be UV mapped. You could use this to store various textures on the same surface, or when exploding an image. Here it's just randomly assigning each face some UV coords though.
Particles + Terrain
Zbuffer Support The addition of the Z buffering makes the DrawPerspectiveSprites render Mode into a mini 3D engine. Z buffering allows faces to intersect each other. This means that when your card renders each pixel of a polygon, it calculates the Z at this pixel then selectively (if it's Z is nearer to the camera) draws it. So polygons will be in the correct order, regardless of depth.
In these simple pictures you can see the previous sprite terrain/particle scene drawn using the zbuffer.
PB 1.70 Back working on PB1.70 again. So far i've just been adding the new features that were added during the recent PB1.63 refresh. Here's the the old sprite rotation demo, 200 rotating sprites, scrolling backdrop. 1000 + fps. And it's not even remotely opt'd yet...
If thats not optimized, that some scary kinda fast...what system are you using?
anyways, holy sh'mokes...
Deep Thought :)
PB1.70a Mapping Test Here's the first look see (for what's it worth) of the rebuilt mapping engine. While I could I have 'modified' the original edition of the library, it really needed to be re-written around the new image system. Which is the current little task. Initially, I was expecting the first slapped together version it to be slower than the older mature version of the library found PB1.63 for example. But interestingly the code bellow is running 80fps quicker in PB1.70a than PB1.63n. Which is more a collective improvement than just the map rendering thing I think.
CreateMap 1,176
BlockWidth=32
BlockHeight=32
TileX=800/BlockWidth
TileY=(600/Blockheight)+1
CreateLevel 1,50,tileX,Tiley
NumbOfBlocks=TileX*TileY
CreateMapGFX 1,BlockWidth,BlockHeight,NumbOfBlocks,$0
LoadImage "D:\Play_Basic\ScreenShots\PB_ForestBlast_V012.JPG",1
RenderToImage 1
Ypos=0
Xpos=0
for lp=0 to NumbOfBlocks-1
GetMapBlk 1,lp,Xpos,Ypos
Xpos=Xpos+BlockWidth
if Xpos>=GetSurfaceWidth()
Xpos=0
Ypos=Ypos+Blockheight
endif
next
RenderToImage 0
Block=0
For ylp=0 to GetLevelHeight(1,50)-1
For Xlp=0 to GetLevelWidth(1,50)-1
PokeLevelTile 1,50,Xlp,ylp,block
inc block
next
next
Do
Cls 255
t=timer()
DrawMap 1,50,0,0
tt#=tt#+(timer()-t)
inc frames
TileXpos=(mousex()/GetMapBlockWidth(1))
TileYpos=(mousey()/GetMapBlockHeight(1))
pokeleveltile 1,50,TileXpos,TileYpos,TileXpos ;rnd(100)
setcursor 0,0
print fps()
print TT#/frames
print GetMapBlockQuantity(1)
Print "status:"+str$(GetLevelstatus(1,50))
Print GetLevelWidth(1,50)
Print GetLevelHeight(1,50)
Print GetMapLevels(1)
Print GetMapBlockStatus(1)
Print GetMapBlockWidth(1)
Print GetMapBlockHeight(1)
Print GetMapBlockQuantity(1)
Print GetMapMaskColour(1)
print TileXpos
print TileYpos
Sync
loop
impressive
PB V1.70b Mapping Test Slowly ticking off the conversion of the various commands/functions in the new mapping library. As such more old demos are running in PB1.70 now. Bellow a mapping test from around 2004 which uses the Xenon 2000 art work (again :) ). With 2 layers it's about 50->60 fps faster than PB1.63n.
PB 1.70e - Even faster Mapping The replacement mapping library is basically finished in PB1.70e. So everything should be working again from Map Animation, Block importation through to the level helper commands. While the first rewrite of library was approximately 25% faster than the old library in PB1.63e and bellow, I still had a few tricks up my sleeve optimization wise. :) Which have been implemented into PB1.70e level render. Which in turn give us approximately another 25% performance improvement. Making the new engine around twice as fast as it was.
The following pics are the previous examples running in the current update. Both demos are around 90->100fps faster than the previous test. If you run in full screen exclusive it's even quicker. For the example the Xenon test which runs around the 390->400fps in windowed mode, clocks around 480->490fps in full screen exclusive.
PB 1.70f - Shape Rotation This piccy is very early test of the revised shape library for PB1.70f. In the pic it's rotating & drawing 50,000 point the shape in dot mode.
Shape Rotation Modes Shapes now support both 2D & 3D rotation modes. Here's the same demo above running with 3D rotation applied.
Speed wise the new version is about 60->70fps faster than
PlayBasic V1.63n retail
vertexcount=50000
EdgeCount=VertexCount
CreateShape 10,vertexcount,EdgeCount
w=GetSCreenWidth()
h=GetSCreenHeight()
w2=w/2
h2=h/2
for lp=0 to vertexcount-1
x=rnd(w)
y=rnd(h)
SetShapeVertex 10,lp,x-w2,y-h2
SetShapeEdge 10,lp,lp,lp
next
Do
Cls 0
drawshape 10,GetSCreenWidth()/2,GetSCreenHeight()/2,0
print fps()
Sync
loop
Note: Rotation Mode and rotation angles are actually bumped inside the library at the moment.
PB 170 Shape Particle Demos Here's the old shape particles demo (in your example pack under projects/demo/shapeparticles) running in Pb1.70. This one's around 40fps faster than PB1.63n.
Particle Sprinkler This is the sprinkler demo (see projects/demos/shapeparticlesprinkler) running in PB1.70f, and it's another 35 fps faster than PB1.63n retail.
PB1.70g - Closest Point To Shape Have pretty much re-written 90% of the shape library in the day few days. It's not really optimized, but it's far clearer. Anyway the following picture is of an internal function that been exposed. What is does is lets you query a shape for the closest point upon and edge within a range. Not pretty to look at, but handy :)
MyShape3=NewConvexShape(100,10)
MyShape4=NewConvexShape(70,5)
MergeShape MyShape3,MyShape4
Do
Cls RGB(0,0,0)
; CreateShape 20,50,50
RotateShape myshape4,angle#,2
ShapeXpos#=400
ShapeYpos#=300
mx=mousex()
my=mousey()
Radius=100
if ClosestPointOnShape(mx,my,Radius,MyShape4,ShapeXpos#,ShapeYpos#)
x1=GetIntersectX#(0)
y1=GetIntersectY#(0)
Circlec x1,y1,50,true,rgb(100,200,50)
ink rgb(255,0,0)
print "HITSHAPE"
Else
Ink RGB(255,255,255)
print "Missed Shape"
EndIF
DrawShape MyShape4,ShapeXpos#,ShapeYpos#,2
CircleC mx,my,Radius,false,rgb(200,100,200)
ink 255
angle#=WrapAngle(angle#,0.01)
print fps()
Sync
loop
PB1.70g Pretty much completed the shape library rewrite and are just hooking up a few extra commands. Which so far is limited to the rotation mode and XYZ rotation angles.
MyShape3=NewConvexShape(100,10)
MyShape4=NewConvexShape(70,5)
MergeShape MyShape3,MyShape4
Do
Cls RGB(0,0,0)
RotateShape myshape4,angle#,2
ShapeXpos#=400
ShapeYpos#=300
mx=mousex()
my=mousey()
if Scaler#=<0 then Scaler#=1
if LeftMousebutton()
Scaler#=scaler#+0.01
endif
if RightMousebutton()
Scaler#=scaler#-0.01
endif
shaperotationmode myShape3,1
rotateShapeXYZ Myshape3,Anglex#,angley#,anglez#
ScaleShape myShape3,scaler#
DRawShape MyShape3,mx,my,2
print "Rotationmode:"+Str$(Getshaperotationmode(myShape3))
print "Rotationmode:"+Str$(Getshaperotationmode(myShape4))
result=ShapeHitShape(MySHape3,mx,my,MyShape4,ShapeXpos#,ShapeYpos#)
if result
Ink rgb(255,0,0)
print "HITSHAPE"
Else
Ink RGB(255,255,255)
print "Missed Shape"
EndIF
DrawShape MyShape4,ShapeXpos#,ShapeYpos#,2
; CircleC mx,my,Radius,false,rgb(200,100,200)
ink 255
angle#=WrapAngle(angle#,0.01)
anglex#=WrapAngle(anglex#,0.11)
angley#=WrapAngle(angley#,0.22)
anglez#=WrapAngle(anglez#,0.23)
print fps()
Sync
loop
Machine Code Execution Experiment The following picture is taken from a recent dynamic recompilation
experiment - I want to stress that the result at this point, is purely for
curiously sake and should not be considered as a coming feature in the short term!
In this picture the code is doing a brute force fill (PB sample code bellow). Where it's drawing a full screen of individually coloured pixels. Unlike a normal PlayBasic program, this sample is not running the entire filler code through PlayBasic current VM#1 runtime, rather it generates a native x86 Machine Code equivalent and executes that.
; This is the what the fill loop is doing
ThisIMage=0
rendertoimage Thisimage
lockbuffer
t=timer()
imageptr=GetIMagePtr(Thisimage)
imagepitch=GetIMagePitch(Thisimage)
CodePtr=GetBankPtr(CodeBank)
For ylp=0 to GetImageHeight(Thisimage)-1
RowAddress=IMagePtr+(ylp*ImagePitch)
for Address=RowAddress to RowAddress+((getimagewidth(ThisImage)-1) * 4) step 4
Pokeint Address,Colour
Colour=Colour+$11
next
next
tt2#=tt2#+(timer()-t)
unlockbuffer
Speed wise, there's a obviously going to be a world of difference. The native machine code version can fill the 800*600*4 screen (1.9meg of data) in 2->3 milliseconds. The runtime equivalent struggles at 150ms for the same task. This is a little
misleading as the VM#1 runtime sees the above inner loop code (above) is low priority opcodes. So execution of that particular loop is much slower than just using dot fill of the screen. Which can be done 3 times faster than the poke solution above.. Even so, the machine code test is approximately 15 ->20times quicker than the fastest VM friendly loop in the runtime.
PB1.70h Here's another newly exposed command
QuadHitShape - It allows you detect intersections between a convex 4 sided polygon (a quad) and a shape. Previously it was only a part of the math engine.
MyShape3=NewConvexShape(100,10)
MyShape4=NewConvexShape(70,5)
MergeShape MyShape3,MyShape4
type Tpoint
x#,y#,z#
endtype
Dim Points(4) as tpoint
Do
Cls RGB(0,0,0)
x=GetSCreenWidth()/2
y=GetSCreenHeight()/2
RotateShape myshape4,angle#,2
ShapeXpos#=400
ShapeYpos#=300
mx=mousex()
my=mousey()
Baseangle#=wrapangle(baseangle#,0.01)
for lp=0 to 3
angle2#=wrapangle(baseangle#,90*lp)
Points(lp).x=mx+(CosRadius(Angle2#,100*scaler#))
Points(lp).y=my+(SinRadius(Angle2#,100*scaler#))
next
for lp=0 to 3
lp2=lp+1
if lp=3 then lp2=0
line Points(lp).x,Points(lp).y,Points(lp2).x,Points(lp2).y
next
if Scaler#=<0 then Scaler#=1
if LeftMousebutton()
Scaler#=scaler#+0.01
endif
if RightMousebutton()
Scaler#=scaler#-0.01
endif
result=QuadHitShape( Points(0).x,Points(0).y,_
Points(1).x,Points(1).y,_
Points(2).x,Points(2).y,_
Points(3).x,Points(3).y,_
MyShape4,ShapeXpos#,ShapeYpos#)
if result
Ink rgb(255,0,0)
print "HITSHAPE"
Else
Ink RGB(255,255,255)
print "Missed Shape"
EndIF
DrawShape MyShape4,ShapeXpos#,ShapeYpos#,2
ink 255
angle#=WrapAngle(angle#,0.01)
anglex#=WrapAngle(anglex#,0.11)
angley#=WrapAngle(angley#,0.22)
anglez#=WrapAngle(anglez#,0.23)
print fps()
Sync
loop
PB1.70 Draw Mode Support in Light + Phong Image This is a small change in PB1.70. Now if you use Light & Phong image now use the current inkmode. So it can blend the lit pixel with the existing pixel.
Width=800
Height=600
srcimg=loadnewimage("D:\Play_Basic\ScreenShots\PB_ForestBlast_V012.JPG")
preparefximage srcimg
img=NewfXImage(Width,height)
FallOffRate=1.5
PhongColour=RndRGB()
For Brightness=0 to 2256 step 8
rendertoimage img
Cls rgb(255,255,255)
copyrect srcimg,0,0,width,height,img,0,0
inkmode 1+128
; LightImage Img, Width/2, Height/2, Brightness, FallOffRate
renderPhongImage img,width/2,height/2,PhongColour,brightness,falloffrate
inkmode 1
if Spacekey() then PhongColour=RndRGB()
rendertoscreen
cls 0
drawimage img,00,00,false
print Brightness
Sync
next
print "done"
Waitkey
Sprite Collision - Point Hit Sprite Point hit sprite now support entity sprites..
Create3DImage 2,32,32
width=GetImageWidth(2)
Height=GetImageHeight(2)
Cls rgb(22,100,0)
box 0,0,width-1,height-1,false
GetIMage 2,0,0,Width,Height
me= MakeParticleSprite(2,rndrange(100,700),rndrange(100,500),5)
;rndrange(10,20))
spritecollisiondebug me,true
spritecollisionMode me,1
;Setfps 75
Do
Cls rgb(100,200,300)
DrawAllSprites
mx=mousex()
my=mousey()
Circle mx,my,5,false
result=PointHitSprite(mx,my,me)
print result
if result
print "Point Hit Face"
else
print "Missed"
endif
; boxc 0,0,50,20,true,rgb(0,0,0)
print fps()
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDRawMOde ThisSprite, 2 ;+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Ray Hit Sprite Slowing converting more of the collision frame work, this picture show that you can now run ray intersection upon
Entity sprites.
Create3DImage 2,32,32
width=GetImageWidth(2)
Height=GetImageHeight(2)
Cls rgb(22,100,0)
box 0,0,width-1,height-1,false
GetIMage 2,0,0,Width,Height
me= MakeParticleSprite(2,rndrange(100,700),rndrange(100,500),5)
spritecollisiondebug me,true
spritecollisionMode me,1
Do
Cls rgb(100,200,300)
turnsprite me,0.1
DrawAllSprites
mx=mousex()
my=mousey()
if Mousebutton()=1
RayX1=mx
RayY1=my
endif
line rayx1,rayy1,mx,my
circle Rayx1,rayy1,3,true
result=RayHitSprite(rayx1,rayy1,mx,my,me)
if result
print "Line Hit Sprite"
circle GetIntersectx#(0),GetIntersecty#(0),5,true
ix=GetIntersectx#(0)
iy=GetIntersecty#(0)
ix2=ix+(GetNormalx#(0)*20)
iy2=iy+(GetNormaly#(0)*20)
line ix,iy,ix2,iy2
else
print "Line Missed Sprite"
endif
print fps()
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDRawMOde ThisSprite, 2 ;+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFUnction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Rect Hit Sprite This one now support entity sprites also.
Create3DImage 2,32,32
width=GetImageWidth(2)
Height=GetImageHeight(2)
Cls rgb(22,100,0)
GetIMage 2,0,0,Width,Height
me= MakeParticleSprite(2,rndrange(100,700),rndrange(100,500),5)
Spritecollisiondebug me,true
SpriteCollisionRadius me,100
Do
Cls rgb(100,200,300)
Turnsprite Me,0.1
DrawAllSprites
mx=mousex()
my=mousey()
if Mousebutton()=1
RayX1=mx
RayY1=my
endif
print "Mode:"+Str$(getSpriteCollisionMode(me))
result=RectHitSprite(rayx1,rayy1,mx,my,me)
box rayx1,rayy1,mx,my,false
if result
print "Rect Hit Sprite"
boxc rayx1,rayy1,mx,my,false,$ff0000
else
print "Rect Missed Sprite"
endif
If EnterKey()
r=GetspritecollisionMode(me)+1
if r>6 then r=0
spritecollisionMode me,r
flushkeys
EndIf
print fps()
Sync
loop
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2 ;+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFunction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Polygon Hit Sprite Quad polygon now supports entity sprites also. This pretty much completes the rewrite of the vector side of the collision engine (code wise), just a matter of hooking stuff back up and culling some any redundant code now.
Create3DImage 2,32,32
width=GetImageWidth(2)
Height=GetImageHeight(2)
Cls rgb(22,100,0)
GetIMage 2,0,0,Width,Height
me= MakeParticleSprite(2,rndrange(100,300),rndrange(100,500),5)
Spritecollisiondebug me,true
SpriteCollisionRadius me,100
Type Vert
X#,y#
endtype
Dim POly(4) as Vert
Do
Cls rgb(100,200,300)
Turnsprite Me,0.1
DrawAllSprites
mx=mousex()
my=mousey()
print "Mode:"+Str$(getSpriteCollisionMode(me))
if mousebutton() then Scaler#=Scaler#+0.01
if Scaler#=0 then Scaler#=0.5
if Scaler#>10 then Scaler#=0.5
For lp=0 to 3
Angle2#=wrapangle(Angle#,(lp*90))
Poly(lp).x=(mx+Cosradius(angle2#,50*Scaler#))
Poly(lp).y=(my+Sinradius(angle2#,50*Scaler#))
next
Angle#=wrapangle(Angle#,0.1)
result=QuadHitSprite(Poly(0).x,Poly(0).y,_
Poly(1).x,Poly(1).y,_
Poly(2).x,Poly(2).y,_
Poly(3).x,Poly(3).y,_
me)
if result
print "Quad Hit Sprite"
HitColour=rgb(255,0,0)
else
HitColour=rgb(255,255,255)
print "Quad Missed Sprite"
endif
DRawPoly(HitColour)
If EnterKey()
r=GetspritecollisionMode(me)+1
if r>6 then r=0
spritecollisionMode me,r
flushkeys
EndIf
print fps()
Sync
loop
Function DRawPoly(HitColour)
For lp=0 to 3
lp2=(lp+1) and 3
linec Poly(lp).x,Poly(lp).y,Poly(lp2).x,Poly(lp2).y,HitColour
next
EndFUnction
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2 ;+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFunction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Sprites OverLap In this demo we're detecting overlaps between two entity level sprites. With this addition, this almost restores all of the vector level sprite collision support from PB1.63. Still a few tidbits left to do before updating the Pixel Perfect stuff. But it won't be too long now :)
Create3DImage 2,32,32
width=GetImageWidth(2)
Height=GetImageHeight(2)
Cls rgb(22,100,0)
GetIMage 2,0,0,Width,Height
me= MakeParticleSprite(2,rndrange(100,300),rndrange(100,500),5)
Spritecollisiondebug me,true
SpriteCollisionRadius me,100
you= MakeParticleSprite(2,rndrange(200,600),rndrange(100,500),7)
Spritecollisiondebug you,true
SpriteCollisionRadius you,200
Type Vert
X#,y#
endtype
Dim POly(4) as Vert
Do
Cls rgb(100,200,300)
mx=mousex()
my=mousey()
positionsprite me,mx,my
Scalesprite me,scaler#
Turnsprite Me,0.1
DrawAllSprites
mode=getSpriteCollisionMode(me)
print " Src Mode:"+Str$(mode)+" "+CollName(Mode)
mode=getSpriteCollisionMode(you)
print "Dest Mode:"+Str$(mode)+" "+CollName(Mode)
if mousebutton() then Scaler#=Scaler#+0.01
if Scaler#=0 then Scaler#=0.5
if Scaler#>10 then Scaler#=0.5
result=spritesoverlap(Me,you)
if result
print "Sprites Overlap"
HitColour=rgb(255,0,0)
else
HitColour=rgb(255,255,255)
print "Sprites Don't OverLap"
endif
k$=lower$(inkey$())
If k$="m"
DumpSpriteMode(me)
flushkeys
EndIf
If k$="y"
DumpSpriteMode(you)
flushkeys
EndIf
print fps()
Sync
loop
Function DumpSpriteMode(ThisSprite)
r=GetspritecollisionMode(ThisSprite)+1
if r>6 then r=0
spritecollisionMode ThisSprite,r
EndFunction
Function MakeParticleSprite(ThisIMage,Xpos#,Ypos#,points)
ThisSprite=NewSprite(Xpos#,Ypos#,ThisIMage)
SpriteDrawMode ThisSprite, 2 ;+16
SpriteVertexQuantity thisSprite,(Points+1)*4
SpriteFaceQuantity thisSprite,(Points+1)
angleStep#=360.0/points
size=32
For lp=0 to points-1
angle#=wrapangle(angle#,anglestep#)
Radius#=100
SetVerts(ThisSprite,VertexOffset,Angle#,Radius#,Size,wrapangle(angle#,-45))
SetFace(ThisSprite,ThisFace,VertexOffset,RndRgb())
VertexOffset=VertexOffset+4
inc thisface
next
EndFunction ThisSPrite
Function SetVerts(ThisSprite,VertexOffset,Angle#,Radius,Size,Rotation)
CenterX#=CosNewValue(0,angle#,Radius)
CenterY#=SinNewValue(0,angle#,Radius)
For lp=0 to 3
X#=CosNewValue(CenterX#,Rotation,Size)
Y#=SinNewValue(CenterY#,Rotation,Size)
PokeSpriteVertex ThisSprite,VertexOffset,X#,y#,z#
Rotation=wrapangle(Rotation,90)
inc VertexOffset
next
EndFunction
Function SetFace(ThisSprite,ThisFace,VertexOffset,ThisColour)
PokeSpriteFaceVerts ThisSprite,ThisFace,4
PokeSpriteface ThisSprite,ThisFace,0,VertexOffset+0,0,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,1,VertexOffset+1,1,0,ThisColour
PokeSpriteface ThisSprite,ThisFace,2,VertexOffset+2,1,1,ThisColour
PokeSpriteface ThisSprite,ThisFace,3,VertexOffset+3,0,1,ThisColour
EndFunction
Function CollName(Mode)
Select mode
case 0 : name$="Rect"
case 1 : name$="Mesh"
case 2 : name$="Circle"
case 3 : name$="Shape"
case 4 : name$="Slide"
case 5 : name$="Sticky"
case 6 : name$="Pixel"
endselect
EndFunction name$
PB1.70k CircleHitSprite (ShapeMode) Restored most of the shape mode vector collision methods today. With any luck, I might be able to finish those all today..
For example code See Projects\Sprites\Collision folder.
PB1.70k QuadHitSprite (ShapeMode) Well, it's just about the end of another long day and Beta K is moving along nicely. Haven't got all of the vector collision done. Found a few missing tidbits that needed to be replaced, due to changing to the mesh library. Probably should have documented how the original version worked at the time :)
The pic is just one of the sprite collision examples. (from your example pack) About 50% of them are working as per PB1.63 now.
PB1.70k ShapeHitSprite (ShapeMode) Shape Hit Sprite is working again.
Video Feedback Here's another video feedback variation in PB1.70
LoadFont "Arial",1,75,0
Surf1=New3Dimage(GetScreenWidth(),GetScreenHeight())
CurrentCol =RndRgb()
NextCol =RndRgb()
Setfps 60
Do
sw=GetScreenWidth()/2
sh=GetScreenHeight()/2
scale#=1.7
angle#=wrapangle(angle#,0.11)
DRawRotatedIMage Surf1,sw,sh,angle#,scale#,scale#,sw*-1,sh*-1,false
CopyRect 0,0,0,GetScreenWidth(),GetSCreenHeight(),surf1,0,0
DRawAlphaIMage Surf1,1,1,0.55,true
ink rgbalphablend(CurrentCol,NextCol,Blend)
CenterText mousex(),mousey(),"PlayBasic V1.70"
inc blend
if blend>100
blend=0
CurrentCol=NextCol
NextCol=RndRgb()
endif
CopyRect 0,0,0,GetScreenWidth(),GetSCreenHeight(),surf1,0,0
Sync
loop
PB1.70l PointHitSpritePixels (PixelPerfectMode) In 1.70L i'm slowly restoring the pixel perfect sprite collision modes. The main change is that now support entity (mesh based) sprites. The following pictures are just taken from PointHitSpritePixels demo (See projects\Sprites\Collision) from the examples pack however. There's two shots in the pic A the point is inside the sprite but missing the pixels, and in the pic B the point is hitting the pixels.. Although it's a little hard to see. But ya get that :)
PB170l PointHitSpritePixels 1500 Rotating Scaling sprites Here's an example of running the new PointHitSpritePixels function on a 1500 sprite scene.
; Load a Ship image and prepare it for 3D (rotation)
Load3DImage "..\..\..\..\gfx\ship.bmp",1
rgbmaskimage 1,$ffffff
; get the images width + height
w=GetImageWidth(1)
h=GetImageHeight(1)
; Set the Max number of sprites in this test
max=1500
Dim Sprites(MAx)
For lp=1 To max
; create a new sprite, and give it a random X & Y position
Spr2 =NewSprite(Rnd(800),Rnd(600),1)
; set the sprites drawmode to rotated (mode 2)
SpriteDrawMode spr2,2
; Turn Sprite Collision OFF - as were manually checking for collisions bellow
SpriteCollision spr2, off
; center sprite handle
CenterSpriteHandle spr2
; randomly scale the sprite
ScaleSprite Spr2,RndRange#(1,2)
Sprites(lp)=spr2
Next
; Start of program Main loop
Do
; clear the screen to RGB colour 100,100,100
Cls RGB(100,100,100)
; Get the Mouse Position
mX=MouseX()-1
mY=MouseY()-1
; run Through and check if this point is over a sprite
For lp=1 To max
; get the sprite index
Spr2=Sprites(lp)
Turnsprite Spr2,(lp*0.05)
; reset this sprites draw mode to mode 2 - rotated
SpriteDrawMode spr2,2
; Check if this point hits this sprites pixels
If PointHitSpritePixels(mx,my,spr2,0.5)
; set the sprite to a red colour
pokeSpritefacergb Spr2,0,0,$ff0000
pokeSpritefacergb Spr2,0,1,$ff0000
pokeSpritefacergb Spr2,0,2,$ff0000
pokeSpritefacergb Spr2,0,3,$ff0000
else
pokeSpritefacergb Spr2,0,0,$ffffff
pokeSpritefacergb Spr2,0,1,$ffffff
pokeSpritefacergb Spr2,0,2,$ffffff
pokeSpritefacergb Spr2,0,3,$ffffff
EndIf
Next
; draw all the sprites
DrawAllSprites
; draw the mouse position
boxc mx,my,mx+2,my+2,true,rndrgb()
s$=str$(fps())
boxc xpos,ypos,xpos+GetTExtWidth(s$),ypos+GetTExtHeight(s$),true,0
Text xpos,ypos,s$
; refresh the display
Sync
; loop back to the DO statement and continue this program
Loop
PB170l Running RectHitSpritePixels 1500 Rotating Scaling sprites This example of running RectHitSpritePixels function on a 1500 sprite scene.
; -----------------------------------------------------------
; >>>>> RECT Hit Sprite Pixels <<<<<<<
; -----------------------------------------------------------
; Load a Ship image and prepare it for FX (rotation)
Load3DImage "..\..\..\..\gfx\ship.bmp",1
rgbmaskimage 1,$ffffff
; get the images width + height
w=GetImageWidth(1)
h=GetImageHeight(1)
; Set the Max number of sprites in this test
max=1500
Dim Sprites(MAx)
For lp=1 To max
; create a new sprite, and give it a random X & Y position
Spr2 =NewSprite(Rnd(800),Rnd(600),1)
; set the sprites drawmode to rotated (mode 2)
SpriteDrawMode spr2,2
; Turn Sprite Collision OFF - as were manually checking for collisions bellow
SpriteCollision spr2, off
;l SpriteCollisionMode spr2, 6
; SpriteCollisionDebug spr2,true
; center sprite handle
CenterSpriteHandle spr2
; randomly scale the sprite
ScaleSprite Spr2,RndRange#(1,2)
Sprites(lp)=spr2
Next
; Start of program Main loop
Do
; clear the screen to RGB colour 100,100,100
Cls RGB(100,100,100)
; Get the Mouse Position
mX=MouseX()
mY=MouseY()
Width=100
Height=200
rectx1=mx-(width/2)
recty1=my-(height/2)
rectx2=mx+(width/2)
recty2=my+(height/2)
; run Through and check if this point is over a sprite
For lp=1 To max
; get the sprite index
Spr2=Sprites(lp)
Turnsprite Spr2,(lp*0.05)
; Check if this point hits this sprites pixels
If RectHitSpritePixels(rectx1,recty1,rectx2,recty2,spr2,1)
pokeSpritefacergb Spr2,0,0,$ff0000
pokeSpritefacergb Spr2,0,1,$ff0000
pokeSpritefacergb Spr2,0,2,$ff0000
pokeSpritefacergb Spr2,0,3,$ff0000
else
pokeSpritefacergb Spr2,0,0,$ffffff
pokeSpritefacergb Spr2,0,1,$ffffff
pokeSpritefacergb Spr2,0,2,$ffffff
pokeSpritefacergb Spr2,0,3,$ffffff
EndIf
Next
; draw all the sprites
DrawAllSprites
; draw the mouse position
boxc rectx1,recty1,rectx2,recty2,false,rgb(200,0,200)
s$=str$(fps())
boxc xpos,ypos,xpos+GetTExtWidth(s$),ypos+GetTExtHeight(s$),true,0
Text xpos,ypos,s$
; refresh the display
Sync
; loop back to the DO statement and continue this program
Loop
PB170l Running EllipseHitSpritePixels 1500 Rotating Scaling sprites and here's the ellipse version.
PB170l LineHitSpritePixels This example is running the lineHitSpritePixels function on a 1500 Rotating Scaling sprites.
; -----------------------------------------------------------
; >>>>> LINE Hit Sprite Pixels <<<<<<<
; -----------------------------------------------------------
; Load a Ship image and prepare it for FX (rotation)
Load3DImage "..\..\..\..\gfx\ship.bmp",1
rgbmaskimage 1,$ffffff
; get the images width + height
w=GetImageWidth(1)
h=GetImageHeight(1)
; Set the Max number of sprites in this test
max=1500
Dim Sprites(MAx)
For lp=1 To max
; create a new sprite, and give it a random X & Y position
Spr2 =NewSprite(Rnd(800),Rnd(600),1)
; set the sprites drawmode to rotated (mode 2)
SpriteDrawMode spr2,2
; Turn Sprite Collision OFF - as were manually checking for collisions bellow
SpriteCollision spr2, off
; SpriteCollisionMode spr2, 6
; SpriteCollisionDebug spr2,true
; center sprite handle
CenterSpriteHandle spr2
; randomly scale the sprite
ScaleSprite Spr2,RndRange#(1,2)
Sprites(lp)=spr2
Next
Linex1=rnd(800)
Liney1=rnd(600)
Linex2=rnd(800)
Liney2=rnd(600)
; Start of program Main loop
Do
; clear the screen to RGB colour 100,100,100
Cls RGB(100,100,100)
; Get the Mouse Position
mX=MouseX()
mY=MouseY()
Width=100
Height=200
if mousebutton()=1
Linex1=mousex()
Liney1=Mousey()
endif
if mousebutton()=2
Linex2=mousex()
Liney2=Mousey()
endif
; run Through and check if this point is over a sprite
For lp=1 To max
; get the sprite index
Spr2=Sprites(lp)
Turnsprite Spr2,(lp*0.05)
; Check if this point hits this sprites pixels
If LineHitSpritePixels(linex1,liney1,linex2,liney2,spr2,0.5)
pokeSpritefacergb Spr2,0,0,$ff0000
pokeSpritefacergb Spr2,0,1,$ff0000
pokeSpritefacergb Spr2,0,2,$ff0000
pokeSpritefacergb Spr2,0,3,$ff0000
else
pokeSpritefacergb Spr2,0,0,$ffffff
pokeSpritefacergb Spr2,0,1,$ffffff
pokeSpritefacergb Spr2,0,2,$ffffff
pokeSpritefacergb Spr2,0,3,$ffffff
EndIf
Next
; draw all the sprites
DrawAllSprites
; draw the mouse position
linec linex1,liney1,linex2,liney2,rgb(200,0,200)
s$=str$(fps())
boxc xpos,ypos,xpos+GetTExtWidth(s$),ypos+GetTExtHeight(s$),true,0
Text xpos,ypos,s$
; refresh the display
Sync
; loop back to the DO statement and continue this program
Loop
PB170l Tri/QuadHitSpritePixels This example is running the Tri And QuadHitSpritePixels function on a 1500 Rotating Scaling sprites.
; Load a Ship image and prepare it for rotation
Load3DImage "..\..\..\..\gfx\ship.bmp",1
RGBmaskImage 1,$00ffffff
; get the images width + height
w=GetImageWidth(1)
h=GetImageHeight(1)
; Set the Max number of sprites in this test
max=1500
Dim Sprites(MAx)
Dim AddColour(max)
For lp=1 To max
; create a new sprite, and give it a random X & Y position
Spr2 =NewSprite(Rnd(800),Rnd(600),1)
; set the sprites drawmode to rotated (mode 2)
SpriteDrawMode spr2,2
; center sprite handle
CenterSpriteHandle spr2
; randomly scale the sprite
ScaleSprite Spr2,RndRange#(1,2)
Sprites(lp)=spr2
Next
; Start of program Main loop
Do
; clear the screen to RGB colour 100,100,100
Cls RGB(100,100,100)
; Get the Mouse Position
mX=MouseX()
mY=MouseY()
; Define a Box for uor collision checks
; define the triangles vertex
tx1=mx
ty1=my
tx2=mx-50
ty2=my+100
tx3=mx-250
ty3=my+10
; define the Quad polygons vertex
qx1=mx
qy1=my
qx2=mx+200
qy2=my-50
qx3=mx+250
qy3=my+100
qx4=mx+30
qy4=my+50
; run Through and check if this point is over a sprite
For lp=1 To max
; get the sprite index
Spr2=Sprites(lp)
AddColour(lp)=0
; turn the sprite
Turnsprite Spr2,(lp*0.05)
; reset this sprites draw mode to rotated (mode2)
SpriteDrawMode spr2,2
; Check if this Triangle hits this sprites pixels
If TriangleHitSpritePixels(tx1,ty1,tx2,ty2,tx3,ty3,spr2,0.5)
AddColour(lp)=rgbalphaadd(AddColour(lp),$0000ff)
EndIf
; Check if this Triangle hits this sprites pixels
If QuadHitSpritePixels(qx1,qy1,qx2,qy2,qx3,qy3,qx4,qy4,spr2,0.5)
AddColour(lp)=rgbalphaadd(AddColour(lp),$ff0000)
EndIf
; set the colour addition colour for this sprite
if AddColour(lp)<>0
pokeSpritefacergb Spr2,0,0,AddColour(lp)
pokeSpritefacergb Spr2,0,1,AddColour(lp)
pokeSpritefacergb Spr2,0,2,AddColour(lp)
pokeSpritefacergb Spr2,0,3,AddColour(lp)
else
pokeSpritefacergb Spr2,0,0,$ffffff
pokeSpritefacergb Spr2,0,1,$ffffff
pokeSpritefacergb Spr2,0,2,$ffffff
pokeSpritefacergb Spr2,0,3,$ffffff
endif
Next
; draw all the sprites
DrawAllSprites
; draw the triangle and the quad regions Alpha blended to the frame buffer
inkmode 1+32
Tric tx1,ty1,tx2,ty2,tx3,ty3,rgb(0,0,255)
Quadc qx1,qy1,qx2,qy2,qx3,qy3,qx4,qy4,rgb(255,0,0)
inkmode 1
s$=str$(fps())
boxc xpos,ypos,xpos+GetTextWidth(s$),ypos+GetTextHeight(s$),true,0
Text xpos,ypos,s$
; refresh the display
Sync
; loop back to the DO statement and continue this program
Loop
PB170l ImageHitSpritePixels This example is running the ImageHitSpritePixels function on a 1500 Rotating Scaling sprites.
PB1.70l CompareSpritePixels (Pixel Perfect collision) oh dear, it would seem i've gone and re-added Pixel Perfect collision support for entity sprites, how rude! :) The pic bellow is showing the standard test where it's comparing a large rotated/scaled sprite to 1500 rotating scaling sprites. The example is using the "
CompareSpritePixels" function to manually resolve the intersections, rather than through
SpriteHit, which hasn't yet been fleshed out to support pixel perfect modes. From memory, all that's remaining now is to implement
ShapeHitSpritePixels method. Once that's in place, the
Direct 3D based sprite engine will be a functional replacement for the older one.
PB1.70m Closest Point To Sprite 1.70m now supports finding the closest point to sprite entities.
PB1.70 - Z ordered Sprite with Video feedback
PB1.70m Closest Point To Sprite #2 While not a pretty screen, the 1.70m version of the command now supports all methods axis,face and collision region.
PB 1.71a - Alpha Channel Support for 3D surfaces This example is a quick rehash of older example that used the AFX image format to load images with Alpha channel. In this version you can load the image directly to a 3D surface (ie. Hardware Accel) and render it. While currently this is only hooked up through the DrawImage method (ie. DrawAlphaImage/DrawRotatedImage namely), the main difference is that you can now tell the renderer what type of transparency to use.
The transparent flag contains packed 3 bit settings, which you can combine will tell it how to render the surface.
1 (bit 0) = Use colour mask
2 (Bit 1) = use alpha channel
4 = not in use.
8 (bit 3) = Apply filtering
openscreen 800,600,32,1
; Include the Free Image Slib
#include "FreeImage"
Screen=newimage(800,600)
; Use Free Image to load this image, so the Alpha channel is preserved.
Logo=FreeImage_LoadImage("PlayBasicSig.png",2)
; Clear Screen
rendertoimage screen
ct=rgb(100,200,50)
cb=rgb(200,200,250)
Shadebox 0,0,getscreenwidth(),GetSCreenHeight(),ct,ct,cb,cb
rendertoscreen
Do
setcursor 0,0
drawimage screen,0,0,0
mx=mousex()
my=mousey()
w=getimagewidth(logo)
h=getimageheight(logo)
DrawAlphaImage logo,mx,my ,1,1 ; Use Mask colour transparent
DrawAlphaImage logo,mx,my+h ,1,2 ; Use Alpha channel
DrawAlphaImage logo,mx,my+(h*2) ,1,2+8 ; Use Alpha channel + filtering
For lp=0 to 10
Scale#=1+(lp/100.0)
DrawRotatedImage logo,400+(lp*1),400+lp,angle#+5,scale#,scale#,w/-2,h/-2,2
next
angle#=angle#+0.1
print fps()
Sync
loop
PB 1.71a - Anti Aliased Shape Rendering (line mode) This demo draws a bunch of ring shaped shapes perspectively, a bit like the old dot tunnel effect (from back in the day). The main difference is that PB1.71a has anti aliased line rendering support for batched tasks like drawing the shape edges.
rings=500
RingSize#=600
FarDepth#=10000
NearDepth#=10
me=NewConvexShape(RingSize#,16)
Edges=GetShapeEdges(me,0)*rings
ClsColour=rgb(50,50,50)
Do
CLs ClsColour
ink $ffffff
mx=getscreenwidth()/2
my=getscreenheight()/2
thisrgb=rgb(50,20,210)
thisrgb= $ffffff
zstep#=(NearDepth#-FarDepth#)/Rings
near=0
far=fardepth#
projection#=400
For lp=0 to rings
x#=cos(angle#+lp*2)*455
y#=sin(angle#+lp)*255
z#=FarDepth#+(lp*zstep#)
ProjectedSize#=(RingSize#*projection#)/z#
Scale#=ProjectedSize#/RingSize#
rotateshape me,Angle#+(lp*10),Scale#
sx#=mx+((x#*projection#)/z#)
sy#=my+((y#*projection#)/z#)
ink RgbDepthCue(thisrgb,ClsColour,z#,near,far)
DrawShape me,sx#,sy#,1
next
ink rgb(255,255,255)
angle#=wrapangle(Angle#,1)
print fps()
print edges
Sync
loop
PB 1.71a - Shape Ball/Tunnel This is slight variation of the previous demo, this it's rendering 100K anti aliased lines.
screenvsync on
rings =50
RingSize# =450
FarDepth# =5000
NearDepth# =510
me=NewConvexShape(RingSize#,15)
For lp=1 to 50
shape=NewConvexShape(RingSize#+(100*lp),17+lp)
MergeShape Shape,ME
DeleteShape Shape
next
ClsColour=rgb(50,50,50)
Surf=New3Dimage(GetScreenWidth(),GetScreenHeight())
Edges=GetShapeEdges(me,0)*rings
Do
CLs ClsColour
DrawAlphaIMage Surf,0,0,0.25,false
ink $ffffff
mx=getscreenwidth()/2
my=getscreenheight()/2
thisrgb=rgb(50,20,210)
thisrgb= $ffffff
zstep#=(NearDepth#-FarDepth#)/Rings
near=0
far=fardepth#
projection#=500
For lp=0 to rings
x#=cos(angle2#+lp*1)*255
y#=sin(angle2#+lp)*555
z#=FarDepth#+(lp*zstep#)
ProjectedSize#=(RingSize#*projection#)/z#
Scale#=ProjectedSize#/RingSize#
rotateshape me,Angle#-(lp*10),Scale#
sx#=mx+((x#*projection#)/z#)
sy#=my+((y#*projection#)/z#)
ink RgbDepthCue(thisrgb,ClsColour,z#,near,far)
; capturedepth z#
DrawShape me,sx#,sy#,1
next
ink rgb(255,255,255)
angle#=wrapangle(Angle#,1)
angle2#=wrapangle(Angle2#,1.1)
currentfps=fps()
text 0,0,CurrentFps
text 0,20,rings
text 0,40, edges
CopyRect 0,0,0,GetScreenWidth(),GetSCreenHeight(),surf,0,0
Sync
loop
PB1.71B Sprite Filtering In this update users can now control if a sprite has filtering or not. To do so use the SpriteFilter&GetSpriteFilter commands.
; Load the Ship Bitmap from GFX folder. Which is locate up 4 level from where
; this example it located.
Load3DImage "..\..\..\..\Gfx\Ship.bmp",1
NoFilter= NewSprite(200,200,1)
SpriteDrawmode NoFilter,2
CenterSpriteHandle NoFilter
ScaleSprite NoFilter,5
SpriteFilter NoFilter,Off
Filter= NewSprite(600,200,1)
SpriteDrawmode Filter,2
CenterSpriteHandle Filter
ScaleSprite Filter,5
SpriteFilter Filter,On
Setfps 30
Do
; Clear the Backgroud toa dark green colour
Cls Rgb(30,50,40)
CenterText GetSpriteX(filter),50,"Filtering "+State(Filter)
CenterText GetSpriteX(Nofilter),50,"Filtering "+State(NoFilter)
turnsprite Filter,1
turnsprite NoFilter,1
DrawAllSprites
Sync
loop
Function State(Spr)
Select getspritefilter(Spr)
case 1
result$="Bilinear Filter"
default
result$="No Filter"
endselect
result$="["+Result$+"]"
EndFunction Result$
PlatFormer Demo Using Perspective Sprites This is the standard platform demo from way back converted to use PB1.71c's perspective sprite rendering. Which is a feature of PB1.7x editions of PlayBasic. Perspective rendering has various rotation modes. In this one (perspective 2D), it will renders the sprite scene down the z axis. So the camera can zoom in/out and spin on the Z axis but not on the X/Y axis. There's other rotation modes (ie full 3D) but this one is a lot simpler for 2D game scenes (no axis flipping). and therefore a lot more plug and play friendly!
Perspective 2D platformer With Particles Patched In This pic is the previous demo with the 2D particles example (http://www.underwaredesign.com/forums/index.php?topic=2117.msg14712#msg14712) cut together into it. Rough as guts, but shows the potential !
Perspective 2D Platformer Video This is a little 30second video capture (3.4 meg - DivX5.1) of the perspective platformer demo running in PB1.71. The demo includes 7 backdrop layers, particles, pixel perfect collision, alpha overlays etc All drawn from a top down perspective.
download Download Platformer Video (http://www.underwaredesign.com/files/demos/PB171_Perspective2DPlatformer.zip)
3D City Scape + Terrain This example is of a 3D city scape that's generated in code. The example uses the Sprite Entity feature of PB1.7x combined and Draw Perspective Sprite command to render a 3D scene.
PB1.71f TexturedPolyHitSprite Pixels This function is more a exposed helper function than a user function persay, but it's there if you want to detect impacts between a textured convex polygon and a sprites pixels.
; Load a Ship image and prepare it for rotation
Load3DImage "..\..\..\..\gfx\ship.bmp",1
; Load the uw logo image as FX image as the texture
LoadFXImage "..\..\..\..\gfx\uwlogo.bmp",2
; get the images width + height
w=GetImageWidth(1)
h=GetImageHeight(1)
; Set the Max number of sprites in this test
max=1500
Dim Sprites(MAx)
Dim AddColour(max)
For lp=1 To max
; create a new sprite, and give it a random X & Y position
Spr2 =NewSprite(Rnd(800),Rnd(600),1)
; set the sprites drawmode to rotated (mode 2)
SpriteDrawMode spr2,2
; center sprite handle
CenterSpriteHandle spr2
; randomly scale the sprite
ScaleSprite Spr2,RndRange#(1,2)
Sprites(lp)=spr2
Next
Dim Poly as PBpositionUV pointer
Dim Vert1 as PBpositionUV pointer
Dim Vert2 as PBpositionUV pointer
Dim Vert3 as PBpositionUV pointer
Dim Vert4 as PBpositionUV pointer
VertexBuffer=Newbank(1000)
poly=GetBankPtr(VertexBuffer)
Vert1=GetBankPtr(VertexBuffer)
Vert2=GetBankPtr(VertexBuffer)+20
Vert3=GetBankPtr(VertexBuffer)+40
Vert4=GetBankPtr(VertexBuffer)+60
; Start of program Main loop
Do
; clear the screen to RGB colour 100,100,100
Cls RGB(100,100,100)
; Get the Mouse Position
mX=MouseX()
mY=MouseY()
texture=2
// Set Vertex 1
vert1.x =-200.00 +mx
vert1.y =0.00 +my
vert1.u =0.0
vert1.v =0.0
vert2.x =300.00 +mx
vert2.y =000.00 +my
vert2.u =float(GetImageWidth(Texture))
vert2.v =0.0
Vert3.x =300.00 +mx
Vert3.y =200.00 +my
Vert3.u =float(GetImageWidth(Texture))
Vert3.v = float(GetImageheight(Texture))
Vert4.x =-200.00 +mx
Vert4.y =200.00 +my
Vert4.u =float(0)
Vert4.v = float(GetImageheight(Texture))
; run Through and check if this point is over a sprite
For lp=1 To max
; get the sprite index
Spr2=Sprites(lp)
AddColour(lp)=0
; turn the sprite
Turnsprite Spr2,(lp*0.05)
; reset this sprites draw mode to rotated (mode2)
SpriteDrawMode spr2,2
; Check if a textured quad hits this sprites pixels
If TexturedPolyHitSpritePixels(poly,4,texture,spr2,0.5)
AddColour(lp)=rgbalphaadd(AddColour(lp),$0fa07f)
EndIf
; set the colour addition colour for this sprite
if AddColour(lp)<>0
pokeSpritefacergb Spr2,0,0,AddColour(lp)
pokeSpritefacergb Spr2,0,1,AddColour(lp)
pokeSpritefacergb Spr2,0,2,AddColour(lp)
pokeSpritefacergb Spr2,0,3,AddColour(lp)
else
pokeSpritefacergb Spr2,0,0,$ffffff
pokeSpritefacergb Spr2,0,1,$ffffff
pokeSpritefacergb Spr2,0,2,$ffffff
pokeSpritefacergb Spr2,0,3,$ffffff
endif
Next
; draw all the sprites
DrawAllSprites
; draw the triangle and the quad regions Alpha blended to the frame buffer
inkmode 1+32
Tric tx1,ty1,tx2,ty2,tx3,ty3,rgb(0,0,255)
Quadc qx1,qy1,qx2,qy2,qx3,qy3,qx4,qy4,rgb(255,0,0)
inkmode 1
s$=str$(fps())
boxc xpos,ypos,xpos+GetTextWidth(s$),ypos+GetTextHeight(s$),true,0
Text xpos,ypos,s$
/*
texturetri texture, Vert1.x,Vert1.y,int(Vert1.u)*$10000,int(Vert1.v)*$10000,_
Vert2.x,Vert2.y,int(Vert2.u)*$10000,int(Vert2.v)*$10000,_
Vert3.x,Vert3.y,int(Vert3.u)*$10000,int(Vert3.v)*$10000,true
*/
textureQuad texture, Vert1.x,Vert1.y,int(Vert1.u)*$10000,int(Vert1.v)*$10000,_
Vert2.x,Vert2.y,int(Vert2.u)*$10000,int(Vert2.v)*$10000,_
Vert3.x,Vert3.y,int(Vert3.u)*$10000,int(Vert3.v)*$10000,_
Vert4.x,Vert4.y,int(Vert4.u)*$10000,int(Vert4.v)*$10000,true
; refresh the display
Sync
; loop back to the DO statement and continue this program
Loop
PB 1.71f Level Hit Sprite Pixels This example is demonstrating the current WIP of the new LevelHitSprite command. This command allows you to detect pixel level intersections between a sprite and a map (level). In the picture bellow the test version of the routine is running through and comparing the overlapping tiles + sprite. If a tile collides with the sprite, the routine internally renders a red coloured rect at this position, so the collision is visible. Obviously that's just for testing purposes atm. The routine supports animated and static levels, moreover the levels transparent tile is ignored during collision.
loadfximage "D:\Play_Basic\PlayBasic\Projects_PB170\GFX\Ship.bmp",50
; =================================================
; Part #1 - CREATE A MAP Manually
; =================================================
; Make a map with space with 5 levels
MyMap=NewMap(5)
; Create some block gfx..
BlockWidth =32
BlockHeight =42
BlockCount =10
; Create Block Gfx in out map. These will be blank by default
CreateMapGfx MyMap,BlockWidth,BlockHeight,BlockCount,rgb(0,0,0)
; Draw an array of random blocks and copy them into the maps private block image
For lp=1 to BlockCount
Cls 0
; Draw a randomly colours box to the screen
; boxc 0,0,BlockWidth,Blockheight,true,rndrgb()
Circlec BlockWidth/2,Blockheight*0.5,10,true,rndrgb()
; draw a character to the box
CenterText BlockWidth/2,Blockheight*0.4,chr$(32+rnd(64))
; grab the upper corner of the screen as a block
GetMapBlk MyMap,lp,0,0
next
; Create Level #1 and attach it to MyMap (100=width in tiles, 200 Height in tiles)
CreateLevel MyMap, 1, 100,200
blk=0
; Fill our level with random block indexes. So it'll be a bit of a mess :)
For ylp=0 to GetLevelHeight(myMap,1)-1
For xlp=0 to GetLevelWidth(myMap,1)-1
; Poke (set) the block index at this x/y position in the level.
PokeLevelTile MyMap,1, Xlp,Ylp, blk
inc blk
if blk=>BlockCount then blk=0
next
next
; =================================================
; Part #2 - CREATE A CAMERA
; =================================================
; create a new camera. This camera's render output with be attached to the screen by default
MyCamera=NewCamera()
Spr=newsprite(100,100,50)
centerspritehandle spr
SpriteDrawMode Spr,2
ScaleSprite Spr,5
SpriteCollisionMode Spr,6
SpriteCollisionDebug Spr,true
; =================================================
; Part #3 - Main Loop
; =================================================
Setfps 30
Do
;
; MapX=(MapX+1) and 127
; MapY=(MapY+1) and 255
; Clear the scene buffer of any previous information
ClsScene
; Tell PB to capture all coming drawing commands to the scenebuffer
CaptureToScene
; Tell PB to give following captured (drawn) items a Z depth of 50. This will make the circles draw in front of the map
CaptureDepth 50
; Draw a ring of circles in world space, these will be assigned a scene depth of 50 when PB captures them into the scene buffer
MaxCircles=10
For lp=0 to MaxCircles-1
Angle#=(lp*(360.0/MaxCircles))
Xpos#=1000+CosRadius(Angle#,600)
Ypos#=1000+SinRadius(Angle#,600)
Circle Xpos#,Ypos#,100,true
next
; Tell PB to assign the next captured (drawn) items a Z depth of 100
CaptureDepth 100
; Draw the Map at position 0x , 0y in world space. Since we're in capture mode
; this drawing request is captured to the scene buffer list. So this object (map/level in this case)
; is positioned at 0,0 in world space. With a Z depth of 100
DrawMap MyMap,1,MapX,MapY
positionsprite Spr,mousex(),mousey()
DrawAllSprites
; DRaw the camera. This converts the objects held in the scenebuffer from world space to screen space
; Allowing us to position the camera anywhere we like (in world space) and render whatever objects are visible
; in that section of the world, and that are currently held in the scenebuffer (captured to the scene).
DrawCamera MyCamera
; Use arrows to Move the Camera through world space.
; If Leftkey() then MoveCamera Mycamera,-1,0
; If rightkey() then MoveCamera Mycamera,1,0
; If upkey() then MoveCamera Mycamera,0,-1
; If downkey() then MoveCamera Mycamera,0,1
;
; Use arrows to Move the Camera through world space.
If Leftkey() then MoveSprite Spr,-1,0
If rightkey() then MoveSprite Spr,1,0
If upkey() then MoveSprite Spr,0,-1
If downkey() then MoveSprite Spr,0,1
turnsprite Spr,1
result=levelhitsprite(MyMap,1,MapX,MapY,spr)
text 100,100,Result
; Call sync to refresh the physical display (swaps the hidden screen image with the visible one, so we can see it!)
sync
; Loop (jump) back to the DO statement to keep this program running in a LOOP
loop
PB 1.71f Level Hit Sprite Pixels (Xenon) This is a quick follow up on previous update about LevelHitSprite. Here i'm simply beta testing the command in the standard scrolling demo, my multi camera Xenon 2000 remake. The players bullets have pixel level collision against the foreground map level. If a hit is detected the bullet pops the standard explosion anim (see the code snippet bellow). The interesting thing is that it doesn't really add any overhead at all to the demo's performance. Which is interesting since the bullet sprites and maps are standard
video images. But anyway, here's another piccy for good measure.
// From Update Player Bullets function in the Player module
; Check if the bullet hits the front map layer
if LevelHitSprite(ThisMap,1,0,0,ThisSprite)=true
xpos#=GetSpriteX(ThisSprite)
ypos#=GetSpriteY(ThisSprite)
zpos#=GetSpriteZ(ThisSprite)
Add_Explosion(Aliens().TAlien,ThisPlayer,Xpos#,Ypos#,Zpos#,1)
Delete_Bullet(Bull().TPlayerBullet,lp)
Continue
endif
Simple Xfile Loader - TeaPot (untextured) This picture is shows the results of loading a DirectX 3D object file into PB. The loader is rough as guts and can only load basic geometry as this point. My aim is just to get it loading 'simple' textured objects. Which would allow you to explore 2D / 3D combinations a little more seriously.
Simple Xfile (ASCII) Loader - Dragon (textured) The loader has been updated to support textured objects. It's still not pretty, but they load pretty fast and you can get some 3D happening in your games. The following pictures are of a simple textured dragon model thrown into the city space scene example.
Example Get Source Code (http://www.underwaredesign.com/forums/index.php?topic=2176.msg14936#msg14936) (requires PlayBasic V1.70 or higher)
Where can I find this particle_white.bmp?
PB1.68h alpha???its new version PlayBasic? :o
No, it's a transitional version between PB V1.63 (from back in 2007) and todays PBFX1.74