Main Menu

Snow - using sprites

Started by Ian Price, February 07, 2006, 02:18:46 PM

Previous topic - Next topic

Ian Price

Here is a simple demonstration of (fairly) realistic falling snow. There are 1000 sprites running simultaneously - you may need to lower this number to get a good speed/snow balance. Requires no external images. The tabs and indentation are a bit fecked on this forum, but hopefully the comments should steer you in the right direction of understanding.

PlayBASIC Code: [Select]
; PROJECT : Snow example, using sprites
; AUTHOR : Ian Price
; CREATED : 07/02/2006
; EDITED : 07/02/2006
; ---------------------------------------------------------------------

OpenScreen 640,480,16,2

SetFPS 30

; Make screen white, so that we can use the colour to create snowflakes
Cls RGB(255,255,255)

; Create 3 different sized snowflake images
For n=1 To 3
GetImage n,0,0,n,n
Next

main()


; Main
Function main()

; Create snowflakes
For n=0 To 1000
create_snowflake(Rnd(640),RndRange(0,480))
Next

; Loop until ESC key is pressed
While Not EscKey()

; Run through every sprite
For n=0 To 1000

; Get every sprite's X and Y co-ordinates and size
x=GetSpriteLocalInt(n,4)
y=GetSpriteLocalInt(n,8)
size=GetSpriteLocalInt(n,12)

; Make snowflake move and fall
If dlay=0
y=y+size
x=x+RndRange(-size,size)
EndIf

; Update snowflake co-ordinates
SpriteLocalInt n,4,x
SpriteLocalInt n,8,y

; Place snowflake sprite in it's new position
PositionSprite n,x,y

; Destroy snowflake if it goes off bottom of screen
If y>485
create_snowflake(Rnd(640),-10)
DeleteSprite n
EndIf

Next

DrawAllSprites

Text 10,10,"IT'S SNOWING!"

Sync

Cls RGB(128,128,128)

EndWhile

EndFunction


; Create snowflake
Function create_snowflake(x,y)

; Get the next available sprite number
flake=GetFreeSprite()

; Create a brand new snowflake sprite
CreateSprite flake

; Allow the sprite to store information about itself
CreateSpriteLocals flake,16

; Create different sized snowflakes
size=RndRange(1,3)

SpriteLocalInt flake,4,x
SpriteLocalInt flake,8,y
SpriteLocalInt flake,12,size

SpriteImage flake, size

PositionSprite flake,x,y

EndFunction


I came. I saw. I played some Nintendo.

kevin

#1
Ian,

 Just had go and found that the example code make PlayBASIC crash.  it occurs because of both a logic issue in the loop and hole in PlayBASIC (fixing that atm).  The logic allows a sprite that doesn't exist to have it's locals accessed.  The following should fix that for the time being


PlayBASIC Code: [Select]
; Run through every sprite
For n=0 To 1000
if GetSpriteStatus(n)
; Get every sprite's X and Y co-ordinates and size
x=GetSpriteLocalInt(n,4)
y=GetSpriteLocalInt(n,8)
size=GetSpriteLocalInt(n,12)

; Make snowflake move and fall
If dlay=0
y=y+size
x=x+RndRange(-size,size)
EndIf

; Update snowflake co-ordinates
SpriteLocalInt n,4,x
SpriteLocalInt n,8,y

; Place snowflake sprite in it's new position
PositionSprite n,x,y

; Destroy snowflake if it goes off bottom of screen
If y>485
DeleteSprite n ; Delete it first.. then create it
create_snowflake(Rnd(640),-10)
EndIf
endif
Next





Ian Price

#2
Doesn't crash for me, but then perhaps I don't have the most upto date version installed?

Cheers for fixing it :)

BTW I accidently left in the "If dlay=0" code - this was used intially to slow down the speed of the snow descent (I was using a 60FPS).
I came. I saw. I played some Nintendo.

kevin

yeah i'm not sure when the changed occured, but current edition die, while previous editions do screen out to the illegal accesses.

Ian Price

#4
Quotewhile previous editions do screen out to the illegal accesses.

I'm using PB v1.11 with IDE 1.0.8q. (Retail version)

It runs fine. No crashes or error messages.

???

[EDIT] This is quite worrying actually - what if competition games work for the creators and some others, but not the judge(s) - Will feedback be given to non-working software authors? Will they be allowed to patch the game?

It would be terrible to have worked on something for weeks, only to find that it won't be judged as it does not work on the judge'(s)' machine/version of PB.

* Forgot to add that the above problem of games not working will/may only affect demo users, as retail versions create .EXE versions, which will work.
I came. I saw. I played some Nintendo.

kevin

QuoteNo crashes or error messages.

 There won't be any run time errors messages pre PB1.15 with sprites, as  it didn't have any :) - But it does now !

 Sadly, I'm sure people are relying upon the fact that sprites don't have error trapping as some type of feature.  In other words PB is allowing users to  access a sprite that doesn't exist and get away with it.  Which is not good !  While I guess this can in a blessing in some cases, it can also be a huge pain in the arse for debugging purposes.

 Now since implementing run time errors into sprites  tonight,  I've been testing a number of sprite examples and a surprising amount contain such errors.   Prolly about 25% of demos tested actually failed.   Many are caused by typos or simply things like overrunning loops.

 The problem above is caused from a combination of two issues. The first is that sprite locals weren't deleted/recreated correctly (which was recently fixed) and the other is that PB lets the user access null sprites it in the first place.

 For the compo, nobody is going be eliminated due to unforeseen variances within PB.  Those submitting sources code would be wise to note what version they were using to develop it.   But it's not that difficult to test them side by side.

Ian Price

That's good news on all counts :)
I came. I saw. I played some Nintendo.

kevin

#7
Here's a bit of a edit of the Snow code

PlayBASIC Code: [Select]
OpenScreen 640,480,16,2

;SetFPS 30

; Make screen white, so that we can use the colour to create snowflakes
Cls RGB(255,255,255)

; Create 3 different sized snowflake images
For n=1 To 3
GetImage n,0,0,n,n
Next

main()




; Main
Function Main()

; Create snowflakes
For n=1 To 1000
create_snowflake(Rnd(640),RndRange(0,480))
Next

; Loop until ESC key is pressed
While Not EscKey()

Cls RGB(100,100,100)

; Run through every sprite
For n=1 To 1000
; Get the Flake size
size=GetSpriteLocalInt(n,0)

; Move the sprite down, with a random wobble
MoveSprite n,rndrange(-size,size),size

; Destroy snowflake if it goes off bottom of screen
If getSpriteY(n)>485
; Delete the sprite first (putting this sprite
; resource on the top of the Free Sprite list
DeleteSprite n

; Create a new flake. This flakes sprite will
; be popped off the free sprite list. Keeping
; it as the same sprite index
create_snowflake(Rnd(640),-10)
EndIf
Next

; Draw all the sprites
DrawAllSprites

Text 10,10,fps()

Sync

EndWhile

EndFunction




; Create snowflake
Function create_snowflake(x,y)

; Create different sized snowflakes
size=RndRange(1,3)

; Create a new sprite for this snoke flake
Flake=NewSprite(x,y,size)

; Allow the sprite to store information about itself
CreateSpriteLocals flake,4

; Store the Size of this flake inside the sprite
SpriteLocalInt flake,0,size

EndFunction






Ian Price

I've just noticed the GetSpriteY(n) bit, other than being a bit less typing (which is a good thing, as I'm a lazy git), does it speed up the code at all? Is that the only difference, I didn't notice anything else.

OK, I've now got over 200FPS and it's blizzard time, and I'm not going outside to build a snowman!
I came. I saw. I played some Nintendo.

kevin

It's just slim lined version of the original.    A bit shorter and a bit quicker, but serves the same purpose really..