home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / assembler-kurs / listings3 / listing7w2.s < prev    next >
Text File  |  1977-12-31  |  10KB  |  347 lines

  1.  
  2. ; Listing7w2.s    KOLLISIONEN ZWISCHEN UNGERADEN SPRITES
  3. ;
  4. ; In diesem Beispiel sehen wir, wie wir die Kollisionen zwischen ungeraden
  5. ; Sprites registrieren können. Diesmal sind zwei Raketen auf der Jagt nach
  6. ; dem Flugzeug, und einer der beiden ist ein ungerader Sprite.
  7. ; Wenn ihr das Programm startet, werdet ihr aber sehen, daß die Rakete
  8. ; ganz rechts nicht funktioniert.
  9. ; Ihr wollt sie repairieren? Dann lest den Kommentar am Ende des Listings.
  10.  
  11.     SECTION CiriCop,CODE
  12.  
  13. Anfang:
  14.     move.l    4.w,a6        ; Execbase
  15.     jsr    -$78(a6)    ; Disable
  16.     lea    GfxName(PC),a1    ; Name lib
  17.     jsr    -$198(a6)    ; OpenLibrary
  18.     move.l    d0,GfxBase
  19.     move.l    d0,a6
  20.     move.l    $26(a6),OldCop    ; speichern die alte COP
  21.  
  22. ;    Pointen das PIC auf die übliche Art
  23.  
  24.     MOVE.L    #PIC,d0
  25.     LEA    BPLPOINTERS,A1
  26.     MOVEQ    #2-1,D1
  27. POINTBP:
  28.     move.w    d0,6(a1)
  29.     swap    d0
  30.     move.w    d0,2(a1)
  31.     swap    d0
  32.     ADD.L    #40*256,d0
  33.     addq.w    #8,a1
  34.     dbra    d1,POINTBP
  35.  
  36. ;    Pointen auf die Sprites
  37.  
  38.     LEA    SpritePointers,a1 ; Pointer in der Copperlist
  39.     MOVE.L    #MEINSPRITE0,d0      ; Adresse des Sprite in d0
  40.     move.w    d0,6(a1)
  41.     swap    d0
  42.     move.w    d0,2(a1)
  43.  
  44.     add.l    #16,a1         ; Spritepointer 2
  45.     MOVE.L    #MEINSPRITE2,d0     ; Adresse des Sprite in d0
  46.     move.w    d0,6(a1)
  47.     swap    d0
  48.     move.w    d0,2(a1)
  49.  
  50.     add.l    #8,a1         ; Spritepointer 3
  51.     MOVE.L    #MEINSPRITE3,d0     ; Adresse des Sprite in d0
  52.     move.w    d0,6(a1)
  53.     swap    d0
  54.     move.w    d0,2(a1)
  55.  
  56.     move.l    #COPPERLIST,$dff080    ; unsere COP
  57.     move.w    d0,$dff088        ; START COP
  58.     move.w    #0,$dff1fc        ; NO AGA!
  59.     move.w    #$c00,$dff106        ; NO AGA!
  60.  
  61. mouse:
  62.     cmpi.b    #$ff,$dff006    ; Zeile 255?
  63.     bne.s    mouse
  64.  
  65.     bsr.s    BewegeSprite0    ; Bewege das Flugzeug
  66.     bsr.s    BewegeSprite2    ; Bewege Rakete 1 gegen das Flugzeug
  67.     bsr.s    BewegeSprite3    ; Bewege Rakete 2 gegen das Flugzeug
  68.     bsr.w    CheckColl    ; Kontrolliert Kollisionen und greift ein
  69.  
  70. Warte:
  71.     cmpi.b    #$ff,$dff006    ; Zeile 255?
  72.     beq.s    Warte
  73.  
  74.     btst    #6,$bfe001    ; Mouse gedrückt?
  75.     bne.s    mouse
  76.  
  77.     move.l    OldCop(PC),$dff080    ; Pointen auf die SystemCOP
  78.     move.w    d0,$dff088        ; Starten die alte COP
  79.  
  80.     move.l    4.w,a6
  81.     jsr    -$7e(a6)     ; Enable
  82.     move.l    gfxbase(PC),a1
  83.     jsr    -$19e(a6)    ; Closelibrary
  84.     rts
  85.  
  86. ;    Daten
  87.  
  88. GfxName:
  89.     dc.b    "graphics.library",0,0
  90.  
  91. GfxBase:
  92.     dc.l    0
  93.  
  94. OldCop:
  95.     dc.l    0
  96.  
  97. ; Diese Routine bewegt das Flugzeug um 2 Pixel pro Durchgang nach links
  98.  
  99. BewegeSprite0:
  100.     subq.b    #1,HSTART0
  101.     rts
  102.  
  103.  
  104. ; Diese Routine steuert die Rakete. Sie tut es nur, wenn das Flugzeug nah
  105. ; genug dran ist, um getroffen zu werden.
  106.  
  107.  
  108. BewegeSprite2:
  109.     cmp.b    #$b0,HSTART0
  110.     bhi.s    nicht_in_Schusslinie2    ; nicht starten, wenn das Flugzeug
  111.     subq.b    #1,VSTART2        ; zu weit rechts ist
  112.     subq.b    #1,VSTOP2
  113. nicht_in_Schusslinie2:
  114.     rts
  115.  
  116. ; Diese Routine steuert die Rakete. Sie tut es nur, wenn das Flugzeug nah
  117. ; genug dran ist, um getroffen zu werden.
  118.  
  119. BewegeSprite3:
  120.     cmp.b    #$d0,HSTART0
  121.     bhi.s    nicht_in_Schusslinie3    ; nicht starten, wenn das Flugzeug
  122.     subq.b    #1,VSTART3        ; zu weit rechts ist
  123.     subq.b    #1,VSTOP3
  124. nicht_in_Schusslinie3:
  125.     rts
  126.  
  127. ; Diese Routine kontrolliert, ob es eine Kollision gab. Wenn ja, löscht sie
  128. ; die beiden Sprites, die zusammengestoßen sind, indem sie die jeweiligen
  129. ; Spritepointer in der Copperlist löscht. Um unterscheiden zu können, welche
  130. ; der beiden Raketen ins Ziel gegangen ist, werden die Positionen abgefragt.
  131. ; In diesem Fall können die Raketen das Flugzeug nur von unten treffen; wenn
  132. ; sich eine Rakete also höher befindet als dieses, dann kann sie es nicht
  133. ; getroffen haben. Durch diese Methode können wir herausfinden, welche
  134. ; Rakete nun getroffen hat.
  135.  
  136. CheckColl:
  137.     move.w    $dff00e,d0 ; liest CLXDAT ($dff00e)
  138.                ; ein Lesevorgang dieses Register bewirkt
  139.                ; auch dessen komplette Löschung, es ist deshalb
  140.                ; ratsam, es sich in d0 zu kopieren, und dann
  141.                ; dort die Tests durchzuführen
  142.     btst.l    #9,d0
  143.     beq.s    no_coll         ; wenn keine Kollision, überspringe
  144.  
  145.     MOVEQ    #0,d0          ; ansonsten lösche die Sprites
  146.     LEA    SpritePointers,a1 ; Pointer Sprite 0
  147.     move.w    d0,6(a1)      ; Lösche Spritepointer 0 in der Copperlist
  148.     move.w    d0,2(a1)
  149.  
  150. ; Nun müssen wir noch verstehen, welche der beiden Raketen getroffen hat.
  151. ; Wir kontrollieren die Höhe der Rakete, die weiter rechts steht: wenn
  152. ; sie höher ist als das Flugzeug, dann KANN sie es NICHT getroffen haben.
  153.  
  154.     move.b    VSTART0,d1    ; liest die Höhe des Flugzeuges
  155.     cmp.b    VSTART3,d1    ; vergleicht mit der Höhe der Rakete rechts
  156.     bhi.s    spr2_coll    ; wenn das Flugzeug tiefer ist
  157.                 ; (also VSTART0 größer als VSTART3 ist)
  158.                 ; dann wurde die Kollision vom Sprite 2
  159.                 ; ausgelöst
  160.  
  161.     LEA    SpritePointer3,a1 ; ansonsten lösche Sprite 3
  162.     move.w    d0,6(a1)      ; Löscht Spritepointer 3 in der Copperlist
  163.     move.w    d0,2(a1)
  164.     bra.s    no_coll
  165.     
  166. spr2_coll:
  167.     LEA    SpritePointer2,a1 ; Löscht Sprite 2
  168.     move.w    d0,6(a1)      ; löscht Spritepointer 2 in der Copperlist
  169.     move.w    d0,2(a1)
  170. no_coll:
  171.     rts
  172.  
  173.  
  174.         SECTION GRAPHIC,DATA_C
  175.  
  176. COPPERLIST:
  177. SpritePointers:
  178.     dc.w    $120,0,$122,0,$124,0,$126,0
  179. SpritePointer2:
  180.     dc.w    $128,0,$12a,0
  181. SpritePointer3:
  182.     dc.w    $12c,0,$12e,0,$130,0,$132,0
  183.     dc.w    $134,0,$136,0,$138,0,$13a,0,$13c,0
  184.     dc.w    $13e,0
  185.  
  186.             ; 5432109876543210
  187.     dc.w    $98,%0000000000000000    ; CLXCON    $dff098
  188.  
  189.     dc.w    $8E,$2c81    ; DiwStrt
  190.     dc.w    $90,$2cc1    ; DiwStop
  191.     dc.w    $92,$38        ; DdfStart
  192.     dc.w    $94,$d0        ; DdfStop
  193.     dc.w    $102,0        ; BplCon1
  194.     dc.w    $104,$0024    ; BplCon2
  195.     dc.w    $108,0        ; Bpl1Mod
  196.     dc.w    $10a,0        ; Bpl2Mod
  197.  
  198.             ; 5432109876543210
  199.     dc.w    $100,%0010001000000000    ; 2 Bitplane Lowres
  200.  
  201. BPLPOINTERS:
  202.     dc.w $e0,0,$e2,0    ;erstes    Bitplane
  203.     dc.w $e4,0,$e6,0    ;zweites Bitplane
  204.  
  205.     dc.w    $180,$000    ; COLOR0    ; schwarzer Hintergrund
  206.     dc.w    $182,$005    ; COLOR1    ; Farbe 1 del bitplane
  207.     dc.w    $184,$a40    ; COLOR1    ; Farbe 2 del bitplane
  208.     dc.w    $186,$f80    ; COLOR1    ; Farbe 3 del bitplane
  209.  
  210.     dc.w    $1A2,$06f    ; COLOR17, also COLOR1 des Sprite0
  211.     dc.w    $1A4,$0c0    ; COLOR18, also COLOR2 des Sprite0
  212.     dc.w    $1A6,$0c0    ; COLOR19, also COLOR3 des Sprite0
  213.  
  214.     dc.w    $1AA,$444    ; COLOR21, also COLOR1 des Sprite2
  215.     dc.w    $1AC,$888    ; COLOR22, also COLOR2 des Sprite2
  216.     dc.w    $1AE,$0c0    ; COLOR23, also COLOR3 des Sprite2
  217.  
  218.     dc.w    $FFFF,$FFFE    ; Ende der Copperlist
  219.  
  220.  
  221. ; ************ Hier ist der Sprite: KLARERWEISE in CHIP RAM! ************
  222.  
  223. MEINSPRITE0:        ; Länge 6 Zeilen
  224. VSTART0:
  225.     dc.b 180    ; Vertikale Anfangsposition des Sprite (da $2c a $f2)
  226. HSTART0:
  227.     dc.b $d8    ; Horizontale Anfangsposition des Sprite (da $40 a $d8)
  228. VSTOP0:
  229.     dc.b 186    ; 180+6=186
  230. VHBITS:
  231.     dc.b $00
  232.     dc.w    $0008,$0000
  233.     dc.w    $1818,$0000
  234.     dc.w    $2C28,$1010
  235.     dc.w    $7FF8,$0000
  236.     dc.w    $3FC0,$0000
  237.     dc.w    $01F0,$0000
  238.     dc.w    $0000,$0000
  239.  
  240. MEINSPRITE2:       ; Länge 16 Zeilen
  241. VSTART2:
  242.     dc.b 224   ; Vertikale Anfangsposition des Sprite (von $2c bis $f2)
  243. HSTART2:
  244.     dc.b $86   ; Horizontale Anfangsposition des Sprite (von $40 bis $d8)
  245. VSTOP2:
  246.     dc.b 240
  247.     dc.b 0
  248.     dc.w    $0200,$0000
  249.     dc.w    $0200,$0000
  250.     dc.w    $0200,$0000
  251.     dc.w    $0000,$0200
  252.     dc.w    $0000,$0700
  253.     dc.w    $0000,$0700
  254.     dc.w    $0500,$0200
  255.     dc.w    $0200,$0500
  256.     dc.w    $0500,$0200
  257.     dc.w    $0200,$0500
  258.     dc.w    $1540,$0200
  259.     dc.w    $0200,$1DC0
  260.     dc.w    $0000,$1FC0
  261.     dc.w    $0000,$1740
  262.     dc.w    $0500,$0200
  263.     dc.w    $0000,$0000
  264.     dc.w    $0000,$0000
  265.  
  266. MEINSPRITE3:       ; Länge 16 Zeilen
  267. VSTART3:
  268.     dc.b 224   ; Vertikale Anfangsposition des Sprite (von $2c bis $f2)
  269. HSTART3:
  270.     dc.b $a6   ; Horizontale Anfangsposition des Sprite (von $40 bis $d8)
  271. VSTOP3:
  272.     dc.b 240
  273.     dc.b 0
  274.     dc.w    $0200,$0000
  275.     dc.w    $0200,$0000
  276.     dc.w    $0200,$0000
  277.     dc.w    $0000,$0200
  278.     dc.w    $0000,$0700
  279.     dc.w    $0000,$0700
  280.     dc.w    $0500,$0200
  281.     dc.w    $0200,$0500
  282.     dc.w    $0500,$0200
  283.     dc.w    $0200,$0500
  284.     dc.w    $1540,$0200
  285.     dc.w    $0200,$1DC0
  286.     dc.w    $0000,$1FC0
  287.     dc.w    $0000,$1740
  288.     dc.w    $0500,$0200
  289.     dc.w    $0000,$0000
  290.     dc.w    $0000,$0000
  291.  
  292. ;    Bild der Startrampe der Raketen
  293.  
  294. PIC:
  295.     incbin    "landschaft.raw"
  296.  
  297.     end
  298.  
  299. Wie wir in der Lektion gesehen haben, erlaubt uns das Register CLXDAT  nur
  300. zu  erkennen,  ob  eine Kollision zwischen Spritepaaren stattgefunden hat,
  301. nicht zwischen den einzelnen Sprite. In diesem  Beispiel  sehen  wir,  wie
  302. dieses  Problem  gelöst  werden  kann.  Ich  erinnere  euch daran, daß die
  303. Kollisionen der geraden Sprite (also 0,2,4,6) immer  aktiviert  sind,  die
  304. der  ungeraden  (1,3,5,7)  aber erst aktivert werden müssen. Das geschieht
  305. durch Kontrollbits im Register CLXCON ($dff098). Jeder ungerade Sprite hat
  306. ein  eigenes  Kontrollbit  und  hann demzufolge unabhängig von den anderen
  307. eingeschaltet werden. Wenn ihr versucht,  das  Listing  auszuführen,  dann
  308. bemerkt  ihr,  daß die rechte Rakete nicht funktioniert. Das deshalb, weil
  309. dieser Sprite ein ungerader ist (Sprite 3), und deaktiviert auch noch.  In
  310. der Copperlist findet ihr folgenden Befehl:
  311.  
  312.            ; 5432109876543210
  313.     dc.w    $98,%0000000000000000
  314.  
  315. Er deaktiviert die Kollisionen für alle ungeraden Sprites (für die  genaue
  316. Beschreibung  aller  Bits  seht  euch  die Lektion an). Um den Sprite 3 zu
  317. aktivieren muß Bit 13 auf 1 gesetzt werden. Die Copperanweisung  muß  also
  318. so aussehen:
  319.  
  320.            ; 5432109876543210
  321.     dc.w    $98,%0010000000000000
  322.  
  323. Probiert das Listing nun  aus,  und  ihr  werdet  sehen,  daß  die  Rakete
  324. funktioniert!
  325.  
  326. Ein  weiteres  Problem  der  Kollisionen  ist, daß das Register CLXDAT nur
  327. Kollisionen unter Spritepaaren aufspürt, nicht aber zwischen den einzelnen
  328. Sprites.  In  unserem  Beispiel gehören die Raketen beide zum selben Paar.
  329. Wenn nun eine Kollision auftritt  können  wir  nicht  wissen,  welche  der
  330. beiden Raktenen es gewesen ist, wenn wir nur das Register CLXDAT lesen. Um
  331. das zu erfahren ist die meistens verwendete Methode das kontrollieren  der
  332. Spritepositionen.  In  diesem  recht  einfachem  Beispiel  braucht  nur
  333. verglichen werden, ob der  Sprite  rechts  mehr  oder  weiniger  ober  dem
  334. Flugzeug ist, es ist besser im Kommentar der Routine CheckColl erklärt. In
  335. komplexeren Situationen, bei denen sich die Sprites in mehrere  Richtungen
  336. bewegen,  sind  aufwendigere  Kontrollen notwendig, dort muß man sich dann
  337. auf vertikale und horizontale Position berufen. Das Prinzip ist aber immer
  338. das gleiche.
  339.  
  340. Ihr  könnt  überprüfen,  daß  unsere  Routine  immer  die richtige Raktete
  341. erwischt, indem ihr die Startpositionen der rechten Rakete verändert.  Der
  342. Anfangswert von HSTART3 ist auf $6a und garantiert der Rakete, daß sie das
  343. Flugzeug treffen wird. Ersetzt $6a durch $6b. Wenn ihr  das  Beispiel  nun
  344. ausführt,  werdet ihr sehen, daß sie nun das Flugzeug verfehlt. Aber keine
  345. Angst! die zweite wird mitten rein dreschen!
  346.  
  347.