magazine logo
Welcome to the official Attitude website - Europe's #1 C64 scene disk magazine
by Puterman/Fairlight

Cactus wanted me to write something about some effect that uses maths in some way, so I'll walk you through the smoke effect in "We/Laser" and also bore you with some of my views on how to do maths stuff in general.

A problem with doing maths on the C-64 is that it's slow, so you really want to do as little of it as possible. So whenever it's possible, use a table instead of calculating stuff. To paraphrase Dragan in the movie "Black Cat White Cat": if you can't do it with tables, do it with more tables.

I guess most people start with an effect idea, figure out how to make a naive implementation and then start thinking about optimizations to get it to run at a decent speed. (What is considered decent speed varies, but I usually try to keep it at a maximum of 2 frames. It depends on the effect in question too, of course.) My method is sometimes a bit different. I skip the step with the realtime calculations and start thinking in terms of tables immediately. That way I gain a lot of time and avoid a few headaches. Sometimes it helps a lot if you're stupid.

So, after a couple of paragraphs of simple-minded philosophizing, let's move on to the effect, the smoke part in "We/Laser". I'll assume that you know what it looks like. No, what the heck, here's a description: smoke coming out of a chimney, done with a plotter.

One day I was walking home from my job, which is in an industrial area, when I suddenly looked up and saw a chimney with smoke bellowing out of it. I looked at it and thought "that shouldn't be too hard to implement". Note how I didn't even have to make the association from the actual smoke to coding, it went naturally. I might be turning into a cyborg.

My reasoning went on in a way which probably resembled this: let's say you have a bunch of points in 2D space. Let's say they all start in the same place (the top of the chimney), all you have to do to make a smoke effect is to make them move upwards and sideways, a bit randomly. Easy-peasy, right? Yep, I wasn't sure if it would actually look good, but it was a good enough idea to try out.

An important question was of course how to make the movement look like smoke, but like all difficult questions, I thought, it could easily be solved with some trial and error. Well, I did some thinking as well, and like most other people would, I came to the conclusion that the points should move in different ways along the x and y axes.

A point should move a small distance upwards each frame, to make the smoke move upwards, and it should move a little bit to either the left or the right. That means you need 2 additions per point and frame, using 2 different tables: one for the y movement and another one for the x movement.

The y table should contain the values 0 or 1, spread out at random, to make a point move either 1 pixel upwards or not move at all vertically. The x table should contain the values 1, 0 and -1, to make the point move either 1 pixel to the left, 1 to the right or not move at all.

Then you'd just need to change the offsets into this table each frame, and have a different offset for each point. The movement will still look a bit static, though, as you'll cycle through the table pretty quickly, so to make it look a bit better you swap the values back and forth a bit within the tables.

Now there's the question of how to set up these tables. What I did was to use the BASIC ROM as a random table, used $dc04 (the low byte of CIA 1 timer) to index into the ROM, and then I masked out some bits to get the desired values. After some trial and error I found some areas of the ROM that made it look good. And as an added bonus, the tables will be different from time to time.

When we have the tables, all that remains is to write some fast plot code, so that we can cram as much plots into a maximum of 2 frames as possible. (I tried running the effect in 3 frames, but it was too slow to look good.) I plot into the usual 16x16 chars area (although it's actually smaller than that, because the smoke will never reach the right and left parts of the area, but this only affects the code that clears the plot area), and the plot code looks something like this:

ldy xtab ; x coord
lda xlo,y ; low byte of base x address to plot into
sta ozplo ; put that in a zero page address
lda (xzplo),y ; high byte, changes each turn (doublebuffering)
sta ozphi ; put that in ozplo+1
lda what,y ; the bit to plot into that byte
ldy ytab ; y coord
ora (ozplo),y ; OR with contents in byte
sta (ozplo),y ; STA OR-ed value

That code plots one point, and takes 38 cycles. But this isn't everything that has to be done each round, the x and y tables also have to be updated. The code that does that is really straight forward:

lda xtab
adc xadd,x
sta xtab
lda ytab
adc yadd,x
sta ytab

That takes 30 cycles, so each point takes 68 cycles. Both of these code chunks are then repeated 352 times (generated speedcode).

Returning to the introduction of the article now, to wrap it up nicely, I pointed out that maths is slow, so you want to do as little of it as possible. As you can see, the effect described here uses no serious maths as all, and the physical model that's implemented is very simplified.

That's about it for this article, I guess, so now I won't bother you anymore until the next issue of Attitude.


   Add/view comments on this article (comments: 0)

Do you believe we are
able to cope with
releasing "Attitude"
on a regular basis?

yes no

 YES: 292 (71.22%)
NO:118 (28.78%) 



all visits:

visits today:

website started:
Official Webpage
of Attitude
Copyright 2004-2018