News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

Cached Sprite Rotation

Started by kevin, January 11, 2005, 01:38:34 PM

Previous topic - Next topic

kevin

PlayBASIC Code: [Select]
; ---------------------------------------------------------------------
; This example creates the illusion of a hundreds of real time rotating
; sprites. The idea here is to show you that you don't actually have to
; rely upon PB rotation of each object. IF you have objects that rotate
; in sync, or don't rotate often you can cache them. This can be give you
; a massive performance gain.
; ---------------------------------------------------------------------


; First lets make an image
; Clear the Screen to black
Cls 0

; draw some stuff to create our image
EllipseC 32,32,RndRange(20,30),RndRange(20,30),1,$ff0080
CenterText 32,32,"Hello"

; grab the screen section as a screen
GetImage 1,0,0,64,64
PrepareFXImage 1

; create a second image to store the temp rotation frames in
CreateImage 2,64,64


; Make Type of the
Type tStar
x#,y#,XSpeed#,Yspeed#
EndType

; Dim a types Array to hold all Of our stars
Dim Stars(200) As tStar

; get the screen width and Height minus 64 pixels
Sw=GetScreenWidth()-64
Sh=GetScreenHeight()-64


; Init the Stars array and the sprites
For starsI=1 To GetArrayElements(Stars().tStar,1)
stars(starsI).x = Rnd(sw)
stars(starsI).y = Rnd(sh)
stars(starsI).xspeed = Rnd(5)
stars(starsI).yspeed = Rnd(5)

CreateSprite starsI
SpriteImage starsI,2
SpriteTransparent starsI,1
PositionSprite starsI,starsX,starxY
Next starsI



; STart a Do/Loop
Do

; Tell PB to Draw to the SCREEN
RenderToScreen
; Clear the Screen
Cls 0

; Bump our Angle variable forward.. it will wrap inside 360 degrees
angle#=WrapAngle(Angle#,1)

; Tell PB to render to our previous created TEMP image #2
RenderToImage 2
; DRaw a rotated version of Image #1 to image #2
DrawRotatedImage 1,32,32,angle#,1,1,-32,-32

; Tell PB to draw to the screen again
RenderToScreen

; Run Through and MOve all the stars in the stars array
For starsI=1 To GetArrayElements(Stars().tStar,1)

x#=stars(starsI).x+stars(starsI).xspeed
Y#=stars(starsI).y+stars(starsI).Yspeed

If X#<0 Or X#>Sw Then stars(starsI).xspeed=-stars(starsI).xspeed
If Y#<0 Or Y#>Sh Then stars(starsI).yspeed=-stars(starsI).yspeed

PositionSprite starsI,x#,y#

stars(starsI).x=x#
stars(starsI).Y=y#

Next starsI

; Now Draw ALL THE Sprites
DrawAllSprites

; PRint the FPS
Print "Cached Rotating Sprite Illusion - Fps: "+Str$(FPS())
; Display the screen
Sync

; Loop back to the DO statement

Loop








tomazmb

Hello Kevin,

Thank you for your example. You are talking about having a massive performance gain in your example using this method. Can you make a standard version that we can compare to see the difference ? Thanks.

Have a nice day,

Tomaz
My computer specification:

AMD Athlon 64 2800+
MB ASUS K8V Socket 754 VIA K8T800
SB Audigy 2
3 GB RAM DDR 400 MHz PQI
AGP NVIDIA GeForce 7600GT 256 MB-Club 3D
Windows XP Pro SP2
DirectX 9.0c

kevin

#2
Here's a brute force example..it's rotating every image in real time.. and is THUS VERY SLOW.   as real time rotation in PB has to be done in software.  While it will certainly get faster once the new rotation engine is written, it will never be super fast.  

So, what i'm trying to show by the above example, is that if you think outside of the box a little,  you can create types of illusions that retro coders had to do constantly (since they had under powered computers),  without the need of large amount of processing power..



PlayBASIC Code: [Select]
; First lets make an image
; Clear the Screen to black
Cls 0

; draw some stuff to create our image
EllipseC 32,32,RndRange(20,30),RndRange(20,30),1,$ff0080
CenterText 32,32,"Hello"

; grab the screen section as a screen
GetImage 1,0,0,64,64
PrepareFXImage 1


; Make Type of the
Type tStar
x#,y#,XSpeed#,Yspeed#
EndType

; Dim a types Array to hold all Of our stars
Dim Stars(200) As tStar

; get the screen width and Height minus 64 pixels
Sw=GetScreenWidth()-64
Sh=GetScreenHeight()-64


; Init the Stars array and the sprites
For starsI=1 To GetArrayElements(Stars().tStar,1)
stars(starsI).x = Rnd(sw)
stars(starsI).y = Rnd(sh)
stars(starsI).xspeed = Rnd(5)
stars(starsI).yspeed = Rnd(5)

CreateSprite starsI
SpriteImage starsI,1
SpriteTransparent starsI,1
PositionSprite starsI,starsX,starxY
SpriteDrawMode Starsi,2
Next starsI



; STart a Do/Loop
Do
; Clear the Screen
Cls 0

; Bump our Angle variable forward.. it will wrap inside 360 degrees
angle#=WrapAngle(Angle#,1)

; Run Through and Move all the stars in the stars array
For starsI=1 To GetArrayElements(Stars().tStar,1)
x#=stars(starsI).x+stars(starsI).xspeed
Y#=stars(starsI).y+stars(starsI).Yspeed

If X#<0 Or X#>Sw Then stars(starsI).xspeed=-stars(starsI).xspeed
If Y#<0 Or Y#>Sh Then stars(starsI).yspeed=-stars(starsI).yspeed

PositionSprite starsI,x#,y#
RotateSprite StarsI,Angle#

stars(starsI).x=x#
stars(starsI).Y=y#

Next starsI

; Now Draw ALL THE Sprites
DrawAllSprites

; PRint the FPS
Print "Rotating Sprites - Fps: "+Str$(FPS())
; Display the screen
Sync
; Loop back to the DO statement
Loop





tomazmb

Hello Kevin,

Yes it's a big difference in speed. In your first example I get ~ 335 FPS and in your second one ~ 13 FPS.

QuoteHere's a brute force example..it's rotating every image in real time.. and is THUS VERY SLOW. as real time rotation in PB has to be done in software. While it will certainly get faster once the new rotation engine is written, it will never be super fast.

Are you refering to writing a 3D engine or something else ?

Have a nice day,

Tomaz
My computer specification:

AMD Athlon 64 2800+
MB ASUS K8V Socket 754 VIA K8T800
SB Audigy 2
3 GB RAM DDR 400 MHz PQI
AGP NVIDIA GeForce 7600GT 256 MB-Club 3D
Windows XP Pro SP2
DirectX 9.0c

kevin

Nah, the current rotation code is just old and sloppy.   While i shouldn't guess how much it can improved, i'd be surprised if I couldn't get it somewhere around  %25 to %50  faster. Which would make it a lot more useful I think.  But we'll see.

tomazmb

Hello Kevin,

Ah, I see you have lots on your minds with future progress of Play Basic. Please continue to inform us (users) what's going on with the development and how we users can speed up our code. Thanks.

Have a nice day,

Tomaz
My computer specification:

AMD Athlon 64 2800+
MB ASUS K8V Socket 754 VIA K8T800
SB Audigy 2
3 GB RAM DDR 400 MHz PQI
AGP NVIDIA GeForce 7600GT 256 MB-Club 3D
Windows XP Pro SP2
DirectX 9.0c

tomazmb

Hello Kevin,

I made a standalone version out of your example. Everythings work great, just 2 newbie question:

1. in one of your post you described PlayBasic as language which produce Byte Code and is later compiled. Why do the standalone executables have the same FPS as do the programs when they are running within PlayBasic ? Stupid question, but I still want to know. :rolleyes:

2. why is executable 2.4 MB long ? :o

In one of your answers on TGC forum, when I ask you is Play Basic gonna be a compiler (produce a machine code), you answered yes (great !). How much of speed gain do you expect and how much of a file reduction in size ?

Will you follow the same route as other developers (IBPro from Pyxia Development ) which includes only DLL's which are needed ?

Have a nice day,

Tomaz
My computer specification:

AMD Athlon 64 2800+
MB ASUS K8V Socket 754 VIA K8T800
SB Audigy 2
3 GB RAM DDR 400 MHz PQI
AGP NVIDIA GeForce 7600GT 256 MB-Club 3D
Windows XP Pro SP2
DirectX 9.0c

Draco9898

#7
Quote2. why is executable 2.4 MB long ? :o


WEll, it could be like Darkbasic EXE's which are 8.4 megabytes, and that smarts!  :huh:

It has to include all the functions that playbasic uses I.E (Mapping system, sound, ETC), it doesnt pick and choose from what you've used as far as code and commands go. So despite if you dont use sound, the code to run it is included anyways, but this is how all these Basic kinda programming languages run.
DualCore Intel Core 2 processor @ 2.3 ghz, Geforce 8600 GT (latest forceware drivers), 2 gigs of ram, WIN XP home edition sp2, FireFox 2.

"You'll no doubt be horrified to discover that PlayBasic is a Programming Language." -Kevin

empty

Quote1. in one of your post you described PlayBasic as language which produce Byte Code and is later compiled. Why do the standalone executables have the same FPS as do the programs when they are running within PlayBasic ? Stupid question, but I still want to know. 
Currently Play compiles to byte code which is then executed by a Virtual Machine (sort of like Java). This is pretty much the same in the compiler version (run from the Editor) and in the stand alone exes. Later versions will translate this byte code to native machine code.


Quote2. why is executable 2.4 MB long ?
Draco's explanation is correct. The so called Runtime libraries (the code that contains graphic and sound functions etc) are alway included in the VM and therefore in the executable.


QuoteWill you follow the same route as other developers (IBPro from Pyxia Development ) which includes only DLL's which are needed ?
We have a couple of ideas of how to seperate the runtime libraries and how to link them to the final executable. But nothing's set in stone yet. :)

kevin

#9
Quote1. in one of your post you described PlayBasic as language which produce Byte Code and is later compiled. Why do the standalone executables have the same FPS as do the programs when they are running within PlayBasic ? Stupid question, but I still want to know.  

 When you run your code from the editor, what happens is the IDE bundles up all your code, launches the PB compiler/runtime and sends the code to it.    The compile process converts your source code, from the Text form, to our binary/byte code form.   If the program compiled successfully, PB then passes the Byte Code representation of your program,  onto the Run Time (Virtual Machine)  which executes it.

 The runtime included in the Compiler package and the stand alone editions are different, but not by a great deal.  The release edition, has all error trapping removed from package.   This is certainly the faster runtime, but obviously not ideal for debugging.  

 However, while the Release Runtime is the fastest, it's only faster in processing program code. So things like the drawing operations for example, will be the same speed, as they are in fact the same code.    Any speed increases will come in a programs processing ability.  So it'll be faster when doing calculations, or working with information stored within arrays.  

 To test this, try these examples, both from the editor, and compiled into exe's..    The first should run pretty much the same regardless, or very close to it.  The second you should see a performance difference.  Not a lot, but some.  


Example #1
PlayBASIC Code: [Select]
; =================================================
; This code just draws a Moving Grid fo boxes
; =================================================

size=32

Do


; Reset the Flag to controls the Box colours
Toggle=0


; Start For/NExt loop that will set down the Y axis
For Y1=(-size)+Offset to GetScreenHeight()+Offset step Size

; pre calc ottom Ypos of this row of boxes
Y2=y1+Size

RowToggle=Toggle
Toggle=1-Toggle

; Start For/NExt loop that will step across the X axis
For x1=(-size)+Offset to (GetScreenWidth()+offset) step Size

; If Row Toggle is true, then draw a Bluey coloured box
IF RowToggle
; Draw the blue box
BoxC x1,y1,x1+size,y2,1,Rgb(20,30,$dd)
; Flip the ROW Toggle to FALSE for next loop
RowToggle=FALSE
else
; Draw a GREEN box if the RowToggle variable was FALSE
BoxC x1,y1,x1+size,y2,1,RGb($33,$a0,50)
; Set the RowToggle to TRUE
RowToggle=TRUE
endif
next X1
next Y1

; Wrap the SCrolling Offset
offset=mod(Offset+1,Size)

text 0,0,fps()
Sync
loop






Example #2
PlayBASIC Code: [Select]
Dim Array(25000)

Do
Cls 0
print "Fps:"+STR$(FPS())

inc frames

T=timer()
; Fill the array with Random nujmbers
For lp=0 to GetArrayElements(Array(),1)
Array(lp)=rnd(1000)*rnd(1000)
next

Total#=Total#+(Timer()-t)
print "Average Loop Time:"+str$(Total#/Frames)

Sync
loop





Quote2. why is executable 2.4 MB long ?  
[/pbquote]

 Yeah, when it builds the exe, the file includes the entire PB runtime, regardless of what was used or not.   So there's not a lot I can do about it at the moment.  Although, I could Cheat or worse Lie about the exe size, by pre-compressing the runtimes.. like some others.. .

 On  that note, the files do compress pretty well.


QuoteIn one of your answers on TGC forum, when I ask you is Play Basic gonna be a compiler (produce a machine code), you answered yes (great !). How much of speed gain do you expect and how much of a file reduction in size ?

 Obviously code execution will be faster, but you have to understand this doesn't change the speed of the GFX functions, so render speed really won't be any different (unless we re-write stuff).   As compiling to machine code only effects the processing code, and not the speed of the PB engine.

tomazmb

Hello,

Thank you all for posting a replay to my questions and giving an explanation in your answers.

Kevin:

in your first example I get ~169 FPS in PB and ~168 FPS in EXE
in your second example I get ~63 FPS in PB and ~ 70 FPS in EXE

Have a nice day,

Tomaz
My computer specification:

AMD Athlon 64 2800+
MB ASUS K8V Socket 754 VIA K8T800
SB Audigy 2
3 GB RAM DDR 400 MHz PQI
AGP NVIDIA GeForce 7600GT 256 MB-Club 3D
Windows XP Pro SP2
DirectX 9.0c

empty

On a related note, when you launch your program from within the IDE, it tells Windows to give it a higher process priority. This is done (mainly) to increase the start-up speed, but slightly affects the pure execution speed under certain circumstances as well.

tomazmb

Hello empty,

Stupid question. Is exe designed the same way, meaning if you want to your game to have the highest possible frame rate it tells the Windows to give such an executed program the highest process priority and possibly as much of available RAM ?

Have a nice day,

Tomaz
My computer specification:

AMD Athlon 64 2800+
MB ASUS K8V Socket 754 VIA K8T800
SB Audigy 2
3 GB RAM DDR 400 MHz PQI
AGP NVIDIA GeForce 7600GT 256 MB-Club 3D
Windows XP Pro SP2
DirectX 9.0c

empty

No the executables always run with normal priority when launched. It would be possible to give an executable higher priorities (to a certain extend at least) but if it crashes, strange things might happen.
Another route is to write a launcher app, that starts the main app with a higher priority. It won't make much difference though, and the user might be annoyed if the rest of Windows runs at the speed of a shifting sand dune.  :)