Sprite trails

Blitz3D Forums/Blitz3D Beginners Area/Sprite trails

Drekinn(Posted 2004) [#1]
Hi all. Any help with the following would be appreciated:

1) I'd like my moving sprite to leave a trail of pixels wherever it goes. I've played around with the Plot and WritePixel commands but anything I draw to the screen is wiped away each time the buffer is refreshed.
Could someone please advise me on how to achieve this trailing effect with double-buffering? (A good example of this would be a paint program).

2) Is it possible to read/set a type field without having to first point at it with the First, Last, Before or After commands?
Sure I could create separate custom type variables, but what if I wanted to refer to say 100 variables individually? I'm not about to hand-type 100 unique custom names am I? Is creating an array with the Dim command the only solution?


Matty(Posted 2004) [#2]
Answer to 1st question:

type SpriteTrail

field x
field y
field lifetime
field r
field g
field b

end type

in your code where you place the pixels do the following instead:
Trail.SpriteTrail=new SpriteTrail
Trail\x=your trailing pixel's x position
Trail\y=your trailing pixel's y position
Trail\r=amount of red
trail\g=amount of green
trail\b=amount of blue
trail\lifetime=number of frames you want this point in the trail to exist for

then in your main loop where you would normally draw the pixels
do the following:

For Trail.spritetrail=each spritetrail
trail\lifetime=trail\lifetime-1
if trail\lifetime>0 then
color trail\r,trail\g,trail\b
plot trail\x,trail\y
else
delete trail
endif
next


Answer to 2nd question:

Explain a little further what you are hoping to achieve please.


Bremer(Posted 2004) [#3]
2) use Object and Handle commands. They give direct access to a particular type.


Drekinn(Posted 2004) [#4]
1) Thanks for the help Matty but your example doesn't work without a lot of tinkering. Could you please copy and paste the entire functioning program so I can actually see your code in action?.
Remember to keep in mind too that the buffer needs to be cleared each frame with Cls. Your example does not work in this case, as the previously drawn pixels are removed with each refresh.

2) As for my other question, take for example:

Type alien
Field x,y
End Type

For z = 1 to 5
nasty.alien = New alien
nasty\x = Rand(800)
nasty\y = Rand(600)
Next


I wish to check the 'x' field values of both the 2nd and 4th alien datatypes for some reason. To be able to read the 'x' field value of the 2nd entry I would need to type:

nasty.alien = First alien
nasty = After nasty


To compare the 'x' field value of this 2nd entry with the 4th entry I would have to store the 2nd entry value in a new variable:

alien2X = nasty\x

Then to grab the 'x' field value of the 4th entry I would type:

nasty = After nasty
nasty = After nasty


I can now read the 4th entry's 'x' field value and compare it to the 2nd entry's 'x' field value previously stored in alien2X.

Now I think you'll agree that this method truly sucks arse.
So to repeat the original question:

Is it possible to read/set a type field without having to first point at it with the First, Last, Before or After commands?

This would save a lot of time and effort. I know creating an array using the Dim command is an option, but I prefer to use Types.

Any assistance would be appreciated.


Drekinn(Posted 2004) [#5]
zawran, neither of those commands are listed in the Command Reference, though Blitz seems to recognise them as official commands when typed into the IDE. Hmmm.
Could you please shed some more light on these two little miracles? An example snippet of code would be great. :)


Stevie G(Posted 2004) [#6]
An array of types is handy here to start with. Although I would recommend using Object and Handle when you are familiar with them. Search the forums - there are countless explanations.

Anywho, here a simplt example of an array of types ...


Dim nasty.Alien( 20 )

for l = 0 to 20
 nasty(l) = new Alien
 nasty(l)\x = rand(-10,10)
 nasty(l)\y = rand(-10,10)
next

;just move nasty 2 and 4
nasty(2)\x = nasty(2)\x + 1
nasty(4)\x = nasty(4)\x + 10




Drekinn(Posted 2004) [#7]
Thanks Stevie! I didn't know you could use Types and Dim arrays together like that! :)


Bremer(Posted 2004) [#8]
Here is a link to a description on BC about those two commands:

http://www.blitzcoder.com/cgi-bin/code/code_showentry.pl?id=thechange08052002184613&comments=no

Do remember that they are officially unsupported and may be broken in future updates of blitz.


Ross C(Posted 2004) [#9]
To compare two types against each other, you could do this....



Function compareX(num,num1)
counter = 0
For a.alien = Each alien
   counter = counter + 1
   If counter = num then
      temp.alien = a.alien
   End If
   If counter = num1 then
      temp1.alien = a.alien
   End If
Next

Return temp\x - temp1\x

End Function



Then, call the "compareX(1,7)" function. Put in the numbers of the two you want to compare. so:

If compareX(2,4) = 0 then
   Print" Aliens are in the same X positions"
End If


The function basically returns the difference between the two ship numbers passed across. You could do a compareY function the same way :o)


Drekinn(Posted 2004) [#10]
Thanks for the link zawran. Not sure if I'm any more the wiser though. ;)
If Object and Handle are, as you say, unofficial commands then perhaps I'll just stick with the Type/Dim combo.

Thanks Ross for the other alternative. :)

If anyone could assist further on my first question regarding sprite trails I'd be grateful.


Stevie G(Posted 2004) [#11]
Drekinn,

Matty's code is pretty much what you asked for. You need to draw these trails after CLS ( I assume your using 2d ) and before the FLIP command.

If it's something different you're after then you'll need to explain a bit better. Why not post your code so far and I'm certain one of us can help :)


Ross C(Posted 2004) [#12]
Hey Drekinn. Here's some code that will do what you need. Basically Matt's stuff, put into functions and a little sample program.

Graphics 800,600

SetBuffer BackBuffer()


Type trail
	Field x,y
	Field size
	Field r,g,b
	Field time
	Field timer
End Type


Global trail_dis_time = 100 ; time trail stay on screen for

Global trail_R = 100; red
Global trail_G = 100; green
Global trail_B = 100; and blue of color of trail.

Global trail_timer = MilliSecs()
Global trail_time = 10 ; leave a trail every 10 milliseconds

While Not KeyHit(1)

	Cls


	If MilliSecs() > trail_timer + trial_time Then
		create_trail(MouseX(),MouseY(),1)
	End If
	

	update_trails()
	Flip
Wend
End


Function create_trail(x,y,size)

	t.trail = New trail
		t\x = x
		t\y = y
		t\size = size
		t\time = trail_dis_time
		t\timer = MilliSecs()
		t\r = trail_R
		t\g = trail_G
		t\b = trail_B
		
End Function


Function update_trails()

	For t.trail = Each trail
	
		Color t\r, t\g, t\b
	
		Rect t\x - (t\size/2), t\y - (t\size/2), t\size, t\size
		
		If MilliSecs() > t\time + t\timer Then
			Delete t.trail
		End If
		
	Next
	
End Function



Ross C(Posted 2004) [#13]
Oh, i get what you mean now :) Your using 3d i guess? Well, you need to use any 2d drawing command after the renderworld, to draw on top of 3d graphics :o) SO, put ANY 2d drawing stuff after the renderworld. Mixing 2d and 3d can cause alot of slowdown for people tho, so keep that in mind :o)


Drekinn(Posted 2004) [#14]
Thanks for the help guys. :)

Ross C, no it's 2D I'm referring to. Ahh, but I see in your example that each pixel is stored as its own type object. I thought that method would have been too intensive, but Blitz seems to handle it no probs at all.
Let me see here then, to paint an entire screen would equal 786432 type objects for a 1024x768 screen area. Hmmm.. You're sure my computer won't choke and die horribly? Are there any examples of a paint program floating around that I can study?


Ross C(Posted 2004) [#15]
Oh, right. Well what you do then, is create an image the size of the screen size. Then, instead of creating a type object, do this

Function paint(x,y,screen_image,r,g,b)

   LockBuffer ImageBuffer(screen_image)
   rgb= (a shl 24) or (r shl 16) or (g shl 8) or b; combine the ARGB into a number that writepixelfast can use
   WritePixelFast x,y,rgb,ImageBuffer(screen_image)
   UnlockBuffer ImageBuffer(screen_image)
End function



Make sure you create an image that is the size of the screen. SOmething like this should do:

Graphics 800,600
SetBuffer BackBuffer()


Global image = CreateImage(800,600)



While Not KeyHit(1)

	Cls

	If MouseDown(1) Then
		paint(MouseX(),MouseY(),image,155,155,255); the the values for different colours :o)
	End If

	DrawImage image,0,0 ; draw the canvas so to speak, the drawing will go to
	Color 255,255,255
	Rect MouseX(),MouseY(),1,1
	Flip
Wend



Function paint(x,y,screen_image,r,g,b)

	LockBuffer ImageBuffer(screen_image) ; lock the imagebuffer for the screen image. MUST be locked!
	RGB= (a Shl 24) Or (r Shl 16) Or (g Shl 8) Or b; combine the ARGB into a number that writepixelfast can use
	WritePixelFast x,y,RGB,ImageBuffer(screen_image) ; write a pixel fast to the image buffer
	UnlockBuffer ImageBuffer(screen_image) ; unlock the buffer for the screen image. MUST be unlocked!

End Function



Ross C(Posted 2004) [#16]
This is a better example. The drawing is more solid. Using line instead of writepixelfast() here:

Graphics 800,600
SetBuffer BackBuffer()
HidePointer

Global image = CreateImage(800,600)



While Not KeyHit(1)
	Mouse_X = MouseX() ; record the mouse x position. For timing issues. The mousex() changes everytime it's called
	Mouse_Y = MouseY() ; record the mouse y position. Same reason as above.
	
	Cls
	
	If MouseDown(1) Then
		paint(mx,my,Mouse_X,Mouse_Y,image,155,155,255); the the values for different colours :o)
	End If

	mx = Mouse_X; record the last mouse X position
	my = Mouse_Y; record the last mouse Y position

	DrawImage image,0,0 ; draw the canvas so to speak, the drawing will go to
	Color 255,255,255
	Rect Mouse_X,Mouse_Y,1,1
	Flip

Wend



Function paint(mx,my,x,y,screen_image,r,g,b) ; point from the last mouse position, to the present

	Color r,g,b
	SetBuffer ImageBuffer(screen_image)
	Line x,y,mx,my ; draw a line from the last recorded mouse position, to the current one
	SetBuffer BackBuffer()

End Function



wedoe(Posted 2004) [#17]
Check this one out, it look pretty cool and does what you ask for:
http://www.blitzbasic.com/codearcs/codearcs.php?code=191


Drekinn(Posted 2004) [#18]
Ross C, excellent examples. Thank you very much. I'll master this technique yet. :)

Thanks for the link wedoe. Looks very nice. :)