Sprite trails
Blitz3D Forums/Blitz3D Beginners Area/Sprite trails
| ||
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? |
| ||
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. |
| ||
2) use Object and Handle commands. They give direct access to a particular type. |
| ||
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. |
| ||
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. :) |
| ||
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 |
| ||
Thanks Stevie! I didn't know you could use Types and Dim arrays together like that! :) |
| ||
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. |
| ||
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) |
| ||
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. |
| ||
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 :) |
| ||
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 |
| ||
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) |
| ||
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? |
| ||
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 thisFunction 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 |
| ||
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 |
| ||
Check this one out, it look pretty cool and does what you ask for: http://www.blitzbasic.com/codearcs/codearcs.php?code=191 |
| ||
Ross C, excellent examples. Thank you very much. I'll master this technique yet. :) Thanks for the link wedoe. Looks very nice. :) |