Legend of Zelda: LTTP Effect?
BlitzMax Forums/BlitzMax Programming/Legend of Zelda: LTTP Effect?
| ||
Would it be possible to do the "wavy" full screen effect in BlitzMax that the Legend of Zelda: LTTP executed when the magic mirror was used? If so, does anyone have any code samples? Thanks! |
| ||
I have some code. I don't know if it's exactly what you need. it manipulates a pixmap. you can download it from my signature link look for it under demos. it's called pixmap distortion. you would need to figure out how to addopt it to your own screen size. |
| ||
Function makeShip:TImage[] (inImage:timage,arr:timage[]) SetImageHandle inimage, 0, 0 DrawImage inImage, 0, 0 For Local i:Int = 0 To arr.count()-1 arr[i] = CreateImage(ImageWidth(inImage) , 1, 1, DYNAMICIMAGE | MASKEDIMAGE | FILTEREDIMAGE) GrabImage (arr[i] , 0, i) Next Return arr End Function I use this code in one of my WIP games to make a particular enemy, however theres no reason you couldn't use it to make a wavy background. Send the function an image and an image array. You'll probably want to set the length of the array to the images height by the looks of things. You could use grabimage to get an image of the screen. you can also use setscale etc. before the grabimage if you don't need it to be as detailed looking. Cheers Charlie |
| ||
@Jesse: Thanks, but that's not the effect I'm looking for. :) @jkrankie: Do you have an example for that piece of code? I have no idea how to use it. IMO, it would be pretty sad if BlitzMax cannot duplicate this effect. I mean, the SNES did it, shouldn't BlitzMax be able to? |
| ||
IMO, it would be pretty sad if BlitzMax cannot duplicate this effect. I mean, the SNES did it, shouldn't BlitzMax be able to? Well that's kind of hard to say for those of us (I'm guessing the majority) who don't even know the effect you refer to. And I played that game a lot. I do know that the SNES had some funky video hardware that almost certainly did things pretty differently than a modern PC vidcard, so it might take some creative thinking. A Youtube link to the effect would be most handy though. |
| ||
Well that's kind of hard to say for those of us (I'm guessing the majority) who don't even know the effect you refer to. And I played that game a lot. ?! A Youtube link to the effect would be most handy though. YouTube. It starts at 8:08. |
| ||
it looks like it might be possible with a light blend effect and continually drawing two complementary images on top of each other and moving away from each other without erasing them but that's just a guess. |
| ||
Oh the sine wave distortion? You probably don't want to hear this but this sort of effect is ridiculously easy (and cheap) when done in a shader. |
| ||
You can duplicate this effect in Max, but depending on how you do it, it might not be super fast. The SNES had this as a hardware effect. Max is a 3D language, and 3D cards aren't designed to do effects like that. At least, they weren't. As someone else mentioned they have shader effects now that can do that stuff, but I don't know how to write shaders or use them in BlitzMax and such effects won't work on all cards out there. So here's how to do it as a software effect that is cross platform and will work on any hardware. But for very high resolutions, it might be a bit slow: Copy the screen to an image before displaying the result of your last set of draw operations. Blit this image, one horizontal line at a time, back to the screen. Offset each of these lines to the left or right as you blit it, using SIN to calculate their position. The math to do this is kinda complicated. But it's something like this: X# = MaxOffset# * Sin(Y#/MaxY# * 360.0*Waves# + Scroll#*360.0) Where MaxOffset# is how big the waves should be, Waves# is the number of waves on screen, Y# is the Y coordinate of the scanline you're blitting, X# is the new start position to blit it at, MaxY# is the height of the screen in pixels-1, and Scroll# is an offset which you can increment to scroll the waves down the screen, with 1 being the height of one wave on the screen. To make the effect look nice, you will want to not only incremenet Scroll# by a little bit each frame, (a little bit being something like 0.05) but also start MaxOffset# at 0 and increment it over time to say, 16, and then decrement it back to 0 again to complete the effect. This will make the waves grow and then shrink again, while also scrolling down the screen. And you'll want something like 2 waves on the screen to get the effect I'm seeing in that video. You can also adjust the number of waves over time too to get an interesting effect. |
| ||
@Gabriel Oh the sine wave distortion? You probably don't want to hear this but this sort of effect is ridiculously easy (and cheap) when done in a shader. Using a shader is probably a good idea. I'm wondering how to add a shader effect in the blitzMax OpenGl driver environment. Would be very nice to add heat effect or fast screen effect in 2D platform game. |
| ||
SSwift that's how I was going to suggest doing it - it should be fast enough to be smooth on a low-mid-range gpu. |
| ||
SuperStrict Graphics 800,600 Const MaxOffSet# = 7.0,Waves# = 4.0 Local Scroll# = 0.0 'load a 800x600 pic, which is the "screen" Local screenshot:TImage = LoadImage("pic.jpg") DrawImage screenshot,0,0 screenshot = Null 'create 600 images, each 1 pixel high and 800 pixels wide Local screenarray:TImage[GraphicsHeight()] For Local y:Int = 0 To GraphicsHeight()-1 screenarray[y] = CreateImage(GraphicsWidth(),1) GrabImage(screenarray[y],0,y) Next Repeat 'DrawImage screenshot,0,0 Scroll# = Scroll# + 0.01 For Local y:Int = 0 To GraphicsHeight()-1 If y Mod 2 = 0 Then DrawImage screenarray[y],MaxOffset# * Sin(Float(y)/(GraphicsHeight()-1) * 360.0*Waves# + Scroll#*360.0),y Else DrawImage screenarray[y],-MaxOffset# * Sin(Float(y)/(GraphicsHeight()-1) * 360.0*Waves# + Scroll#*360.0),y EndIf Next Flip Cls Until KeyHit(KEY_ESCAPE) This is to get started, based on sswift's ideas. |
| ||
That looks great. I like the scanline effect. :-) I wanted to see how it would look with a straight alpha blit though: SuperStrict Graphics 800,600 SetBlend(ALPHABLEND) Const MaxOffSet# = 7.0,Waves# = 4.0 Local Scroll# = 0.0 'load a 800x600 pic, which is the "screen" Local screenshot:TImage = LoadImage("pic.jpg") DrawImage screenshot,0,0 screenshot = Null 'create 600 images, each 1 pixel high and 800 pixels wide Local screenarray:TImage[GraphicsHeight()] For Local y:Int = 0 To GraphicsHeight()-1 screenarray[y] = CreateImage(GraphicsWidth(),1) GrabImage(screenarray[y],0,y) Next Repeat 'DrawImage screenshot,0,0 Scroll# = Scroll# + 0.01 For Local y:Int = 0 To GraphicsHeight()-1 SetAlpha(1) DrawImage screenarray[y],MaxOffset# * Sin(Float(y)/(GraphicsHeight()-1) * 360.0*Waves# + Scroll#*360.0),y SetAlpha(0.5) DrawImage screenarray[y],-MaxOffset# * Sin(Float(y)/(GraphicsHeight()-1) * 360.0*Waves# + Scroll#*360.0),y Next Flip Cls Until KeyHit(KEY_ESCAPE) I like the scanlines better, though I think if I was using this in a modern game I'd go with the alpha cause scanlines are retro. |
| ||
Note that Nawi's code doesn't grab the image on the screen and split it into scanlines. It splits a loaded image before it starts. That means the effect may be a bit slower in practice, because the slow bit is grabbing the image off the screen which 3D cards tend to suck at. |
| ||
It's not that confusing. send the function a Timage (this is any TImage), and an array of type Timage. The size of the array is the number of slices you want to make, presumable in your case it will the the same as the graphics height. anyway, this code should demonstrate how to use the function. Cheers Charlie SuperStrict Graphics 800,600,0,60 'create an array of images Local imgArray:timage[600] 'image to send to the function Local backgroundImage:timage 'draw checkerboard for background For Local i:Int=0 To 7 For Local o:Int=0 To 5 If i Mod 2=0 If o Mod 2=0 SetColor 255,255,255; Else SetColor 0,0,0; EndIf Else If o Mod 2=0 SetColor 0,0,0 Else SetColor 255,255,255 EndIf EndIf DrawRect i*100,o*100,100,100 Next Next 'copy the checkerboard to a Timage backgroundImage=CreateImage(800,600,1,DYNAMICIMAGE | MASKEDIMAGE | FILTEREDIMAGE) GrabImage backgroundImage,0,0 Flip Cls 'cut the image up into 600 lines imgArray=makeship(backgroundimage,imgarray) 'wobble the lines around :) Local angle:Int=0 While Not KeyHit(key_escape) angle:+1 For Local i:Int=0 To 599 Local r:Float=10*Sin(angle+i) DrawImage imgArray[i],r,i Next Flip Cls Wend Function makeShip:TImage[] (inImage:timage,arr:timage[]) SetImageHandle inimage, 0, 0 DrawImage inImage, 0, 0 For Local i:Int = 0 To arr.length-1 arr[i] = CreateImage(ImageWidth(inImage) , 1, 1, DYNAMICIMAGE | MASKEDIMAGE | FILTEREDIMAGE) GrabImage (arr[i] , 0, i) Next Return arr End Function |
| ||
@sswift & @nawi: Both of those examples do not work for me. Here is what I'm getting: EDIT: Nevermind! I was using a modified D3D7Max2DDriver that I modded with a "tweak" I guess doesn't work anymore! :) Effect is fantastic! Exactly what I was looking for! Thanks! |
| ||
can someone plz fix this so it works with blitz3d? |
| ||
yea. heres the blitz3d version fix it up how u wish. code: ;SuperStrict Graphics 800,600,0,2 ;'create an array of images ;Local imgArray:timage[600] Dim imgArray(600) ;'image To send To the Function ;Local backgroundImage:timage Global backgroundImage ;'draw checkerboard For background For i = 0 To 7 ;For Local i:Int=0 To 7 For o = 0 To 5 ; For Local o:Int=0 To 5 If i Mod 2=0 If o Mod 2=0 Color 255,255,255 Else Color 0,0,0 EndIf Else If o Mod 2=0 Color 0,0,0 Else Color 255,255,255 EndIf EndIf Rect i*100,o*100,100,100 Next Next ;'copy the checkerboard To a Timage backgroundImage=CreateImage(800,600,1) GrabImage backgroundImage,0,0 Flip Cls ;'cut the image up into 600 lines imgArray1=makeship(backgroundimage,imgarray1) ;'wobble the lines around :) ;Local angle:Int=0 Global angle=0 While Not KeyHit(key_escape) angle=angle+1 For i = 0 To 599 ; For Local i:Int=0 To 599 r#=(10*Sin(angle)+i) ; Local r:Float=10*Sin(angle+i) DrawImage imgArray1,r,i Next Flip Cls Wend Function makeShip(inImage,arr) HandleImage inimage, 0, 0 DrawImage inImage, 0, 0 For i=0 To arr Step -1 ; For Local i:Int = 0 To arr.length-1 arr = CreateImage(ImageWidth(inImage), 1, 1) ; arr[i] = CreateImage(ImageWidth(inImage) , 1, 1, DYNAMICIMAGE | MASKEDIMAGE | FILTEREDIMAGE) GrabImage (arr, 0, i) Next Return arr End Function |