Amiga copper effects

BlitzPlus Forums/BlitzPlus Beginners Area/Amiga copper effects

How do you simulate Amiga Copper cycle effects in BlitzPlus?

never had an amiga, on msx coders claimed to have the 'copper' effect (colorful filled sines, vertically stretching etc.), but that's all I know ..

you have a screenshot somewhere ? :)

If I'm not mistaken, copper effects require knowing what scanline the monitor is currently drawing, and having graphics based on a 256 color palette which you can change faster than the scanline can move.

BlitzPlus does not support palleted video modes, and though it will tell you what scanline is currently being drawn, that sort of effect wouldn't work on an LCD display which many PC's now use.

On today's PC, if you want something that looks like the copper effect, then all you really need to do is take advantage of the fact that the PC is realyl fast, and you have 24bit color. Creating smooth color gradients that scroll down the screen is pretty simple to do when you have 24bit color.

dunno .. is this what you want? :)

; copper?
;
; hackjob by CS_TBL, no optimizing and variables-check .. just hacky crap.. ^_^

window=CreateWindow("copper? - by CS_TBL",160,160,320,320,0,1)
Global canvas=CreateCanvas(8,8,256,256,window)
Global grad=CreateImage(256,1),mask=CreateImage(256,256)
Global p,p2,p3


; nice colors below ^_^
SetBuffer ImageBuffer(grad)
	For x=0 To 255
		c1=128+Sin((x*3)*256/360)*256
		c2=128+Sin((x*4)*256/360)*256
		c3=128+Sin((x*5)*256/360)*256
		Bcolor c1,c2,c3
		Plot x,0
	Next

SetBuffer CanvasBuffer(canvas)

timer=CreateTimer(35)
Repeat
	WaitEvent()
	If EventID()=$803 quit=True
	If EventID()=$4001
		blah()
		p=p+6
		p2=p2+5
		p3=p3+4
		FlipCanvas canvas
	EndIf
Until quit
SetBuffer DesktopBuffer() ; do we want nasty errors?    "NO, MASTER!"
End

Function blah() ; do the effect o_O
	Color 0,0,0
	For y=0 To 255
		v=128+Sin((x+y+p)*256/360)*128

		Viewport 0,y,256,1
		TileImage grad,v+p,y

		v1=Sin(((y+p2)*6)*256/360)*64
		v2=Sin(((y+p3)*5)*256/360)*64
		x1=v1+v2+64

		v1=Sin(((y+p3)*4)*256/360)*64
		v2=Sin(((y+p2)*7)*256/360)*64
		x2=v1+v2+192

		Line 0,y,x1,y
		Line x2,y,255,y
	Next
	Viewport 0,0,256,256
End Function


; misc handy stuff..
Function Bcolor(r,g,b)
	r=Limit(r,0,255)
	g=Limit(g,0,255)
	b=Limit(b,0,255)
	Color r,g,b
End Function

Function Limit(value,minvalue,maxvalue)
	If value<minvalue Return minvalue
	If value>maxvalue Return maxvalue
	Return value
End Function


Try this code out, don't run it with debug mode on or it will crawl! The time in the top left is how many millisecs the code takes to execute (31 on my PC). It can be optimised lots. Paste into notepad first and then into blitz to ensure it formats correctly.

Hey CS_TBL how do you get you code to appear in the scrollbox?

; -----------------------------------------------------------------------------
; JB Demo 0.1 JB 09/01/05
; -----------------------------------------------------------------------------
; Last Revision: 28/01/05
; -----------------------------------------------------------------------------

	Const GAMENAME$ = "JB Demo"
	Const VERSION$ = "V0.1"
	Const COPYRIGHT$ = " (c) 2005"
	Const FULLNAME$ = GAMENAME$ + " " + VERSION$ + COPYRIGHT$

	Const GAME_WIDTH = 640
	Const GAME_HEIGHT = 480

	Const ESCAPE = 1

;demo globals
	Global Amp# = 100
	Global AmpSpeed% = 5
	Global Phase = 0
	Global PhaseSpeed = 4
	Global WL# = 1
	Global WLSpeed# = 0.05
	Global MidY% = GAME_HEIGHT/2
	Global StartTime%
	Global EndTime%	
	Global MinCounter = 90
	Global MaxCounter = 170
	Global Counter = MinCounter
	Global CounterDir% = 1
	
;Note: Sin 0 = 0, 90 = 1, 180 = 0, 270 = -1

; -----------------------------------------------------------------------------
; Includes...
; -----------------------------------------------------------------------------

; -----------------------------------------------------------------------------
; Create a Graphics window...
; -----------------------------------------------------------------------------
	AppTitle FULLNAME ;do before graphics is called
	Graphics GAME_WIDTH, GAME_HEIGHT, 32
	SetBuffer BackBuffer()	
	SeedRnd MilliSecs()

; -----------------------------------------------------------------------------
; Main loop...
; -----------------------------------------------------------------------------
SetBuffer BackBuffer() ;vital

Local LoopExit = 0
Repeat 

	LoopExit = 0	

	Repeat
		;code here	
		Cls

		;drawcode goes here		
		StartTime = MilliSecs()
		DrawSinWaveBlurToEdgeAuto()
		EndTime = MilliSecs()

		;output time
		Color 255,255,255
		Text(10,10,EndTime-StartTime + " ms")

		If DoVWait Then VWait
		Flip False

		;escape key quits
		If (KeyHit (ESCAPE)) Then
			LoopExit = 1
		EndIf
	
	Until LoopExit <> 0
	
	;set LoopExit to 1 to exit the program
Until LoopExit = 1

;Exit the program
End

; -----------------------------------------------------------------------------
Function DrawSinWaveBlurToEdgeAuto()
		;31ms
		Local Start = 200
		Local m=2 ;multiplier
		LockBuffer 
		For i = 0 To GAME_WIDTH-1
			Col = MakeARGB(Start,0,0)
			x = i

			;get y coord		
			y = MidY+Sin(phase+(i/WL))*Amp
			For j = 0 To Start*m
				Col = MakeARGB((Start-j/m),j/m,(Start-j/m)+j/m)
				oy = y-j
				;limit coords to screen
				;y
				If oy < 0 Then
				  oy = 0
				Else
				  If oy >= GAME_HEIGHT Then
				     oy = 0
				  EndIf
				EndIf  
				;don't draw oy=0 pixels
				If oy > 0 Then WritePixelFast (x, oy, Col)
				oy = y+j
				;y again
				If oy < 0 Then
				  oy = 0
				Else
				  If oy >= GAME_HEIGHT Then
				     oy = 0
				  EndIf
				EndIf
				;don't draw oy=0 pixels
				If oy > 0 Then WritePixelFast (x, oy, Col)
			Next	   
		Next
		UnlockBuffer 

		Phase = Phase + PhaseSpeed
		Limit = 360
;		Limit = 360 * WL
		While Phase >= Limit
		  Phase = Phase - Limit
		Wend
		
		;pendulum counter
		Select CounterDir
			Case 1
				If Counter < MaxCounter-1 Then
					Counter = Counter + 1
				Else
					CounterDir = -1
					Counter = Counter - 1
				EndIf
			Case -1
				If Counter > MinCounter Then
					Counter = Counter - 1
				Else
					CounterDir = 1
					Counter = Counter + 1
				EndIf
		End Select
		
		WL = Sin(Counter)
		If WL < 0.0 Then
    	   WL = 0.0-WL ;reverse -ve
		EndIf
		If WL = 0 Then WL = 0.001 ;avoid divide by zero
		Amp = 150 * Sin(Counter)
End Function

; -----------------------------------------------------------------------------
; Take 3 colours and make ARGB Integer
; -----------------------------------------------------------------------------
Function MakeARGB%(R, G, B)
    Return R*256*256+G*256+B
End Function


how do you get you code to appear in the scrollbox?

<codebox>
</codebox>


<> = [] obviously ^_^


or:

CreateSlider()

^_^

Thanks dude, try this then for copper bars (just whipped it up) ... 4ms on my PS.

On the Amiga the copper bars could go from the far left of the screen to the far right and thus would display on areas you couldn't normally draw too. Also the copper was a co-processor that did its cool stuff independantly of the main CPU so your main code never slowed down. There were other co-processors such as for sound etc. The PC's architecture is a bit crap by comparison.

; -----------------------------------------------------------------------------
; JB Demo 0.1 JB 09/01/05
; -----------------------------------------------------------------------------
; Last Revision: 28/01/05
; -----------------------------------------------------------------------------

	Const GAMENAME$ = "JB Demo"
	Const VERSION$ = "V0.1"
	Const COPYRIGHT$ = " (c) 2005"
	Const FULLNAME$ = GAMENAME$ + " " + VERSION$ + COPYRIGHT$

	Const GAME_WIDTH = 640
	Const GAME_HEIGHT = 480

	Const ESCAPE = 1

;demo globals
	Const MAX_BARS = 5
	Const BAR_HEIGHT = 25
	Const BAR_RANGE = 200
	Dim BarCounter (MAX_BARS-1)
	;init bars
	For bar = 0 To MAX_BARS-1
		BarCounter(bar) = 90 + 20*(bar+1)
	Next	
		
;Note: Sin 0 = 0, 90 = 1, 180 = 0, 270 = -1
; -----------------------------------------------------------------------------
; Includes...
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; Create a Graphics window...
; -----------------------------------------------------------------------------
	AppTitle FULLNAME ;do before graphics is called
	Graphics GAME_WIDTH, GAME_HEIGHT, 32
	SetBuffer BackBuffer()	
	SeedRnd MilliSecs()

; -----------------------------------------------------------------------------
; Main loop...
; -----------------------------------------------------------------------------
SetBuffer BackBuffer() ;vital

Local LoopExit = 0
Repeat 

	LoopExit = 0	

	Repeat
		;code here		
		Cls

		;drawcode goes here
		StartTime = MilliSecs()
		CopperBars()
		EndTime = MilliSecs()

		;output time
		Color 255,255,255
		Text(10,10,EndTime-StartTime + " ms")

		If DoVWait Then VWait
		Flip False

		;escape key quits
		If (KeyHit (ESCAPE)) Then
			LoopExit = 1
		EndIf
	
	Until LoopExit <> 0
	
	;set LoopExit to 1 to exit the program
Until LoopExit = 1

;Exit the program
End

; -----------------------------------------------------------------------------
Function CopperBars()	
	For bar = 0 To MAX_BARS-1
		Local BarY = GAME_HEIGHT/2 - BAR_HEIGHT + Sin(BarCounter(bar))*BAR_RANGE
		For y = 0 To BAR_HEIGHT-1
			Color y*10,0,0
			Line 0,BarY+y, GAME_WIDTH, BarY+y
		Next
		For y = 0 To BAR_HEIGHT
			Color 250-(y*10),0,0
			Line 0,BarY+BAR_HEIGHT+y, GAME_WIDTH, BarY+BAR_HEIGHT+y
		Next
		BarCounter(bar) = BarCounter(bar) + 1
	Next
End Function



ah, I know that effect .. is that the official copper thing then?

christ that was a quick reply, I just edited my post, read a bit more. Copper was used for full screen coloured sine waves, bars like in my 2nd post, mirror effects under scrolling messages, colour cycling fractals, gradiated sky effects behind platformers (Turrican etc.) and much more, it was cool.

Why Not just Create an image to draw onto as the 'bar', and draw it at the relevent coordinates?

Yeah, aab, much faster; but I was still thinking in Amiga mode and it was quick and dirty. Also commonly the bars would be different colours. In fact I nearly coded it using lock buffer and writepixel and thought doh ... use Line as it is probably well optimised.

In fact here are some coloured copper bars

; -----------------------------------------------------------------------------
; JB Demo 0.1 JB 09/01/05
; -----------------------------------------------------------------------------
; Last Revision:
; -----------------------------------------------------------------------------

	Const GAMENAME$ = "JB Demo"
	Const VERSION$ = "V0.1"
	Const COPYRIGHT$ = " (c) 2005"
	Const FULLNAME$ = GAMENAME$ + " " + VERSION$ + COPYRIGHT$

	Const GAME_WIDTH = 640
	Const GAME_HEIGHT = 480

	Const ESCAPE = 1

	Global DoVWait = 1

;demo globals
	Const MAX_BARS = 5
	Const BAR_HEIGHT = 25
	Const BAR_RANGE = 200
	Dim BarCounter (MAX_BARS-1)
	;init bars
	For bar = 0 To MAX_BARS-1
		BarCounter(bar) = 90 + 20*(bar+1)
	Next	
		
;Note: Sin 0 = 0, 90 = 1, 180 = 0, 270 = -1
; -----------------------------------------------------------------------------
; Includes...
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; Create a Graphics window...
; -----------------------------------------------------------------------------
	AppTitle FULLNAME ;do before graphics is called
	Graphics GAME_WIDTH, GAME_HEIGHT, 32
	SetBuffer BackBuffer()	
	SeedRnd MilliSecs()

; -----------------------------------------------------------------------------
; Main loop...
; -----------------------------------------------------------------------------
SetBuffer BackBuffer() ;vital

Local LoopExit = 0
Repeat 

	LoopExit = 0	

	Repeat
		;code here		
		Cls

		;drawcode goes here
		StartTime = MilliSecs()
		ColouredCopperBars()
		EndTime = MilliSecs()

		;output time
		Color 255,255,255
		Text(10,10,EndTime-StartTime + " ms")

		If DoVWait Then VWait
		Flip False

		;escape key quits
		If (KeyHit (ESCAPE)) Then
			LoopExit = 1
		EndIf
	
	Until LoopExit <> 0
	
	;set LoopExit to 1 to exit the program
Until LoopExit = 1

;Exit the program
End

; -----------------------------------------------------------------------------
Function ColouredCopperBars()
	
	For bar = 0 To MAX_BARS-1
		Local BarY = GAME_HEIGHT/2 - BAR_HEIGHT + Sin(BarCounter(bar))*BAR_RANGE
		For y = 0 To BAR_HEIGHT-1
 			SetBarColour(bar, y*10)
			Line 0,BarY+y, GAME_WIDTH, BarY+y
		Next
		For y = 0 To BAR_HEIGHT
 			SetBarColour(bar, 250-(y*10))
			Line 0,BarY+BAR_HEIGHT+y, GAME_WIDTH, BarY+BAR_HEIGHT+y
		Next
		BarCounter(bar) = BarCounter(bar) + 1
	Next
End Function

; -----------------------------------------------------------------------------
Function SetBarColour(bar, col)
	Select bar Mod 6
		Case 0 Color col,0,0
		Case 1 Color 0, col,0
		Case 2 Color 0, 0, col
		Case 3 Color col, 0, col
		Case 4 Color col, col, 0
		Case 5 Color 0, col, col
	End Select
End Function


use Line as it is probably well optimised
Actually not. A Rect only 1 pixel thick is 70% faster than a Line.

wow, I guess that's because the line may have an end point not on the same line and a rect just draws a block.

ok .. lame .. but it's small code :)
window=CreateWindow("B+ bars -- by CS^TBL",100,100,400,300,0,1)
canvas=CreateCanvas(1,1,2,240,window):SetGadgetShape canvas,4,4,320,240
Global f1

timer=CreateTimer(100)
SetBuffer CanvasBuffer(canvas)
Repeat
	WaitEvent()
	If EventID()=$803 quit=True
	If EventID()=$4001
		blah():	f1=f1+1:FlipCanvas canvas
	EndIf
Until quit
SetBuffer DesktopBuffer()
End

Function blah()
	For t=0 To 7
		p=120+Sin((f1+t*4)*2)*116
		Color 0,t*35,0:	Rect 0,p-4,1,8
		Color 255,0,(t*35):	Rect 1,p-4,1,8
	Next
End Function