bogax
-
Content Count
902 -
Joined
-
Last visited
Posts posted by bogax
-
-
Mountain King's version of mutisprite
Added rand16
_COLUP1 instead of COLUP1
player1x<9
player1y = (rand&63)+16
moved JUMP2
bytes are 8 bits
bits 0..7 (right to left) are powers of 2
2^0 = 1
2^1 = 2
2^2 = 4
2^3 = 8
etc
AND is (bits)
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1
& is a bitwise AND (bytes a & b = c, bits a0 AND b0 = c0, a1 AND b1 = c1, etc)
63 = 00111111 = 32 + 16 + 8 + 4 + 2 + 1
76 = 01001100 = 64 + 8 + 4
you'll only get a bit where you've got two ones
so ANDing something with 76 will only give you numbers
that are the sum of three of 64, 8, 4, 0, 0, 0 (the corresponding power of 2 or 0, for each bit)
that's 8 different possibilities (3 bits set, 2^3 = 8 possibilities)
-
When l gets (up) to 1 player1x gets reset
-
You won't get more than 2^16 (2^16-1 actually 'cause you're using an LFSR)
you'd have 2^(6*4) possibilities with that many bits but they're not independent
there will be (are) overlaps.
-
1
-
-
As I am writing this, I'm wondering if it isn't possible somehow to "buffer" the surrounding screens of the current screen the player might be inhabiting. Calculating the left and right screen only requires one iteration of the feedback register. I wonder if there's a mathematical trick to reduce the amount of cycles required to go through in order to calculate a new Y-index of the overworld, instead of a new X-index. Perhaps a lookup table? A lookup table could perhaps be used to do multiple loops through the feedback register, just a row up and a row down. It might be possible to do some algebra and find out what XOR $D4 to XOR $D4 to XOR $D4 to an unknown number is...
Otherwise every movement up or down a Y-index is a full-row's worth of screens' calculations...
There has got to be a faster way... Feel free to jump in and give your two cents!
==
This is what you want jumpf2.pdf (warning: the math is kind of dense
)This one deals with LCGs anl-rn-arb-stride.pdf
This one also deals with LCGs but it has a couple of paragraphs (mostly I'm just throwing it in 'cause it's a good read
) hmc-cs-2014-0905.pdfedit: not sure I understand what you're doing Why not just run two polynomial counters, one for X and one for Y?
better yet if you've got the ROM just run two counters and look up the room configuration ie a mapping from
a straight counter to (something like) your polynomial counter's state except it could be completely arbitrary
and taylored more to what you want the rooms to be instead of what you'ld get from the polynomial counters
-
A couple more things.
First I didn't really mention it 'cause it doesn't really pertain
to tables
If eg you take the room 2 branch and fall through you go on and
spend another 150 cycles or so testing a bunch of rooms you already
know you're not in.
Second the 180 cycles v 77 + 50 is worst case and only if you change rooms
If you ran through that code every frame and changed rooms three times
a second that would still only be 5% of the time
If you fall through after, say, the two x position tests then break even
is at about 5 room tests.
The table code always (potentially) does four tests (not counting the room test)
Only a few of the string of if tests do that many. -
Here I've done some code with tables
First is 22 of your if statements (put in to a more tabular form)
then the same thing with tables.
Each if statement takes a minimum of 7 cycles so if you fall through
all 22 that by it self takes 154 cycles.
If the if statements represent 1/3 of the possible rooms and the
rooms come up at random (they probably don't) 2/3 of the time you'll
spend 154 cycles just to decide you don't want to do anything.
If you do take the if statement then on average you'll do half of them
or about 77 cycles (again if the rooms are random which they probably aren't)
plus the 50 cycles or so that it takes for the rest it.
In the case of the tables it does a look up to decide if it needs to do
anything, that takes about nine cycles (versus 154).
The rest of the table code takes 180 cycles or so (versus the 77 + 50)
But that's all sort of worst case. It might be faster it might not.
I don't think it would be much worse.
It takes about 1/3 the ROM
Of course, it's not tested but it does compile.
set romsize 32k
set optimization noinlinedata
dim _Room = r
dim _Bit5_Frozen = f
bank 2
dispatch2
bank 3
dispatch3
DS7
mk1
if _Room = 2 && player1x > 72 && player1x < 85 && player1y < 55 then _Room = 46 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS46 bank5 ; 01 1
if _Room = 4 && player1x > 66 && player1x < 86 && player1y > 45 && player1y < 55 then _Room = 42 : player1x = 117 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS42 bank5 ; 02 0
if _Room = 5 && player1x > 108 && player1x < 118 && player1y < 65 then _Room = 39 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS39 bank4 ; 03 10
if _Room = 6 && player1x > 44 && player1x < 56 && player1y < 71 then _Room = 27 : player1x = 78 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS27 bank4 ; 04 3
if _Room = 7 && player1x > 114 && player1x < 134 && player1y < 25 then _Room = 37 : player1y = 18 : _Bit5_Frozen{5} = 0 : goto DS37 bank4 ; 05 8
if _Room = 8 && player1x > 62 && player1x < 77 && player1y > 52 && player1y < 62 then _Room = 40 : player1x = 21 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS40 bank4 ; 06 11
if _Room = 9 && player1x > 49 && player1x < 70 && player1y < 24 then _Room = 66 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS66 bank5 ; 07 7
if _Room = 10 && player1x > 80 && player1x < 91 && player1y > 55 && player1y < 63 then _Room = 31 : player1x = 77 : player1y = 77 : _Bit5_Frozen{5} = 0 : goto DS31 bank4 ; 08 4
if _Room = 13 && player1x > 46 && player1x < 66 && player1y > 40 && player1y < 46 then _Room = 37 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS37 bank4 ; 09 8
if _Room = 15 && player1x > 87 && player1x < 96 && player1y > 60 && player1y < 77 then _Room = 25 : player1x = 78 : _Bit5_Frozen{5} = 0 : goto DS25 bank4 ; 10 1
if _Room = 18 && player1x > 99 && player1x < 113 && player1y > 40 && player1y < 47 then _Room = 38 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS38 bank4 ; 11 9
if _Room = 19 && player1x > 51 && player1x < 64 && player1y < 63 then _Room = 26 : player1x = 78 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS26 bank4 ; 12 2
if _Room = 24 && player1x > 58 && player1x < 78 && player1y < 62 then _Room = 32 : player1x = 46 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS32 bank4 ; 13 5
if _Room = 32 && player1x > 88 && player1x < 104 && player1y < 31 then _Room = 34 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS34 bank4 ; 14 6
if _Room = 35 && player1x > 96 && player1x < 106 && player1y < 62 then _Room = 36 : player1y = 85 : _Bit5_Frozen{5} = 0 : goto DS36 bank4 ; 15 7
if _Room = 37 && player1x > 124 && player1x < 134 && player1y > 28 then _Room = 7 : player1y = 34 : _Bit5_Frozen{5} = 0 : goto DS7 bank3 ; 16
if _Room = 41 && player1y < 55 then _Room = 56 : player1x = 25 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS56 bank5 ; 17 5
if _Room = 47 && player1x > 32 && player1x < 52 && player1y < 47 then _Room = 48 : player1y = 75 : _Bit5_Frozen{5} = 0 : goto DS48 bank5 ; 18 2
if _Room = 51 && player1x > 114 && player1x < 134 && player1y < 47 then _Room = 50 : player1y = 75 : _Bit5_Frozen{5} = 0 : goto DS50 bank5 ; 19 3
if _Room = 52 && player1x > 71 && player1x < 90 && player1y < 47 then _Room = 51 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS51 bank5 ; 20 4
if _Room = 54 && player1x > 77 && player1x < 90 && player1y < 40 then _Room = 64 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS64 bank5 ; 21 6
if _Room = 59 && player1x > 84 && player1x < 101 && player1y > 59 && player1y < 76 then _Room = 23 : player1y = 84 : _Bit5_Frozen{5} = 0 : goto DS23 bank4 ; 22 0
mk2
dim room_index = temp1
dim target_bank = temp2
dim DS_target = temp3
if !ridat[_Room] then skip
room_index = ridat[_Room]-1
if player1x < P1xlo[room_index] || player1x > P1xhi[room_index] then skip
if player1y < P1ylo[room_index] || player1y > P1yhi[room_index] then skip
_Bit5_Frozen{5} = 0
if newxdat[room_index] then player1x = newxdat[room_index]
if newydat[room_index] then player1y = newydat[room_index]
_Room = new_room[room_index]
DS_target = DStdat[room_index]
target_bank = tbnkdat[room_index]
on target_bank goto bnk3 bnk4 bnk5 bnk6
skip
bnk3 goto dispatch3
bnk4 goto dispatch4 bank4
bnk5 goto dispatch5 bank5
bnk6 goto dispatch6 bank6
; 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21
data newydat
85, 85, 84, 85, 18, 85, 84, 77, 84, 0, 84, 85, 85, 85, 85, 34, 84, 75, 75, 84, 84, 84
end
data newxdat
0, 117, 0, 78, 0, 21, 0, 77, 0, 78, 0, 78, 46, 0, 0, 0, 25, 0, 0, 0, 0, 0
end
data P1xlo
73, 67, 109, 45, 115, 63, 50, 81, 47, 88, 100, 52, 59, 89, 97, 125, 0, 33, 115, 72, 78, 85
end
data P1xhi
84, 85, 117, 55, 133, 76, 69, 90, 65, 95, 112, 63, 77, 103, 105, 133, 255, 51, 133, 89, 89, 100
end
data P1ylo
255, 46, 255, 255, 255, 53, 255, 56, 41, 61, 41, 255, 255, 255, 255, 29, 255, 255, 255, 255, 255, 60
end
data P1yhi
54, 54, 64, 70, 24, 61, 23, 62, 45, 76, 46, 62, 61, 30, 61, 0, 54, 46, 46, 46, 39, 75
end
data new_room
46, 42, 39, 27, 37, 40, 66, 31, 37, 25, 38, 26, 32, 34, 36, 7, 56, 48, 50, 51, 64, 23
end
data DStdat
1, 0, 10, 3, 8, 11, 7, 4, 8, 1, 9, 2, 5, 6, 7, 0, 5, 2, 3, 4, 6, 0
end
data tbnkdat
3, 3, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, 3, 3, 2
end
data ridat
0, 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 0, 0, 9, 0, 10
0, 0, 11, 12, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0
14, 0, 0, 15, 0, 16, 0, 0, 0, 17, 0, 0, 0, 0, 0, 18
0, 0, 0, 19, 20, 0, 21, 0, 0, 0, 0, 22, 0, 0, 0, 0
end
mk3
bank 4
dispatch4 on DS_target goto DS23 DS25 DS26 DS27 DS31 DS32 DS34 DS36 DS37 DS38 DS39 DS40 DS37
DS23
DS25
DS26
DS27
DS31
DS32
DS34
DS36
DS37
DS38
DS39
DS40
bank 5
dispatch5 on DS_target goto DS42 DS46 DS48 DS50 DS51 DS56 DS64 DS66
DS42
DS46
DS48
DS50
DS51
DS56
DS64
DS66
bank 6
dispatch6
asm
echo (.mk2 - .mk1)d
echo (.mk3 - .mk2)d
end
-
excerpts from two bB.asm files
.L00 ; if a < b then if a < b then if a < b then c = c
LDA a
CMP b
BCS .skipL00
.condpart0
LDA a
CMP b
BCS .skip0then
.condpart1
LDA a
CMP b
BCS .skip1then
.condpart2
LDA c
STA c
.skip1then
.skip0then
.skipL00
.L00 ; if a < b && a < b && a < b then c = c
LDA a
CMP b
BCS .skipL00
.condpart0
LDA a
CMP b
BCS .skip0then
.condpart1
LDA a
CMP b
BCS .skip1then
.condpart2
LDA c
STA c
.skip1then
.skip0then
.skipL00
.
ie they produce the same code
-
what kernel?
use joy0 up-down
the score is player0y
-
1
-
-
It's doing what it should do
I was just wondering how you're using the same variable in your 8.8 type x & y variablesdim p1x = player1x.wdim p1y = player1y.wJust w while I have to use both v & wdim _P1_L_R = player1x.vdim _P1_U_D = player1y.wSo I'm wondering if I could also use just one variable in some way? Just making shure I'm not currently wasting nine variables if I don't have to?it only uses the fractional part in one direction at a time
if the angle is less than 45 or greater than 135 the x direction is whole integer and the y is fractional
other wise y is integers and x is fractional
-
I'm still not clear on what your trying to do that it's not doing
if you're trying to get it to wrap around from 0 to 93 then maybe something like this
_P1_U_D = _P1_U_D - _robotspeed
if player1y > 93 then player1y = player1y + 93
-
what kernel?
what are you trying to do?
if your speed was, say, l = 5
then player1y would have to be >= 99 for player1y to not be set to 93 and then player1y would be >=94
-
I don't think I'd call this a work in progress, more like exploring some ideas
The code is buggy there aren't many comments and it's full of kruft
the stuff in the bottom left corner is the upper byte of a 9 bit counter which
is supposed to be keeping track of the number of playfield blocks but it doesn't quite
edit: forgot to mention I had to adjust some stuff in the 2600basic.h file
but I don't know how it comports with RevEng's latest and greatest
I moved playfieldpos = $F0 and commented out the calculations
for playfield from pfres
-
4
-
-
-
from the DPCplus.h file
;----------------------------------------; Random Number Initialization;----------------------------------------; The random number generate defaults to a value that spells out DPC+.; Store any value to RRESET to set the random number back to DPC+, or you; can use RWRITE0-3 to change the 32 bit value to anything you desire.;; reset random number; LDA #0; STA RRESET;; set a specific random number (spells out 2600); LDA #$32; STA RWRITE0; LDA #$36; STA RWRITE1; LDA #$30; STA RWRITE2; STA RWRITE3;; NOTE: do not set all 4 bytes to 0, as that will disable the generator.;----------------------------------------RRESET DS 1 ; $70RWRITE0 DS 1 ; $71RWRITE1 DS 1 ; $72RWRITE2 DS 1 ; $73RWRITE3 DS 1 ; $74 -
I did that, like, five years ago or so and I don't remember what I did.
I'm sure I didn't use a spread sheet. It was just by inspection.
ie what needs to go where. (but by all means use a spread sheet
if it helps)
It was just something I banged together to see how it would work.
In retrospect, I was too conservative with my tables.
Looking at it now, I prefer more comprehensive table
(ie more like ZackAttack's suggestion)
So here's the new, improved version.
There will always be a sprite copy in the left position. (I have decreed it thus)
So There are only four possible configurations for the sprite.
a single sprite, a near copy, a far copy, or both copies.
(the original table is somewhat redundant in that regard)
If there is a collision it can only happen in one of three possible places
If there is a collision you may have to adjust the sprite x position and
change the configuration.
You only have to change the sprite's x position if there's a collision
with the left most sprite/copy
So you need a 3 x 4 table to look up NUSIZ0 and a table with 4 elements
for the adjustment to the x position.
(But that requires an if statement to restrict x position adjusments
to the 0 sprite position. It could be done with a twelve element table
but you'd be adjusting the sprite x position by 0 most of the time)
(the NUSIZ0 table will have four positions for situations that can't
happen, but that's about 2/3 of an if statement so well worth a little
redundancy)
The limit for rightward movement of the sprite will also depend on the
sprite configuration.
You could probably calculate that from the tabel for the x position adjustment,
but there's only four possibilities so its probably faster and easier
and maybe smaller to just do another table.
If there's a collision it can only happen in an interval of 40 pixels to the
right of the sprite's x position,
The copies are spaced on 16 pixel intervals so we take
(missile1x - player0x)/16
and that will give us a number 0..2 for which copy had the collision.
I use that as the row address and since there's four values per row
its divide by 16 multiply by 4 ie divide by 4 with an AND mask to get rid
of the fractional part.
((missile1x - player0x)/16) & %00001100
I save the sprite configuration in bits 0..1 of jf and changed missile fired
flag to jf{7} (0 if the missile's fired) (there's also a direction flag, jf{6})
So the table address for the new sprite configuration is
(((missile1x - player0x)/16) & %00001100) | (jf & %00000011)
The playfield junk in the lower right is jf with some pixels below it to
indicate the bit positions (var40 = $55, var36 = jf)
edit: I swapped missile1x and player0x above (not in the code) (now fixed)
I left out the bit reference in the if predicate so you can (re)fire the missile
some times when you shouldn't be able to
line 69 in the code should be
if joy0fire && jf{7} then missile1x = player1x + 3 : missile1y = 80 : jf{7} = 0
-
1
-
-
-
Lolkiu64,
Thanks to Bogax code I was able to adjust some of my stuff. I did add the feature of speed control (based upon RT's Code) if that helps. That way your sprite speed is adjustable.
;***************************************************************
;
; Don't move right if pfpixel is in the way.
;
if joy0right then _P0_L_R = _P0_L_R + .5 : then left
temp3 = (player0x - 14)/4 : temp4 = (player0y - 6)/8
if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down
temp3 = (player0x - 14)/4 : temp4 = (player0y - 1)/8
if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down
(Just adjust all the .5 to what ever you need. 1.5; 1.8; .9 etc.) I did try to add another section, but got an error to detect the middle of the sprite. My thought there was if you can detect the middle of the sprite. Why not code it for the entire sprite. I know it will eat up space but then I think you have 100% collision. What I tried and it didn't compile. temp4 = (player0y - 3)/8 should detect the middle of the sprite, i think.
;***************************************************************
;
; Don't move right if pfpixel is in the way.
;
if joy0right then _P0_L_R = _P0_L_R + .5 : then left
temp3 = (player0x - 14)/4 : temp4 = (player0y - 6)/8
if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down
temp3 = (player0x - 14)/4 : temp4 = (player0y - 3)/8
if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down
temp3 = (player0x - 14)/4 : temp4 = (player0y - 1)/8
if pfread(temp3, temp4) then _P0_L_R = _P0_L_R - .5 : then down
I am working on the Multisprite version which is attached. Hopefully Bogax or someone can adjust the code around to work. The left and right detection works. I'm having trouble with the up and down portions.
The issue I see even in the above program is that they both use only one pixel for detection which is great, but at times the sprite will cut corners and not have the 100% true detection. This is still better that the bouncy detection that I first learned how to use. Hope these help in your game development, thanks.
you could have a look at this
-
1
-
-
here I've inserted different collision code and changed the height of player0
the code is basically similar
it tests two corners of the player0 for each direction
to see if there's a playfield pixel in the way
so for example if you're moving right it tests the top right
corner of player0 against the bottom left of the PFpixel
and the bottom right of player0 against the top left of the PFpixel
-
this lets you step player0 around the screen while displaying
player0x in the left three score digits and player0y in the right three score digits
the sprite changes color when there's a collision with the playfield
bear in mind that the sprites are drawn upside down so this 3x6 sprite
is in the lower left corner of an 8x8 sprite definition
-
1
-
-
If you can clear the whole screen instead of just the Golem
-
-
It kind of worked. The flicker is gone. But it still doesn't look right.
dim ptr = a mainloop temp1=golemShape[ptr] temp2=golemShape[0] temp3=golemShape[1] temp4=golemShape[2] COLUBK=$00 COLUPF=$08 pfpixel 20 5 on pfpixel 21 5 on pfpixel 22 5 on pfpixel temp2 7 on pfpixel temp3 7 on pfpixel temp4 7 on ptr = 0 pfpixel temp1 9 on ptr = ptr + 1 pfpixel temp1 9 on ptr = ptr + 1 pfpixel temp1 9 on drawscreen goto mainloop data golemShape 20, 21, 22 end
pfpixel uses temp1 and temp2
-
try something like this
temp1 = golemShape[0] pfpixel temp1 7 on
-
not sure what you want
your second line is just the first line mod 16
so if you have a number from the first line the number on the second line is number & 15

"Sierra Maestra", an Early WIP
in Atari 2600 Programming
Posted · Edited by bogax