Dark Bit Factory & Gravity
PROGRAMMING => Purebasic => Topic started by: svenf on February 17, 2015
-
As can be seen here throughout the demo:
https://www.youtube.com/watch?v=H233cYfmWv8
Have no idea how to get there... But gonna try! :carrot:
-
Here's what I got right now. Still VERY far from the intended result, obviously. Yes, I'm a complete noob at these things as you can tell!
Wouldn't mind some help from a pro... :)
-
My take would be to load at least 2 screens that you want to transition between in memory. and then perhaps use a 3rd image as an alpha channel. and animate the alpha channel so that every pixel that is white show image #1 and every pixel that is black show image #2.
all you need to do then is animate the alpha channel to provide the clockwork like transition between the two images. as for implementing that you could start start of with the alpha channel all black. and then starting from the center of the screen draw 2 lines. One from the center, straight to the top and the other to move to the left or right by 1 increment such as 1 degree. then you simply flood fill between the 2 lines to be white, which will show the whole of the 2nd image once complete.
there are probably better ways to do it. but that should be a good starting point.
l
-
Should be pretty much this alpha mask with something like:
if (alpha[i] < time)
screen[i]= ...;
else
screen[i]= ...;
Back in the days they probably used the blitter to copy only parts of a scanline.
-
Thanks for your input!
A lilttle more complicated than I thought... Was hoping for a magic one-liner :)
I'll see if I manage to implement something based on your thoughts...
-
To get you started, its much easier to just do a simple left to right swipe transition. Here is a simple example in processing that starts off with an all black alpha channel. Every 10ms it draws a 1px column to all white starting at the left of the alpha channel untill in reaches the end, by which time the all black alpha channel is now all white.
https://github.com/flightcrank/processing-sketches/blob/9c18ac5c96e8ca7fe0178f4d07e58afba017283e/transition/transition.pde
you can do all sorts of fancy transitions this way. even using gray values to act as an transparency value.
here's a screen hot of my simple program, transitioning from a red image to a blue image.
-
@flightcrank: thanks for your help!
But in the meantime I went ahead with my attempts and this is where I am now. I feel I'm getting closer :)
PS sorry for the bad quality screen capture
(http://i.imgur.com/Ai3xkg1.gif)
-
Ok I don't really know why I started this, it just began to get larger and larger and I need to sleep now.
It's pretty basic but does the job. The routine could be adapted so that instead of pasting a black sprite, you could copy the area from a sprite and paste to the screen.
Probably a way easier way to do this :
InitSprite()
InitKeyboard()
#ScreenWidth = 1024
#ScreenHeight = 768
#ScreenBits = 32
#MiddleX = #ScreenWidth / 2
#MiddleY = #ScreenHeight / 2
#Radius = 600
Define grad.f = 0
Structure Vector
x.f
y.f
EndStructure
Global pix.f=2*#PI/360
Macro Distance(p1, p2)
Sqr((p1\x - p2\x) * (p1\x - p2\x) + (p1\y - p2\y) * (p1\y - p2\y))
EndMacro
Declare Norm(*V.Vector)
Define.Vector Direction, Sprite, Destination
Destination\x = 0
Destination\y= 0
Sprite\x = 0
Sprite\y = 0
Procedure Norm(*V.Vector)
Define.f Norm
Norm.f = Sqr(*V\x * *V\x + *V\y * *V\y)
If Norm
*V\x / Norm
*V\y / Norm
EndIf
EndProcedure
Procedure UpdateSpr()
Protected Angle.f, dist, speed.f = 10
Shared Direction,Destination,Sprite
Direction\x = (Destination\x - Sprite\x) ; -1
Direction\y = (Destination\y - Sprite\y)
Norm(@Direction)
dist = DISTANCE(Destination, Sprite)
If dist < speed
Sprite\x + Direction\x * dist
Sprite\y + Direction\y * dist
Else
Sprite\x + Direction\x * speed
Sprite\y + Direction\y * speed
EndIf
EndProcedure
Procedure BuildImage(Sprite,Image,mode)
Protected SpriteID=SpriteID(Sprite)
w=SpriteWidth(Sprite)
h=SpriteHeight(Sprite)
CreateImage(Image,w,h)
StartDrawing(ImageOutput(Image))
*buf = DrawingBuffer()
If DrawingBufferPixelFormat() = #PB_PixelFormat_32Bits_BGR
GetObject_(ImageID, SizeOf(BITMAP), bmp.BITMAP)
If bmp\bmBitsPixel = 32
CopyMemory(bmp\bmBits, *buf, w*h*SizeOf(RGBQUAD))
EndIf
EndIf
StopDrawing()
EndProcedure
Procedure makenewlogo()
Static lastpush
Shared logo, spr1
If lastpush > 0 And ElapsedMilliseconds() - lastpush < 310 : ProcedureReturn : EndIf
patternpool.s = "A0 6C FC 21 C8 B2 F5 EA C2 C4 60 77 6B 22 AE"
pattern.s = Mid(patternpool, FindString(patternpool, " ", Random(Len(patternpool)))+1, 2)
LoadFont(5, "Trebuchet MS" ,57, #PB_Font_Bold)
logo=CreateSprite(#PB_Any, #ScreenWidth,#ScreenHeight, #PB_Sprite_AlphaBlending)
spr1=CreateSprite(#PB_Any,20,20)
StartDrawing(SpriteOutput(spr1)) : Box(0,0,20,20,#Black) : StopDrawing()
StartDrawing(SpriteOutput(logo))
DrawingFont(FontID(5))
DrawText(80, 30, "SKID//ROW NEVER DIES!" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(80, 130, "ELUSIVE DREAMS - USHQ" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(80, 230, "- - - - - - - - - " , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 430, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 530, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 630, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
lastpush = ElapsedMilliseconds()
For i = 1 To #ScreenHeight Step 7 : Line(0, i, #ScreenWidth, 1 , $000000) : Line(0, i+1, #ScreenWidth, 1 , $000000) : Line(0, i+2, #ScreenWidth, 1 , $000000) :Next
StopDrawing()
EndProcedure
Procedure.f GSin(winkel)
ProcedureReturn Sin(winkel*(pix))
EndProcedure
Procedure.f GCos(winkel)
ProcedureReturn Cos(winkel*(pix))
EndProcedure
Procedure FillVect(vx1,vy1,vx2,vy2)
Shared Sprite, Destination, spr1
fill = #True
Sprite\x=vx1
Sprite\y=vy1
Destination\x=vx2
Destination\y=vy2
Repeat
UpdateSpr()
; If fill = #True
;
; ; DisplayTransparentSprite(logo,0,0)
; spr2=GrabSprite(#PB_Any,Sprite\x,Sprite\y,20,20)
; ; BuildImage(spr2,new,0)
; ; DrawImage(spr2,sprite\x,sprite\y)
; Else
DisplaySprite(spr1,Sprite\x,Sprite\y)
; EndIf
loop+1
Until loop = 200
EndProcedure
window = OpenWindow(0,0,0,#ScreenWidth,#ScreenHeight,"")
screen = OpenWindowedScreen(WindowID(0),0,0,#ScreenWidth , #ScreenHeight )
makenewlogo()
DisplayTransparentSprite(logo,0,0)
Repeat
gsinr=GSin(grad)*#Radius
gcosr=GCos(grad)*#Radius
lx1=#MiddleX-gsinr : ly1=#MiddleY-gcosr
lx2=#MiddleX+gsinr : ly2=#MiddleY+gcosr
FillVect(lx1,ly1,lx2,ly2)
grad + 2
If grad >= 180: grad = 0 :makenewlogo() : DisplayTransparentSprite(logo,0,0): EndIf
ExamineKeyboard()
WindowEvent()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
-
Ok, I finally got the effect. Still needs some polishing but it works.
*edit : removed unused procedure
InitSprite()
InitKeyboard()
#ScreenWidth = 1024
#ScreenHeight = 768
#ScreenBits = 32
#MiddleX = #ScreenWidth / 2
#MiddleY = #ScreenHeight / 2
#Radius = 600
Define grad.f = 0
Structure Vector
x.f
y.f
EndStructure
Global pix.f=2*#PI/360
Macro Distance(p1, p2)
Sqr((p1\x - p2\x) * (p1\x - p2\x) + (p1\y - p2\y) * (p1\y - p2\y))
EndMacro
Declare Norm(*V.Vector)
Define.Vector Direction, Sprite, Destination
Destination\x = 0
Destination\y= 0
Sprite\x = 0
Sprite\y = 0
Procedure Norm(*V.Vector)
Define.f Norm
Norm.f = Sqr(*V\x * *V\x + *V\y * *V\y)
If Norm
*V\x / Norm
*V\y / Norm
EndIf
EndProcedure
Procedure UpdateSpr()
Protected Angle.f, dist, speed.f = 10
Shared Direction,Destination,Sprite
Direction\x = (Destination\x - Sprite\x) ; -1
Direction\y = (Destination\y - Sprite\y)
Norm(@Direction)
dist = DISTANCE(Destination, Sprite)
If dist < speed
Sprite\x + Direction\x * dist
Sprite\y + Direction\y * dist
Else
Sprite\x + Direction\x * speed
Sprite\y + Direction\y * speed
EndIf
EndProcedure
Procedure makenewlogo()
Static lastpush
Shared logo, spr1, brush
If lastpush > 0 And ElapsedMilliseconds() - lastpush < 310 : ProcedureReturn : EndIf
patternpool.s = "A0 6C FC 21 C8 B2 F5 EA C2 C4 60 77 6B 22 AE"
pattern.s = Mid(patternpool, FindString(patternpool, " ", Random(Len(patternpool)))+1, 2)
LoadFont(5, "Trebuchet MS" ,57, #PB_Font_Bold)
logo=CreateSprite(#PB_Any, #ScreenWidth,#ScreenHeight, #PB_Sprite_AlphaBlending)
spr1=CreateSprite(#PB_Any,20,20)
StartDrawing(SpriteOutput(spr1)) : Box(0,0,20,20,#Black) : StopDrawing()
StartDrawing(SpriteOutput(logo))
DrawingFont(FontID(5))
DrawText(80, 30, "SKID//ROW NEVER DIES!" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(80, 130, "ELUSIVE DREAMS - USHQ" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 230, "#######################" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 430, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 530, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 630, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
lastpush = ElapsedMilliseconds()
For i = 1 To #ScreenHeight Step 7 : Line(0, i, #ScreenWidth, 1 , $000000) : Line(0, i+1, #ScreenWidth, 1 , $000000) : Line(0, i+2, #ScreenWidth, 1 , $000000) :Next
StopDrawing()
brush=CopySprite(logo, #PB_Any)
EndProcedure
Procedure.f GSin(winkel)
ProcedureReturn Sin(winkel*(pix))
EndProcedure
Procedure.f GCos(winkel)
ProcedureReturn Cos(winkel*(pix))
EndProcedure
Procedure CopyBit(x,y)
Shared logo,brush
ClipSprite(brush,x,y,20,20)
DisplayTransparentSprite(brush,x,y)
EndProcedure
Procedure FillVect(copy=0)
Shared Sprite, Destination, spr1 , grad, brush
gsinr=GSin(grad)*#Radius
gcosr=GCos(grad)*#Radius
lx1=#MiddleX-gsinr : ly1=#MiddleY-gcosr
lx2=#MiddleX+gsinr : ly2=#MiddleY+gcosr
fill = #True
Sprite\x=lx1
Sprite\y=ly1
Destination\x=lx2
Destination\y=ly2
Repeat
UpdateSpr()
If copy = 1
CopyBit(Sprite\x,Sprite\y)
Else
DisplaySprite(spr1,Sprite\x,Sprite\y)
EndIf
loop+1
Until loop = 200
EndProcedure
window = OpenWindow(0,0,0,#ScreenWidth,#ScreenHeight,"")
screen = OpenWindowedScreen(WindowID(0),0,0,#ScreenWidth , #ScreenHeight )
makenewlogo()
timer = 1780 ; pause loop delays
Global start = ElapsedMilliseconds()
Repeat
now=ElapsedMilliseconds()-start
If grad < 180 And now < timer
grad + 2
FillVect(1) ; draw the screen
ElseIf grad >= 180 And now > timer
FillVect() ; wipe the screen
grad + 2
ElseIf now > timer
start = ElapsedMilliseconds()
EndIf
If grad >= 360 And now > timer ; all timers are down and we've reached 0, reset
grad = 0
start = ElapsedMilliseconds()
makenewlogo() : EndIf
ExamineKeyboard()
WindowEvent()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
-
@emook, well done for your efforts, really appreciated! So this FX takes a bit more code than I thought... It looked so deceptively simple in the original demo.
Unfortunately I'm not able to view the result of your code, as my eval version of PB does not recognize the GetObject_ API call. Any chance you can post a compiled version?
-
Exe attached for your viewing pleasure.
Btw you can include API calls in the demo version of PureBasic and use them afterwards by doing something like the following. The example is considered 'pseudo code' and probably not working at all as I can't test it. But maybe you (or someone) can get it working when fiddling with the general idea... ;)
Pad :cheers:
Import "Gdi32.lib"
GetObj_(hgdiobj, *cbBuffer, lpvObject) As "_GetObj"
EndImport
-
Oops, the procedure can be removed, it isn't actually used - it was going to be used with the first solution.
I've updated the code
A little explanation on why I went this route. There is probably a way easier way to calculate the line which spins in the middle. My initial thought was to draw a line which rotates around its centre, positioned in the centre of the screen that will overwrite the screen as it rotated. Then knowing the x1 and y1 (the top of the line) and then x2 and y2 (the bottom of the line) I would be able to use an old vector routine that takes a start and end position and returns a new position, which is a step closer on each call - this way I could feed in x1,y1 as my start, x2 and y2 as my finish, then loop through the locations pasting a block of 20,20 pixels. I found around 200 loops got me from top to bottom and I could jump about 20 pixels on each degree of rotation. That's when I posted the first solution.
I then got thinking that if I am pasting a boxes 20 pixels apart 20x20 pixels in size along the length of the rotating line, well I know the x and y so why not have the completed screen in the a buffer and then copy the area at the x and y position to the front screen instead. Seems to work well.
InitSprite()
InitKeyboard()
#ScreenWidth = 1024
#ScreenHeight = 768
#ScreenBits = 32
#MiddleX = #ScreenWidth / 2
#MiddleY = #ScreenHeight / 2
#Radius = 600
Define grad.f = 0
Structure Vector
x.f
y.f
EndStructure
Global pix.f=2*#PI/360
Macro Distance(p1, p2)
Sqr((p1\x - p2\x) * (p1\x - p2\x) + (p1\y - p2\y) * (p1\y - p2\y))
EndMacro
Declare Norm(*V.Vector)
Define.Vector Direction, Sprite, Destination
Destination\x = 0
Destination\y= 0
Sprite\x = 0
Sprite\y = 0
Procedure Norm(*V.Vector)
Define.f Norm
Norm.f = Sqr(*V\x * *V\x + *V\y * *V\y)
If Norm
*V\x / Norm
*V\y / Norm
EndIf
EndProcedure
Procedure UpdateSpr()
Protected Angle.f, dist, speed.f = 10
Shared Direction,Destination,Sprite
Direction\x = (Destination\x - Sprite\x) ; -1
Direction\y = (Destination\y - Sprite\y)
Norm(@Direction)
dist = DISTANCE(Destination, Sprite)
If dist < speed
Sprite\x + Direction\x * dist
Sprite\y + Direction\y * dist
Else
Sprite\x + Direction\x * speed
Sprite\y + Direction\y * speed
EndIf
EndProcedure
Procedure makenewlogo()
Static lastpush
Shared logo, spr1, brush
If lastpush > 0 And ElapsedMilliseconds() - lastpush < 310 : ProcedureReturn : EndIf
patternpool.s = "A0 6C FC 21 C8 B2 F5 EA C2 C4 60 77 6B 22 AE"
pattern.s = Mid(patternpool, FindString(patternpool, " ", Random(Len(patternpool)))+1, 2)
LoadFont(5, "Trebuchet MS" ,57, #PB_Font_Bold)
logo=CreateSprite(#PB_Any, #ScreenWidth,#ScreenHeight, #PB_Sprite_AlphaBlending)
spr1=CreateSprite(#PB_Any,20,20)
StartDrawing(SpriteOutput(spr1)) : Box(0,0,20,20,#Black) : StopDrawing()
StartDrawing(SpriteOutput(logo))
DrawingFont(FontID(5))
DrawText(80, 30, "SKID//ROW NEVER DIES!" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(80, 130, "ELUSIVE DREAMS - USHQ" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 230, "#######################" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 430, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 530, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
DrawText(20, 630, "###EMOOK IS CODING!####" , RGB(Random(75)+190, Random(255), Random(75)+190))
lastpush = ElapsedMilliseconds()
For i = 1 To #ScreenHeight Step 7 : Line(0, i, #ScreenWidth, 1 , $000000) : Line(0, i+1, #ScreenWidth, 1 , $000000) : Line(0, i+2, #ScreenWidth, 1 , $000000) :Next
StopDrawing()
brush=CopySprite(logo, #PB_Any)
EndProcedure
Procedure.f GSin(winkel)
ProcedureReturn Sin(winkel*(pix))
EndProcedure
Procedure.f GCos(winkel)
ProcedureReturn Cos(winkel*(pix))
EndProcedure
Procedure CopyBit(x,y)
Shared logo,brush
ClipSprite(brush,x,y,20,20)
DisplayTransparentSprite(brush,x,y)
EndProcedure
Procedure FillVect(copy=0)
Shared Sprite, Destination, spr1 , grad, brush
gsinr=GSin(grad)*#Radius
gcosr=GCos(grad)*#Radius
lx1=#MiddleX-gsinr : ly1=#MiddleY-gcosr
lx2=#MiddleX+gsinr : ly2=#MiddleY+gcosr
fill = #True
Sprite\x=lx1
Sprite\y=ly1
Destination\x=lx2
Destination\y=ly2
Repeat
UpdateSpr()
If copy = 1
CopyBit(Sprite\x,Sprite\y)
Else
DisplaySprite(spr1,Sprite\x,Sprite\y)
EndIf
loop+1
Until loop = 200
EndProcedure
window = OpenWindow(0,0,0,#ScreenWidth,#ScreenHeight,"")
screen = OpenWindowedScreen(WindowID(0),0,0,#ScreenWidth , #ScreenHeight )
makenewlogo()
timer = 1780 ; pause loop delays
Global start = ElapsedMilliseconds()
Repeat
now=ElapsedMilliseconds()-start
If grad < 180 And now < timer
grad + 2
FillVect(1) ; draw the screen
ElseIf grad >= 180 And now > timer
FillVect() ; wipe the screen
grad + 2
ElseIf now > timer
start = ElapsedMilliseconds()
EndIf
If grad >= 360 And now > timer ; all timers are down and we've reached 0, reset
grad = 0
start = ElapsedMilliseconds()
makenewlogo() : EndIf
ExamineKeyboard()
WindowEvent()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
-
k+ emook, excellent recreation of the effect there mate!!
im with hellfire on this one though a simple hue mask and a couple of if checks is so much less computationally expensive and simpler too execute.. these demos were coded at a time where doing this effect in a geometry sort of way would have been too hard on the system.
ill try too grab an hour free in the next few afternoons and code a little example of how i belive this was done. just for fun and adding a little into mix :D
-
Great-looking result, emook!
Padman: thanks a lot for the compiled version and the import tip!!
-
right here is my attempt from tonight. i downloaded hellfire's little alpha mask image and loaded it into my code then i just treated treat the red color channel as a distance value and draw everything up to timestep until timestep hits 255.
i did this little example in freebasic but hopefully you guys get the idea.
please ignore all the code in my main file other than this part
dim as short x,y
for y=0 to resY-1
for x=0 to resX-1
if ((alphamask->integer_buffer[x+y*resX] shr 16)and 255)<this_timestep then' if value in alpha mask is lower than what our current time step is display this pixel!
backbuffer(x+y*resX)=image(imgtype)->integer_buffer[x+y*resX]
end if
next
next
this_timestep += 0.07f' change this timestep to a higher value for a faster unvailing or a lower value for slower.
if this_timestep>255 then
imgtype+=1
if imgtype>1 then imgtype = 0
'change display too next sequence
this_timestep=0
end if
all the other code sets up a window and double buffering and loading images etc.etc which is specific too freebasic and windows. the code above is the only part that actually relates to this effect.. it takes care of swapping images and sweeping round the alpha mask etc.
this is very fast on my comp. if timestep is set too 1 it is unwatchable quick.
ive attached a rar with source, images, and exe included.
-
ninogenio: thanks, that's great! I have so much to learn from this...
-
Hi guys
Here is the source code for the amiga.
May shed more light on how this was achieved.
-
not really an amiga guy, so not sure quite what i need too view the code from that file?! is there any way that someone could do a text dump of it.. or is this just a ram dump that would need reverse engineered.
-
Ooops, thats the Amiga executable, meant to post the source! :D
:|| :|| :||
Inside you will see the skidrow.s which is the plain text assembly source file. It contains the routines used.