|
Author |
Message |
motorcross
Member |
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 |
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 |
@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 |
@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 |
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 |
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 |
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 |
@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 |
@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.
|
|
|