Angepinnt Project J - Wir schreiben ein C64 Spiel in mehreren Schritten

  • Final Step

    Und wir fixen die letzten Bugs. Der Score wurde nach einem Game Over nicht sauber zurückgesetzt, und die Musik quält sich während des Speicherns weiter.

    Und falls es doch noch jemand nicht wußte, die ausgebaute Finalversion ist als Guns'n'Ghosts bei Psytronik und RGCD erhältlich!






    Damit ist dieser Exkurs beendet.

    Viel Spaß und vielen Dank für Ihre Aufmerksamkeit!
    Dateien
    • step100.zip

      (234,98 kB, 75 mal heruntergeladen, zuletzt: )
  • Endurion schrieb:

    Und wir fixen die letzten Bugs. Der Score wurde nach einem Game Over nicht sauber zurückgesetzt, und die Musik quält sich während des Speicherns weiter.

    Und falls es doch noch jemand nicht wußte, die ausgebaute Finalversion ist als Guns'n'Ghosts bei Psytronik und RGCD erhältlich!






    Damit ist dieser Exkurs beendet.

    Viel Spaß und vielen Dank für Ihre Aufmerksamkeit!


    Hallo,
    hat schon mal wer was bei Psytronik bestellt das per Post geschickt werden musste?
    Ich habe mir heute 2 Sachen geordert. Einmal Guns 'n' Ghosts als Digital Download.
    Aber dann noch Assembloids als Tape Version. Ich habe per Paypal bezahlt und danach wurde erst die Auswahl der Versandmöglichkeiten
    und die Kosten dafür angezeigt. Ich habe also bis jetzt nur die Programme bezahlt, aber noch nicht den Versand. Das lief irgendwie in der
    falschen Reihenfolge ab.
  • Ich habe dort schon mehrfach bestellt, ja. Allerdings habe ich mir ein Kundenkonto eröffnet. Du bist wohl direkt über den Paypal Button gegangen? Keine Ahnung warum da nicht vorher Porto kalkuliert wird. Mit Kundenkonto kommt man gar nicht zu Paypal ohne vorher Porto auszuwählen.
    Evtl. Kenz mal anschreiben. Oder warten bis er sich meldet. Das kann aber ein paar Tage dauern.
  • Hallo Endurion!

    Erst mal vielen herzlichen Dank für die viele Arbeit und alles hier reinzustellen!
    :)

    Ich bin grad dabei mir Spieleprogrammierung auf dem C64 in Assembler beizubringen
    und arbeite deswegen genau solche Quellcodes durch. Heute (und auch gestern schon)
    stecke ich schon den ganzen Tag im Step 3:

    Endurion schrieb:

    Jetzt geht es erstmal mit einigen grösseren Schritten weiter: Wir bewegen das Sprite mit dem Joystick.

    Da wir da ein richtiges Spiel draus machen wollen, soll das Sprite auch über den ganzen Bildschirm bewegbar sein. Mit anderen Worten, wir berücksichtigen direkt das 9. X-Bit. Da nicht geplant ist, über den Bildrand hinaus zu gehen, gibt es dafür keine Kontrollabfrage. D.h. das Sprite bewegt sich einfach weiter, und sobald die Koordinate wrappt (sprich unter 0 oder über 255 geht), springt das Sprite einfach wieder zurück.

    Dieser Schritt zeigt:
    -Joystick-Steuerung (Port II)
    -Erweitertes X-Bit




    In diesem Step 3 hast Du die Steuerung des Sprites mit dem Joystick hinzugefügt und
    ich versuche alles zu verstehen.
    Jetzt scheint es mir, nach 2 Tagen grübeln und ärgern dass ich nicht alles verstehe, dass
    Du vielleicht Code-Schnipsel von anderen Spielen eingebaut hast, die zum Teil noch
    Zeilen enthalten, die in diesem Schritt überhaupt nicht oder erst viel später gebraucht
    werden und die überhaupt nicht erklärt werden oder gebraucht werden. Kann das sein?

    Hier konkret, bei einer Bewegung nach links sowie dem Update des 9'ten Bits für den
    Überlauf der X-Koordinate (255):

    Brainfuck-Quellcode: Step 4 - jmain.asm

    1. ;------------------------------------------------------------
    2. ;Move Sprite Left
    3. ;expect x as sprite index (0 to 7)
    4. ;------------------------------------------------------------
    5. !zone MoveSpriteLeft
    6. MoveSpriteLeft
    7. dec SPRITE_POS_X,x
    8. bpl .NoChangeInExtendedFlag
    9. lda BIT_TABLE,x
    10. eor #$ff
    11. and SPRITE_POS_X_EXTEND
    12. sta SPRITE_POS_X_EXTEND
    13. sta 53248 + 16
    14. .NoChangeInExtendedFlag
    15. txa ; <-- Das ist doch überhaupt nicht nötig!!!!
    16. asl ; <-- Das ist doch überhaupt nicht nötig!!!!
    17. tay ; <-- Das ist doch überhaupt nicht nötig!!!!
    18. lda SPRITE_POS_X,x
    19. sta 53248,y ; sta 53248,x wäre hier doch passender!!!!?
    20. rts
    21. <snip>
    22. ;------------------------------------------------------------
    23. ;game variables
    24. ;------------------------------------------------------------
    25. SPRITE_POS_X
    26. !byte 0,0,0,0,0,0,0,0
    27. SPRITE_POS_X_EXTEND
    28. !byte 0
    29. SPRITE_POS_Y
    30. !byte 0,0,0,0,0,0,0,0
    31. BIT_TABLE
    32. !byte 1,2,4,8,16,32,64,128
    Alles anzeigen

    Konkret machst Du unter .NoChangeInExtendedFlag ein TXA, ein ASL und ein TAY, das hier überhaupt nicht
    gebraucht wird (hab's auskommentiert, läuft auch einwandfrei ohne!).
    Mit Step 4 hat das also sicher nichts zu tun! Oder?
    Ich muss sagen, solche Dinge verwirren mich EXTREM wenn ich versuche die blutigen Anfänge zu lernen!
    Naja, das nur als Feedback von einem blutigen Anfänger.
    Ich bin natürlich dankbar dass Du den Code überhaupt veröffentlichst, aber für mich als Anfäger
    sind solche Dinge im Code die darin nichts verloren haben aber sehr den Anschein machen
    extrem verwirrend... - Das nur als Tipp, falls Du mit diesen 100 Steps mal ein Buch für
    Anfänger schreiben möchtest, was natürlich super wäre... :)

    LG,
    Markie
  • Ändere Deinen Code mal von Sprite 0 zu Sprite 1 und Du wirst sehen, wozu der auskommentierte Bereich gut ist. ;)

    Die Designer des VIC haben die Register für die Sprite-Koordinaten leider nicht so angeordnet:

    Quellcode

    1. x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, y6, y7

    sondern so:

    Quellcode

    1. x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7

    Man muss also beim Zugriff auf diese Register den Index verdoppeln; genau das tut die Codesequenz TXA:ASL:TAY.
    Wenn man nur Sprite 0 benutzt, macht das natürlich keinen Unterschied, denn zwei mal Null bleibt Null.
    Yes, I'm the guy responsible for the ACME cross assembler
  • Hallo Mac Bacon!

    Hey danke für die Erklärung! :) :)

    Und nochmehr danke für den ACME!! :D ^^

    Zum Index der verdoppelt wird:
    Wieso den Index verdoppeln? Du meinst doch zwei mal inkrementieren, oder?
    Das ist ja gar nicht das selbe wie Verdoppeln!!!
    --> +2 ist nicht gleich * 2!
    --> 0, 2, 4, 6, 8 ist nicht gleich 1, 2, 4, 8, 16
    Und wieso überhaupt WÄHREND der Spritebewegung plötzlich die Spritenummer ändern???
    Das ist doch völlig hirnrissig! - Sorry, ich hab eben völlig Bahnhof dazu...
    Dass da der Index verdoppelt wird, das hab ich mir nach 2 Tagen auch mühsam zusammengebröselt.
    Nur: Das macht für mich keinen Sinn!
    Ja, Du hast recht, die X und Y Koordinaten sind paarweise im Speicher abgelegt.
    Das heisst aber eben nicht, dass der Index verdoppelt werden muss um auf den nächsten
    Wert zuzugreifen. Er muss einfach um + 2 anstatt um +1 inkrementiert werden für
    das nächste Sprite, bzw. dessen X Koordinate. Oder hab ich da was wichtiges verpasst
    oder verwechselt? Wohl schon, nur was???
    Gemäss obigem Quellcode ist es doch so, dass die Sprite-Nummer als Index im X-Register liegt.
    Also 0, 1, 2, 3, etc.

    Ich kleb mal den ganzen Quellcode rein:

    Brainfuck-Quellcode: Step 4 - jmain.asm

    1. ;compile to this filename
    2. !to "jmain.prg",cbm
    3. ;define constants here
    4. ;placeholder for various temp parameters
    5. PARAM1 = $03
    6. PARAM2 = $04
    7. PARAM3 = $05
    8. PARAM4 = $06
    9. PARAM5 = $07
    10. ;placeholder for zero page pointers
    11. ZEROPAGE_POINTER_1 = $17
    12. ZEROPAGE_POINTER_2 = $19
    13. ZEROPAGE_POINTER_3 = $21
    14. ZEROPAGE_POINTER_4 = $23
    15. ;address of the screen buffer
    16. SCREEN_CHAR = 52224
    17. ;address of color ram
    18. SCREEN_COLOR = $d800
    19. ;address of sprite pointers
    20. SPRITE_POINTER_BASE = SCREEN_CHAR + 1016
    21. ;number of sprites divided by four
    22. NUMBER_OF_SPRITES_DIV_4 = 1
    23. ;sprite number constants
    24. SPRITE_BASE = 64
    25. SPRITE_PLAYER = SPRITE_BASE + 0
    26. ;this creates a basic start
    27. *=$0801
    28. ;SYS 2064
    29. !byte $0C,$08,$0A,$00,$9E,$20,$32,$30,$36,$34,$00,$00,$00,$00,$00
    30. ;init sprite registers
    31. ;no visible sprites
    32. lda #0
    33. sta 53248 + 21
    34. ;set charset
    35. lda #$3c
    36. sta 53272
    37. ;VIC bank
    38. lda 56576
    39. and #$fc
    40. sta 56576
    41. ;----------------------------------
    42. ;copy charset and sprites to target
    43. ;----------------------------------
    44. ;block interrupts
    45. ;since we turn ROMs off this would result in crashes if we didn't
    46. sei
    47. ;save old configuration
    48. lda $01
    49. sta PARAM1
    50. ;only RAM
    51. ;to copy under the IO rom
    52. lda #%00110000
    53. sta $01
    54. ;take source address from CHARSET
    55. LDA #<CHARSET
    56. STA ZEROPAGE_POINTER_1
    57. LDA #>CHARSET
    58. STA ZEROPAGE_POINTER_1 + 1
    59. ;now copy
    60. jsr CopyCharSet
    61. ;take source address from SPRITES
    62. lda #<SPRITES
    63. sta ZEROPAGE_POINTER_1
    64. lda #>SPRITES
    65. sta ZEROPAGE_POINTER_1 + 1
    66. jsr CopySprites
    67. ;restore ROMs
    68. lda PARAM1
    69. sta $01
    70. cli
    71. ;test charset
    72. lda #'H'
    73. sta SCREEN_CHAR
    74. lda #'E'
    75. sta SCREEN_CHAR + 1
    76. lda #'L'
    77. sta SCREEN_CHAR + 2
    78. sta SCREEN_CHAR + 3
    79. lda #'O'
    80. sta SCREEN_CHAR + 4
    81. ;set char color to white
    82. lda #1
    83. sta SCREEN_COLOR
    84. sta SCREEN_COLOR + 1
    85. sta SCREEN_COLOR + 2
    86. sta SCREEN_COLOR + 3
    87. sta SCREEN_COLOR + 4
    88. ;init sprite 1 pos
    89. lda #100
    90. sta 53248
    91. sta 53248 + 1
    92. sta SPRITE_POS_X
    93. sta SPRITE_POS_Y
    94. ;set sprite image
    95. lda #SPRITE_PLAYER
    96. sta SPRITE_POINTER_BASE
    97. ;enable sprite 1
    98. lda #1
    99. sta 53248 + 21
    100. ;------------------------------------------------------------
    101. ;the main game loop
    102. ;------------------------------------------------------------
    103. GameLoop
    104. jsr WaitFrame
    105. jsr PlayerControl
    106. jmp GameLoop
    107. ;------------------------------------------------------------
    108. ;check joystick (player control)
    109. ;------------------------------------------------------------
    110. !zone PlayerControl
    111. PlayerControl
    112. lda #$02
    113. bit $dc00
    114. bne .NotDownPressed
    115. jsr PlayerMoveDown
    116. .NotDownPressed
    117. lda #$01
    118. bit $dc00
    119. bne .NotUpPressed
    120. jsr PlayerMoveUp
    121. .NotUpPressed
    122. lda #$04
    123. bit $dc00
    124. bne .NotLeftPressed
    125. jsr PlayerMoveLeft
    126. .NotLeftPressed
    127. lda #$08
    128. bit $dc00
    129. bne .NotRightPressed
    130. jsr PlayerMoveRight
    131. .NotRightPressed
    132. rts
    133. PlayerMoveLeft
    134. ldx #0
    135. jsr MoveSpriteLeft
    136. rts
    137. PlayerMoveRight
    138. ldx #0
    139. jsr MoveSpriteRight
    140. rts
    141. PlayerMoveUp
    142. ldx #0
    143. jsr MoveSpriteUp
    144. rts
    145. PlayerMoveDown
    146. ldx #0
    147. jsr MoveSpriteDown
    148. rts
    149. ;------------------------------------------------------------
    150. ;Move Sprite Left
    151. ;expect x as sprite index (0 to 7)
    152. ;------------------------------------------------------------
    153. !zone MoveSpriteLeft
    154. MoveSpriteLeft
    155. dec SPRITE_POS_X,x
    156. bpl .NoChangeInExtendedFlag
    157. lda BIT_TABLE,x
    158. eor #$ff
    159. and SPRITE_POS_X_EXTEND
    160. sta SPRITE_POS_X_EXTEND
    161. sta 53248 + 16
    162. .NoChangeInExtendedFlag
    163. txa
    164. asl
    165. tay
    166. lda SPRITE_POS_X,x
    167. sta 53248,y
    168. rts
    169. ;------------------------------------------------------------
    170. ;Move Sprite Right
    171. ;expect x as sprite index (0 to 7)
    172. ;------------------------------------------------------------
    173. !zone MoveSpriteRight
    174. MoveSpriteRight
    175. inc SPRITE_POS_X,x
    176. lda SPRITE_POS_X,x
    177. bne .NoChangeInExtendedFlag
    178. lda BIT_TABLE,x
    179. ora SPRITE_POS_X_EXTEND
    180. sta SPRITE_POS_X_EXTEND
    181. sta 53248 + 16
    182. .NoChangeInExtendedFlag
    183. txa
    184. asl
    185. tay
    186. lda SPRITE_POS_X,x
    187. sta 53248,y
    188. rts
    189. ;------------------------------------------------------------
    190. ;Move Sprite Up
    191. ;expect x as sprite index (0 to 7)
    192. ;------------------------------------------------------------
    193. !zone MoveSpriteUp
    194. MoveSpriteUp
    195. dec SPRITE_POS_Y,x
    196. txa
    197. asl
    198. tay
    199. lda SPRITE_POS_Y,x
    200. sta 53249,y
    201. rts
    202. ;------------------------------------------------------------
    203. ;Move Sprite Down
    204. ;expect x as sprite index (0 to 7)
    205. ;------------------------------------------------------------
    206. !zone MoveSpriteDown
    207. MoveSpriteDown
    208. inc SPRITE_POS_Y,x
    209. txa
    210. asl
    211. tay
    212. lda SPRITE_POS_Y,x
    213. sta 53249,y
    214. rts
    215. !zone WaitFrame
    216. ;wait for the raster to reach line $f8
    217. ;this is keeping our timing stable
    218. ;are we on line $F8 already? if so, wait for the next full screen
    219. ;prevents mistimings if called too fast
    220. WaitFrame
    221. lda $d012
    222. cmp #$F8
    223. beq WaitFrame
    224. ;wait for the raster to reach line $f8 (should be closer to the start of this line this way)
    225. .WaitStep2
    226. lda $d012
    227. cmp #$F8
    228. bne .WaitStep2
    229. rts
    230. ;------------------------------------------------------------
    231. ;copies charset from ZEROPAGE_POINTER_1 to ZEROPAGE_POINTER_2
    232. ;------------------------------------------------------------
    233. !zone CopyCharSet
    234. CopyCharSet
    235. ;set target address ($F000)
    236. lda #$00
    237. sta ZEROPAGE_POINTER_2
    238. lda #$F0
    239. sta ZEROPAGE_POINTER_2 + 1
    240. ldx #$00
    241. ldy #$00
    242. lda #0
    243. sta PARAM2
    244. .NextLine
    245. lda (ZEROPAGE_POINTER_1),Y
    246. sta (ZEROPAGE_POINTER_2),Y
    247. inx
    248. iny
    249. cpx #$08
    250. bne .NextLine
    251. cpy #$00
    252. bne .PageBoundaryNotReached
    253. ;we've reached the next 256 bytes, inc high byte
    254. inc ZEROPAGE_POINTER_1 + 1
    255. inc ZEROPAGE_POINTER_2 + 1
    256. .PageBoundaryNotReached
    257. ;only copy 254 chars to keep irq vectors intact
    258. inc PARAM2
    259. lda PARAM2
    260. cmp #254
    261. beq .CopyCharsetDone
    262. ldx #$00
    263. jmp .NextLine
    264. .CopyCharsetDone
    265. rts
    266. ;------------------------------------------------------------
    267. ;copies sprites from ZEROPAGE_POINTER_1 to ZEROPAGE_POINTER_2
    268. ; sprites are copied in numbers of four
    269. ;------------------------------------------------------------
    270. !zone CopySprites
    271. CopySprites
    272. ldy #$00
    273. ldx #$00
    274. lda #00
    275. sta ZEROPAGE_POINTER_2
    276. lda #$d0
    277. sta ZEROPAGE_POINTER_2 + 1
    278. ;4 sprites per loop
    279. .SpriteLoop
    280. lda (ZEROPAGE_POINTER_1),y
    281. sta (ZEROPAGE_POINTER_2),y
    282. iny
    283. bne .SpriteLoop
    284. inx
    285. inc ZEROPAGE_POINTER_1+1
    286. inc ZEROPAGE_POINTER_2+1
    287. cpx #NUMBER_OF_SPRITES_DIV_4
    288. bne .SpriteLoop
    289. rts
    290. ;------------------------------------------------------------
    291. ;game variables
    292. ;------------------------------------------------------------
    293. SPRITE_POS_X
    294. !byte 0,0,0,0,0,0,0,0
    295. SPRITE_POS_X_EXTEND
    296. !byte 0
    297. SPRITE_POS_Y
    298. !byte 0,0,0,0,0,0,0,0
    299. BIT_TABLE
    300. !byte 1,2,4,8,16,32,64,128
    301. CHARSET
    302. !binary "j.chr"
    303. SPRITES
    304. !binary "j.spr"
    Alles anzeigen

    Wenn man diesen Index jetzt mit Bitshift (ASL) verdoppelt, dann bleibt ja Sprite 0
    noch immer Sprite 0: %00000000 -> %00000000
    Sprite 1 wird zu Sprite 2: %00000001 -> %00000010, ok,
    aber Sprite 2 zu Sprite 4: %00000010 -> %00000100,
    und Sprite 3 zu Sprite 6, 4 zu 8 und Sprite 5 zu 10, usw.
    Doch warum sollte man überhaupt wärend der Bewegung plötzlich die Sprite
    Nummer ändern wollen? Das ist doch völlig widersinnig!
    - Abgesehen davon, dass es hier weit und breit nur ein Sprite gibt, aber das
    nebenbei, vielleicht ist der Code ja später nützlich, nur das verstehe ich eben
    noch überhaupt nicht!

    Liebe Grüsse und sorry wenn ich da ein wenig schwer von Begriff bin... :/
    Markie

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Markie ()

  • Markie schrieb:

    Zum Index der verdoppelt wird:
    Wieso den Index verdoppeln?
    Weil die Positionsregister im VIC so angeordnet sind, dass man "Register von Sprite N" bei der Adresse "Basis + 2 * N" findet.
    Beispiel:
    Die logischen Spritenummern gehen von 0 bis 7. Wir wählen das Sprite mit der Nummer "N", dann gilt:
    Der Spritezeiger von Sprite N liegt bei SCREEN_BASE + 1016 + N.
    Das Farbregister von Sprite N liegt bei $d027 + N.
    In Endurions Beispielprogramm werden die Koordinaten in zwei separaten Tabellen abgelegt,
    der X-Wert von Sprite N liegt bei SPRITE_POS_X + N,
    der Y-Wert von Sprite N liegt bei SPRITE_POS_Y + N.
    Im VIC sind die X- und Y-Werte aber leider abwechselnd angeordnet, d.h.
    der X-Wert von Sprite N liegt bei $d000 + 2 * N,
    der Y-Wert von Sprite N liegt bei $d001 + 2 * N.

    Sollten diese Formeln nicht klar sein, rechne es mit N=7 durch.

    Markie schrieb:

    Du meinst doch zwei mal inkrementieren, oder? Das ist ja gar nicht das selbe wie Verdoppeln!
    Wenn man von einem Koordinatenregister im VIC zu dem des nächsten Sprites gelangen möchte, kann man auch zweimal inkrementieren, richtig. In einer einfachen Schleife über alle Sprites wäre das auch sinnvoll. Die Routine im Programm ist aber so geschrieben, dass man sie für ein beliebiges Sprite aufrufen kann, dessen Nummer man im X-Register übergibt. Wenn nun die Koordinatenregister im VIC benutzt werden, muss der Adressoffset (nicht die Spritenummer!) verdoppelt werden. Damit man sich nicht die Spritenummer in X kaputtmacht, wird das Ergebnis (2 * Spritenummer) ins Y-Register geschrieben. Somit kann man die "normalen", kleinen, 8-Byte-Tabellen mit X indizieren (0, 1, 2, 3, 4, 5, 6, 7), während man die "interleaved" Koordinatenregister im VIC mit Y indiziert (0, 2, 4, 6, 8, 10, 12, 14).
    Rechne es nach, das X-Koordinatenregister für z.B. Sprite 3 befindet sich bei $d000 + 2*3,
    das Y-Koordinatenregister für z.B. Sprite 5 befindet sich bei $d001 + 2*5.
    Yes, I'm the guy responsible for the ACME cross assembler
  • Keine Ahnung, ob das hier im Thread schon irgendwo erwähnt wurde:

    Jemand (smithrobs) hat sich die Mühe gemacht und ProjectJ auf GitHub abgelegt und jeden Step als eigenen Commit abgelegt:
    github.com/smithrobs/Endurion-ProjectJ

    Irgendwo meine ich, auch einen sauberen PDF Ausdruck aller Schritte gefunden zu haben, aber ich finde ihn gerade nicht.
    Die englischsprachige Version dieses Tutorials findet man hier: retroremakes.com/remaketalk/in…-game-in-several-steps/p1
    ___________________________________________________________
    Meine Kreationen: Deviant Art | Toonsup | Flickr | Youtube
    | Twitter
    Avatar: Copyright 2017 by Saiki
  • Hoppla, hier geht's ja rund. MacBacon hat es glaube ich schon recht ausführlich erklärt:

    Die Routine ist für verschiedene Objekte ausgelegt, nicht nur für Objekte in Slot X=0. Es wird aus dem eigentlichen Objekt-Index in X (Werte von 0 bis 7) durch Verdoppeln der zugehörige Koordinaten-Offset für den VIC errechnet (aus 0,1,2,3,4,5,6,7 wird 0,2,4,6,8,10,12).

    Das sieht, wenn man nur Slot 0 betrachtet, natürlich sinnlos aus, 0 bleibt ja 0.

    Ich plane schon die ganze Zeit, das Tutorial bei C64Studio mitzuliefern. Markie hat in mühevoller Kleinarbeit alle Schritte in ein großes Dokument zusammengesetzt (danke dafür!), das ist deutlich übersichtlicher als alle Steps einzeln.
  • Mac Bacon schrieb:

    Wenn man von einem Koordinatenregister im VIC zu dem des nächsten Sprites gelangen möchte, kann man auch zweimal inkrementieren, richtig. In einer einfachen Schleife über alle Sprites wäre das auch sinnvoll. Die Routine im Programm ist aber so geschrieben, dass man sie für ein beliebiges Sprite aufrufen kann, dessen Nummer man im X-Register übergibt. Wenn nun die Koordinatenregister im VIC benutzt werden, muss der Adressoffset (nicht die Spritenummer!) verdoppelt werden.
    Richtig! Äh falsch. Bzw richtig erkannt: Genau damit hatte ich den Knopf:
    Den direkten Sprung in den richtigen Adressoffset erreicht man dadurch,
    dass man den Offsett = 2 * Spritenummer setzt! :)
    Also dass man die Spritenummer verdoppelt, wie ich das bemerkte
    und mir darüber eben fast mein kleines Hirnchen zerbrach... :schande:
    Ich dachte: WIESO die Spritenummer verdoppeln???
    Wieso ist jetzt zum Beispiel Sprite Nr. 8 plötzlich doppelt so sexy wie
    Sprite Nr. 4? Und warum hat Endurion jetzt plötzlich nur noch dafür
    Augen!!?? Wir waren doch schon mit Sprite Nr. 4 liasioniert! :cursing: ;)

    Mac Bacon schrieb:

    Damit man sich nicht die Spritenummer in X kaputtmacht, wird das Ergebnis (2 * Spritenummer) ins Y-Register geschrieben. Somit kann man die "normalen", kleinen, 8-Byte-Tabellen mit X indizieren (0, 1, 2, 3, 4, 5, 6, 7), während man die "interleaved" Koordinatenregister im VIC mit Y indiziert (0, 2, 4, 6, 8, 10, 12, 14).Rechne es nach, das X-Koordinatenregister für z.B. Sprite 3 befindet sich bei $d000 + 2*3,
    das Y-Koordinatenregister für z.B. Sprite 5 befindet sich bei $d001 + 2*5.

    Fantastisch! Vielen herzlichen Dank!
    Jetzt hat es KLICK gemacht!
    :thumbsup:

    Endurion schrieb:

    Hoppla, hier geht's ja rund. MacBacon hat es glaube ich schon recht ausführlich erklärt:

    Die Routine ist für verschiedene Objekte ausgelegt, nicht nur für Objekte in Slot X=0. Es wird aus dem eigentlichen Objekt-Index in X (Werte von 0 bis 7) durch Verdoppeln der zugehörige Koordinaten-Offset für den VIC errechnet (aus 0,1,2,3,4,5,6,7 wird 0,2,4,6,8,10,12).

    Das sieht, wenn man nur Slot 0 betrachtet, natürlich sinnlos aus, 0 bleibt ja 0.

    Ja, das ist kurz und bündig.
    Mein Problem war ja nicht nur dass es nur für ein Sprite 0 sinnlos aussieht / ist,
    sondern auch, dass ich nicht wusste und nicht verstand, dass die Routine
    für beliebige Sprite-Nummern angelegt ist (logisch hinterher) und dass
    jedes Sprite, bzw. die Koordinaten zwar um +2 weiter hinten ist, dass
    man aber eben mit der Verdoppelung der Spritenummer den OFFSET
    ab der Startadresse bekommt. Ich dachte immer, da wird bloss die
    Spritenummer verdoppelt, warum interessiert uns plötzlich ein doppelt
    weiter gezähltes Sprite so viel mehr, als das dessen Koordinaten wir
    eigentlich hätten ändern möchten?
    - Naja - bin da einfach hängengeblieben... X/
    Jedenfalls jetzt hat's geklappt. Vielen herzlichen Dank Euch beiden! :)
    Jetzt hab ich's begriffen! :)

    Was lange währt... äh, findet manchmal auch ein Korn...
    - Oder so.

    Danke Euch beiden für die Erklärungen. Die kommen jetzt fast 1:1 in meinen
    ausführlich kommentierten Code von Step 4! :)


    LG,
    Markie