Acorn Arcade forums: Programming: Take two
|
Take two |
|
This is a long thread. Click here to view the threaded list. |
|
Andrew |
Message #63188, posted by andrew at 20:04, 10/3/2005 |
Handbag Boi
Posts: 3439
|
Here are some gfx and shots from the cave-demo I was working on:
http://web.ukonline.co.uk/a.weston2/programs/vic1.png
http://web.ukonline.co.uk/a.weston2/programs/vic2.png
Here's the total map (1806x the size of the screen!): http://web.ukonline.co.uk/a.weston2/programs/mapFS.png
[Edited by andrew at 00:55, 11/3/2005] |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #63190, posted by Phlamethrower at 20:30, 10/3/2005, in reply to message #63188 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
<img src="url">
Looks good, but the large map is a bit... simple |
|
[ Log in to reply ] |
|
Andrew |
Message #63210, posted by andrew at 13:56, 11/3/2005, in reply to message #63190 |
Handbag Boi
Posts: 3439
|
Well the idea behind the map was to have it generated by an algorithm and technically it can be generated on-the-fly although that would make it extremely slow as it uses sine/cosine. Therefore it creates a lookup table of bits (~36K). There was one map when I was playing about with the generator that was incredibly complex and looked like a vast cave network with a vertical shaft going all the way to the bottom and 'tunnels' emerging at the sides but it would have made it impossible to navigate. So I opted for this which although less complex is easier to fly about in |
|
[ Log in to reply ] |
|
Tony Haines |
Message #63211, posted by Loris at 17:19, 11/3/2005, in reply to message #63210 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
Moral of the story - don't use sin or cosine in on-the-fly generation.
Seriously, Andrew, if you want help generating a suitable, big, interesting-looking map let me know.
(I'm not disparaging what you've done - keep working on it.)
[Edited by Loris at 17:21, 11/3/2005] |
|
[ Log in to reply ] |
|
Lewis Westbury |
Message #63212, posted by instantiator at 17:33, 11/3/2005, in reply to message #63211 |
Member
Posts: 365
|
tables? |
|
[ Log in to reply ] |
|
Andrew |
Message #63220, posted by andrew at 01:14, 12/3/2005, in reply to message #63212 |
Handbag Boi
Posts: 3439
|
Thanks for the offer. I found it v.difficult to get interesting patterns without using polar calculations but I didn't want to nab anybody's formula although there was a random no. generator I was going to try. It's not a problem really having a lookup table in terms of size although finding bits might impose an overhead. |
|
[ Log in to reply ] |
|
Jason Tribbeck |
Message #63256, posted by tribbles at 23:59, 12/3/2005, in reply to message #63220 |
Captain Helix
Posts: 929
|
Mmmm ... tables...
For ArcCommand (and Equinox), I have sin tables, and an arctan table (cos is derived from sin).
The sin table contains 256 fixed-point values, although everything is actually 32-bit (only uses top 24-bits for sin). This means you don't need to worry about overflow when you're rotating anything, and you get enough accuracy in the value so it doesn't look jerky.
Arctan is used to calculate the angle something needs to be at in order for it to point at something else. My implementation of that algorithm is actually very quick (if you aren't interested in being 100% accurate). The table size is also surprisingly small.
This is ultimately used by the seeking missiles, and enemies that need to track where you are.
Equinox uses random polar coordinates for enemy generation, with 4 different values:
- start angle - delta angle - start distance - delta distance
With these variables, you can create objects at individual points, rings around the player, or randomly. |
|
[ Log in to reply ] |
|
Andrew |
Message #63273, posted by andrew at 15:55, 13/3/2005, in reply to message #63256 |
Handbag Boi
Posts: 3439
|
Why 256 values? |
|
[ Log in to reply ] |
|
Adrian Lees |
Message #63275, posted by adrianl at 16:55, 13/3/2005, in reply to message #63273 |
Member
Posts: 1637
|
Why 256 values? Most probably because if your angles are then in units of 1/256th of a cycle (full circle) then you can look up a value by using modulo arithmetic (sine functions are periodic) which is very cheap for powers of two. int sin_table[256]; draw(sin_table[(theta + 64) & 0xff], sin_table[theta & 0xff]); The +64 gives a phase shift, ie. a cosine function rather than have two separate tables of values. Clear as mud?
[Edited by adrianl at 16:57, 13/3/2005] |
|
[ Log in to reply ] |
|
Andrew |
Message #63286, posted by andrew at 20:13, 13/3/2005, in reply to message #63275 |
Handbag Boi
Posts: 3439
|
What is 1/256th in degrees/radians though? |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #63288, posted by Phlamethrower at 20:22, 13/3/2005, in reply to message #63286 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
1/256th would be 360/256 in degrees, or 2*PI/256 in radians. Not that hard to work out, eh? |
|
[ Log in to reply ] |
|
Andrew |
Message #63299, posted by andrew at 23:10, 13/3/2005, in reply to message #63288 |
Handbag Boi
Posts: 3439
|
what I mean is why would your angles be in units of 1/256th of a circle? |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #63302, posted by Phlamethrower at 23:22, 13/3/2005, in reply to message #63299 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
The main reason as I see it is that you won't have to worry about rounding large angles down so that they lie in a 0-360 degree range. All you'll have to do is AND the angle with 255 and look up the result in the table. |
|
[ Log in to reply ] |
|
Adrian Lees |
Message #63303, posted by adrianl at 23:31, 13/3/2005, in reply to message #63302 |
Member
Posts: 1637
|
The main reason as I see it is that you won't have to worry about rounding large angles down so that they lie in a 0-360 degree range. All you'll have to do is AND the angle with 255 and look up the result in the table. Indeed. If you already know that your angle lies between 0 and 360 degrees then there's no merit to choosing a power of two. If, however, your angle can be any number, then it's more efficient to use a power of two because that 'rounding down' process involves a division which is expensive, but division by any power of two is cheap - it becomes a right-shift, and remainder becomes a bitwise AND. |
|
[ Log in to reply ] |
|
Tony Haines |
Message #63332, posted by Loris at 17:51, 14/3/2005, in reply to message #63299 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
Jeffry and Adrian are correct - powers of 2 have binary advantages, but to add to that : perhaps you should be asking yourself "why 360?" 256 also has the property of fitting in a byte, which is often useful, and there is of course the ARM constant issue. But if you need more accuracy, use more bits!
Why did you start using trig. functions in the first place - could you give us some idea of what sort of map you really want? I think you want large caverns, but are there any other desires? |
|
[ Log in to reply ] |
|
Jason Tribbeck |
Message #63337, posted by tribbles at 21:47, 14/3/2005, in reply to message #63302 |
Captain Helix
Posts: 929
|
The main reason as I see it is that you won't have to worry about rounding large angles down so that they lie in a 0-360 degree range. All you'll have to do is AND the angle with 255 and look up the result in the table. Actually, I store it as a full 32-bit value, which means if you want to rotate by, say, 43 bradians (binary radians ), then you just do:
ADD r0, r0, #43<<24
You don't need to worry if you've gone over 255, or under 0. It also gives you a heck of a lot of accuracy (should you need it).
Reading from the SIN table is fairly easy:
MOV r0, r0, LSR#24 LDR r0, [r1, r0, LSL#2]
Reading the COS value from the SIN table is also fairly easy:
ADD r0, r0, #64 << 24 MOV r0, r0, LSR#24 LDR r0, [r1, r0, LSL#2]
Any more, and this should be in programming
[Edited by tribbles at 21:50, 14/3/2005] |
|
[ Log in to reply ] |
|
Richard Goodwin |
Message #63345, posted by rich at 00:25, 15/3/2005, in reply to message #63337 |
Dictator for life
Posts: 6828
|
I can move it if you wish... ________ Cheers, Rich.
|
|
[ Log in to reply ] |
|
Adrian Lees |
Message #63348, posted by adrianl at 10:30, 15/3/2005, in reply to message #63337 |
Member
Posts: 1637
|
Reading the COS value from the SIN table is also fairly easy:
ADD r0, r0, #64 << 24 MOV r0, r0, LSR#24 LDR r0, [r1, r0, LSL#2] For the benefit of anybody else using this technique, you can avoid the ADD instruction by replicating the first 90 degrees worth of table at the table end, so you have 450 degrees of data, and then adjusting the value of r1.
This is more efficient if you do a lot of COS lookups in a row, or can spare a register to have one COS table base and one SIN table base. |
|
[ Log in to reply ] |
|
Tony Haines |
Message #63352, posted by Loris at 12:09, 15/3/2005, in reply to message #63348 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
ADD r0, r0, #64 << 24 MOV r0, r0, LSR#24 LDR r0, [r1, r0, LSL#2] For the benefit of anybody else using this technique, you can avoid the ADD instruction by replicating the first 90 degrees worth of table at the table end, so you have 450 degrees of data, and then adjusting the value of r1.
Ppht. too slow. One should insert other useful instructions between the MOV and LDR if possible, since memory accesses are slower if the regs are adjusted in preceeding ops. |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #63357, posted by Phlamethrower at 12:58, 15/3/2005, in reply to message #63352 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
Just for completeness, here's the code from WOUM for the 16.16 fixed-point sin/cos functions. They accept angles in degrees as input, and return results within +/- 1/65536th of the correct value (Possibly +/- 2/65536th on one or two values, I can't remember). f1616_costabptr points to a 1441 entry table containing the values of cos 0 to cos 90 in 16.16 format, each entry being one 16th of a degree.
f1616_sin ; r0=in,r0=out ; since sin x=cos (x-90)... SUB R0,R0,#90*65536 f1616_cos ; R0=angle, returns value CMP R0,#0 RSBLT R0,R0,#0 ; Make positive f1616_cos_loop CMP R0,#360*65536 SUBGE R0,R0,#360*65536 BGT f1616_cos_loop MOV R1,R0,LSR #12 ; Get location in table SUB R0,R0,R1,LSL #12 ; Get interpolation factor ADD R2,R1,#1 ; Location of 2nd value ; Work out quadrant CMP R1,#180*16 RSBGE R1,R1,#360*16 ; Reflect if >180 RSBGE R2,R2,#360*16 CMP R1,#90*16 CMPGE R2,#90*16 RSBGE R1,R1,#180*16 ; Reflect again RSBGE R2,R2,#180*16 LDR R3,f1616_costabptr LDR R1,[R3,R1,LSL #2] LDR R2,[R3,R2,LSL #2] MUL R2,R0,R2 RSB R0,R0,#4096 MLA R1,R0,R1,R2 RSBGE R1,R1,#0 ; Negate answer if needed MOV R0,R1,ASR #12 ; Back to 16.16 MOV PC,R14
And for the benefit of Adrian, no this hasn't been heavily optimised yet (Although I did just spot a couple of inefficiencies and update the code )
I did have some code knocking around for representing angles as fractions from 0-1, but it translates them into another format before looking up the result
[Edited by Phlamethrower at 13:38, 15/3/2005] |
|
[ Log in to reply ] |
|
Adrian Lees |
Message #63360, posted by adrianl at 13:24, 15/3/2005, in reply to message #63352 |
Member
Posts: 1637
|
One should insert other useful instructions between the MOV and LDR if possible, since memory accesses are slower if the regs are adjusted in preceeding ops. Do you mean that there's an extra cycle of result latency because r0 is shifted by an immediate constant in the LDR instruction? True. LDRs aren't delayed by any old write to their source registers in the preceding instruction, it's just for shifted operands (and just on XScale).
You don't want to go using the result of the LDR within the next 2 cycles, however. (XScale, 1 cycle on SA)... leave it as late as possible, in fact; the data may not be cached! |
|
[ Log in to reply ] |
|
Jason Tribbeck |
Message #63361, posted by tribbles at 13:51, 15/3/2005, in reply to message #63352 |
Captain Helix
Posts: 929
|
ADD r0, r0, #64 << 24 MOV r0, r0, LSR#24 LDR r0, [r1, r0, LSL#2] Ppht. too slow. One should insert other useful instructions between the MOV and LDR if possible, since memory accesses are slower if the regs are adjusted in preceeding ops. <sarcastic>Aha, so the whole reason why my game is too slow is because I'm wasting cycles.
Wow! I was thinking it's that silly "C" stuff, with all its bloat-code around entry and exit procedures. Thanks for the tip!</sarcastic>
|
|
[ Log in to reply ] |
|
Tony Haines |
Message #63365, posted by Loris at 15:05, 15/3/2005, in reply to message #63360 |
Ha ha, me mine, mwahahahaha
Posts: 1025
|
One should insert other useful instructions between the MOV and LDR if possible, since memory accesses are slower if the regs are adjusted in preceeding ops. Do you mean that there's an extra cycle of result latency because r0 is shifted by an immediate constant in the LDR instruction? True. LDRs aren't delayed by any old write to their source registers in the preceding instruction, it's just for shifted operands (and just on XScale).
There is result delay too, of course. I was remembering some trials that - I think it was Icebird - did. He found that LDRs were affected by their addressing operands changing. This is different to what Acorn stated. Can't seem to access the website now, so I can't check. Didn't do my own trials on this, and it was a long time ago, so more recent processors may exhibit different behaviour. Although given that the more recent ARMs seem to have more dependencies, they may not.
You don't want to go using the result of the LDR within the next 2 cycles, however. (XScale, 1 cycle on SA)... leave it as late as possible, in fact; the data may not be cached! Does moving it beyond 2 instructions change anything? I understood that if it wasn't cached the processor would pause anyway.
<sarcastic>Aha, so the whole reason why my game is too slow is because I'm wasting cycles.
Wow! I was thinking it's that silly "C" stuff, with all its bloat-code around entry and exit procedures. Thanks for the tip!</sarcastic> Yeah, slowcoach!
You're right of course, and it really doesn't matter that much unless its in the inner loop anyway.
[Edited by Loris at 15:06, 15/3/2005] |
|
[ Log in to reply ] |
|
Andrew |
Message #63385, posted by andrew at 20:05, 15/3/2005, in reply to message #63345 |
Handbag Boi
Posts: 3439
|
I can move it if you wish... Did you mean to post this in the '2's complement' thread? |
|
[ Log in to reply ] |
|
Andrew |
Message #63386, posted by andrew at 20:16, 15/3/2005, in reply to message #63332 |
Handbag Boi
Posts: 3439
|
Jeffry and Adrian are correct - powers of 2 have binary advantages, but to add to that : perhaps you should be asking yourself "why 360?" 256 also has the property of fitting in a byte, which is often useful, and there is of course the ARM constant issue. But if you need more accuracy, use more bits! Why did you start using trig. functions in the first place - could you give us some idea of what sort of map you really want? I think you want large caverns, but are there any other desires? The problem isn't the looking up it's just the storage of negative values which I refer to in a previous thread. It's a useful tip though should I need more angles calculated as it is important to remember the phase-shift AL refers to. It's easy to forget the relationships between angles, pythagoras, nomenclature etc.
As I said above I used trig. functions as I found it difficult to create the kind of map I was after, otherwise. The sin and cos lookups (other post) that I am talking about are for something else in the program. The map generator I have ended up storing the result of as a 36K table as I said above. The intention was to create the map on-the-fly but the trig. functions I feared would slow it down too much (although yes I could have a lookup).
The kind of map I was aiming for was shafts and tunnels with caverns but I'm fairly happy with the map personally. However I was going to ask you today about how in Exile bits of scenery might have been generated by the algorithm. Surely they weren't all stored in terms of positions? |
|
[ Log in to reply ] |
|
Adrian Lees |
Message #63390, posted by adrianl at 23:33, 15/3/2005, in reply to message #63365 |
Member
Posts: 1637
|
He found that LDRs were affected by their addressing operands changing. This is different to what Acorn stated. Can't seem to access the website now, so I can't check. OK, I'm only going on the documented performance in the datasheets. As an aside, the XScale makes it a lot easier to actually measure the performance of instruction sequences because of its lovely cycle counter
Does moving it beyond 2 instructions change anything? I understood that if it wasn't cached the processor would pause anyway. TBH I'm not entirely certain. Logically there's no reason for the LDR to stall subsequent instructions unless they require the result, the updated base or the pipeline stage that the LDR occupies (ie. another LDR/STR op), though it could complicate exception handling. I may have a look at this when I've got something better to do
[Edited by adrianl at 23:34, 15/3/2005] |
|
[ Log in to reply ] |
|
Richard Goodwin |
Message #63404, posted by rich at 09:30, 16/3/2005, in reply to message #63385 |
Dictator for life
Posts: 6828
|
I can move it if you wish... Did you mean to post this in the '2's complement' thread? No, the Programming section that you mentioned in your previous post. ________ Cheers, Rich.
|
|
[ Log in to reply ] |
|
Jason Togneri |
Message #63406, posted by filecore at 10:22, 16/3/2005, in reply to message #63404 |
Posts: 3868
|
Yeah, programming would be better. It's also of use perhaps to other programmers who wouldn't otherwise come into the Playpen... ;-) and it's boring to those of us (just me?) who aren't really that interested in programming - or not this specific thing at least. Do it without telling anybody, confuse the buggers :-o |
|
[ Log in to reply ] |
|
15:45, 16/3/2005 - At this point the thread was moved from The Playpen to Programming by rich |
|
Andrew |
Message #63422, posted by andrew at 01:10, 17/3/2005, in reply to message #63404 |
Handbag Boi
Posts: 3439
|
I can move it if you wish... Did you mean to post this in the '2's complement' thread? No, the Programming section that you mentioned in your previous post. Yes but that post was in the 2's complement thread was it not? |
|
[ Log in to reply ] |
|
Pages (2): 1
> >|
|
Acorn Arcade forums: Programming: Take two |
|