A.D.A. Amiga Demoscene Archive

  Welcome guest! Please register a new account or log in

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / How to code this demo effects?

 

Author Message
motorcross
Member
#1 - Posted: 26 Jun 2007 16:28 - Edited
Reply Quote
Hello. This is my first posting here. i saw a lot of amiga demos and i must really say, amiga is an amazing great machine! I am interested in motor-cross sport and demo coding.

My biggest attention is going to learn how to code the following demo effects on the screenshots and their effect names.

Actually i am trying to learn coding using Basic languages, because its easy to code and help me to understand some stuff.

Using google i found an very old and incomplete article about coding demo effects like tunnels and others. The author wrote that all this effects are basically very simple to code and all effects are using the same mainloop with just different filled arrays? How is this possible? o_O













If someone knows how to code one of this or any other effect based on this technique, please use basic styled code =) thanks
motorcross
Member
#2 - Posted: 27 Jun 2007 11:40 - Edited
Reply Quote
okay, i found a small tutorial to code a tunnel effect and i get it work... it runs very slow here... possible there are other ways to speed up the table based tunnel effect?

If you may share any for/next loop to generate other tablebased effects, it would be cool!



; ---------- Code to generate tables for free directional tunnel effect ----------

lTextureSize.l = 256
lScreenWidth.l = 640
lScreenHeight.l = 480

Dim aTexture (lTextureSize , lTextureSize )
Dim aDistance (lScreenWidth*2, lScreenHeight*2)
Dim aAngle (lScreenWidth*2, lScreenHeight*2)
Dim aBuffer (lScreenWidth , lScreenHeight )

; -------- Generating Mapping Texture --------

For x.l = 0 To lTextureSize -1
For y.l = 0 To lTextureSize -1
aTexture(x,y) = (x * 256 / lTextureSize) ! (y * 256 / lTextureSize)
Next
Next

; -------- Generating Distance and Angle Table --------

dDistance.d = 32.0
dParts.d = 0.5

For x = 0 To lScreenWidth*2 -1
For y = 0 To lScreenHeight*2 -1
aDistance(x,y) = Int(dDistance * lTextureSize / Sqr( (x-lScreenWidth) * (x-lScreenWidth) + (y-lScreenHeight) * (y-lScreenHeight) )) % lTextureSize
dAngle.d = (dParts * lTextureSize * ATan2(y-lScreenHeight, x-lScreenWidth) / #PI)
aAngle(x,y) = Int (256 - dAngle) & 255
Next
Next




; ---------- This is the mainloop (slow) ----------

dSpeedX.d = 2.0
dSpeedY.d = 2.0

Repeat
; ------- Stuff for doing the animation -------

dAnimation.d = dAnimation.d + 0.005

lShiftX.l = Int(lTextureSize * dSpeedX.d * dAnimation.d)
lShiftY.l = Int(lTextureSize * dSpeedY.d * dAnimation.d)

lLookX = lScreenWidth /2 + Int(lScreenWidth /2 * Sin(dAnimation * 4.0 ))
lLookY = lScreenHeight/2 + Int(lScreenHeight/2 * Sin(dAnimation * 6.0 ))

; -------- Calculate Texture coordinates and draw Tunnel -------

For y = 0 To lScreenHeight-1
For x = 0 To lScreenWidth -1
lCoordinateX.l = (aDistance(x+lLookX, y+lLookY) + lShiftX) % lTextureSize
lCoordinateY.l = (aAngle (x+lLookX, y+lLookY) + lShiftY) % lTextureSize
aBuffer(x,y) = aTexture (lCoordinateX.l , lCoordinateY.l)
DrawPixel (x, y, RGB( aBuffer(x,y) 0, 0,) )
Next
Next

FlipScreen()
Until GetAsyncKeyState(VK_ESCAPE)




I understand the source but i have no idea how to optimize things to speed it up nor how to change the tabledatas to get another effect as the tunnel. Any ideas or examples? ;-)
z5_
Member
#3 - Posted: 27 Jun 2007 12:44
Reply Quote
@motorcross: first welcome :o) Can't help you with the code (too advanced for me) but i was wondering: what platform are you coding on?
motorcross
Member
#4 - Posted: 27 Jun 2007 14:35
Reply Quote
@z5_:
Thanks :o) First i am trying to code and learn things using Windows and basic coding languages. I use this way, because its more easy and you donīt must wait so long to see any (animated) results. Then i try to port the source to the Amiga.
sp_
Member
#5 - Posted: 27 Jun 2007 22:47
Reply Quote
No time to give you a complete guide but here you have an idea what the realtime loops can look like:

Mc680x0 assembly:

.loop
move.w (a0,d0.w),d1
move.b (a1,d1.w),(a2)+
dbf d7,.loop

C++:

for(int i=0;i<width*height;i++)
{
int offset=precalc[i];
chunky[i}=texture[offsett];
}
motorcross
Member
#6 - Posted: 27 Jun 2007 23:45
Reply Quote
for(int i=0;i<width*height;i++)
{
int offset=precalc[i];
chunky[i}=texture[offsett];
}


??? How does the precalc[] and chunky[] arrays does look like? only one loop instead one for x and one for y? O_O (any psydo basic source would be great) thanks!
Kalms
Member
#7 - Posted: 28 Jun 2007 00:55 - Edited
Reply Quote
The demonstrated C-code depends on the fact that all the 2D arrays can be accessed as long 1D arrays in C/assembly.

I.e.

table[y][x] can be converted into table[y * width + x] assuming that it is a rectangular 2d table.

And scrolling, as in:

table[y + offsety][x + offsetx] can be converted into table[(y + offsety) * width + x + offsetx]

And finally, stop doing those "% lTextureSize" and 1) ignore the wraparound totally or (when that doesn't work) 2) make tables bigger.



1a. Start with a simple, static tunnel


For y = 0 To lScreenHeight-1
For x = 0 To lScreenWidth -1
lCoordinateX.l = (aDistance(x, y)) % lTextureSize
lCoordinateY.l = (aAngle (x, y)) % lTextureSize
color = aTexture (lCoordinateX.l , lCoordinateY.l)
DrawPixel (x, y, RGB( color, 0, 0) )
Next
Next


1b. Rewrite this into a 1-dimensional loop:

Dim aTexture2 (lTextureSize * lTextureSize)

;-- precalc
For i = 0 To lTextureSize*lTextureSize-1
u = i % lTextureSize
v = (i - u) / lTextureSize
aTexture2(i) = aTexture(u, v)
Next

For i = 0 To lScreenHeight*lScreenWidth-1
x = i % lScreenWidth
y = (i - x) / lScreenWidth
aOffset(i) = aAngle(x, y) * lTextureSize + aDistance(x, y)
Next

;-- draw tunnel
For i = 0 To lScreenHeight*lScreenWidth-1
x = i % lScreenWidth
y = (i - x) / lScreenWidth
lCoordinateXY.l = aOffset(i)
color = aTexture2(aOffset)
DrawPixel (x, y, RGB( color, 0, 0) )
Next



2a. Tunnel + angle/z scroll

For y = 0 To lScreenHeight-1
For x = 0 To lScreenWidth -1
lCoordinateX.l = (aDistance(x, y) + distOffset) % lTextureSize
lCoordinateY.l = (aAngle (x, y) + angleOffset) % lTextureSize
color = aTexture (lCoordinateX.l , lCoordinateY.l)
DrawPixel (x, y, RGB( color, 0, 0) )
Next
Next

2b. Tunnel + angle/z scroll, 1D

Dim aTexture2 (lTextureSize * lTextureSize * 2)

;-- precalc
For i = 0 To lTextureSize*lTextureSize*2-1
u = i % lTextureSize
v = ((i - u) / lTextureSize) % lTextureSize
aTexture2(i) = aTexture(u, v)
Next

For i = 0 To lScreenHeight*lScreenWidth-1
x = i % lScreenWidth
y = (i - x) / lScreenWidth
aOffset(i) = aAngle(x, y) * lTextureSize + aDistance(x, y)
Next

;-- draw tunnel
offset = angleOffset * lTextureSize + distOffset

For i = 0 To lScreenHeight*lScreenWidth-1
x = i % lScreenWidth
y = (i - x) / lScreenWidth
lCoordinateXY.l = aOffset(i)
color = aTexture2(aOffset + offset)
DrawPixel (x, y, RGB( color, 0, 0) )
Next


If you are using C, then the 'draw tunnel' loop can be turned into what sp posted by replacing DrawPixel with a simple assignment into the 'screen pixel array' (which can also be accessed 1-dimensionally) and eliminating unnecessary computations.

It's difficult to pinpoint where most of your time is being spent. Try making aTexture() contain RGB triplets already -- perhaps copying around those is quicker than copying around single values and building the RGB triplets per-pixel.
motorcross
Member
#8 - Posted: 29 Jun 2007 10:50
Reply Quote
@Kalms:
First i have to thanks a lot for your great and very good explained sources! There was a small bug in your example source but i managed to get it work now. Its amazing, because the tunnel works now up to 20% faster, wow!

I have tried to understand the modified source and i will try to optimize the actual source length if possible. However there is one codingline i dont really understand. Why and what are you calculating this way and where do you got the algo from? ^^

aOffset(i) = aAngle(x, y) * lTextureSize + aDistance(x, y)



The tunnel is moving and rotating nice... to get back the free directional view, i have just to add following lines again? Or is there any way to change and optimize this too? ^^

dAnimation.d = dAnimation.d + 0.005

lShiftX.l = Int(lTextureSize * dSpeedX.d * dAnimation.d)
lShiftY.l = Int(lTextureSize * dSpeedY.d * dAnimation.d)

lLookX = lScreenWidth /2 + Int(lScreenWidth /2 * Sin(dAnimation * 4.0 ))
lLookY = lScreenHeight/2 + Int(lScreenHeight/2 * Sin(dAnimation * 6.0 ))



Many thanks Kalms! *thumbs up*
Kalms
Member
#9 - Posted: 29 Jun 2007 13:32
Reply Quote
@motorcross:

aTexture2 is lTextureSize*lTextureSize pixels in size. In aTexture2, going "1 pixel down" is equivalent to going lTextureSize pixels horizontally. Let's refer to the distance between the first pixel in the first 'row' and the first pixel in the second 'row' as the stride, or the pitch. The stride for aTexture2 is lTextureSize.

aOffset contains X- and Y-displacements into aTexture2. Therefore, each x-displacement is encoded as an offset of (xDisplacement) units, and each y-displacement is encoded as an offset of (yDisplacement * stride) units. That's where the expression for aOffset() computations comes from.

As for movement... You will have to compute a similar offset for where you fetch from the aOffset array in the per-pixel drawing loop.

 

  Please register a new account or log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0