【问题标题】:Drawing two character sprite in Z80 assembly在 Z80 组件中绘制两个字符精灵
【发布时间】:2022-06-16 14:48:23
【问题描述】:

First Steps in Z80 Assembly Language 开始,我正在尝试在汇编程序中移动两个高字符精灵。

            ORG 30000         ; Origin

LASTK       EQU 23560         ; last key press (system variable)

PRINT       EQU 8252          ; This means the label PRINT equates to 8252.


            XOR a             ; quick way to load accumulator with zero.
            LD A, 2           ; set print channel to screen

            CALL 5633         ; Open channel two (ie, write to screen)
            LD HL, GFX        ; set up UDGs
            LD (23675), HL    ; where the UDG characters are stored.
            CALL 3503         ; clear the screen. CLS


MAINLP      CALL PRTPLAY      ; print player sprite
            
            HALT              ; Slow it down three times
            HALT
            HALT

            LD BC, $FEFE      ; load port address into BC, scan for right ("X")
            IN A, (C)         ; load port data into A
            AND %0000100      ; looking for X
            JR Z, GORIGHT     ; if Z is press, go right

            JR MAINLP         ; loop back to continue scanning


GORIGHT     LD A, (PLAYER+2)  ; if player is at right edge, don't continue
            CP 31
            JR Z, MAINLP      ; Jump Relative Zero
            CALL UNDRAW
            LD A, (PLAYER+2)  ; get player's X coordinate
            INC A             ; add 1
            LD (PLAYER+2), A
            JR MAINLP


PRTPLAY     LD DE, PLAYER           ; print player graphic
            LD BC, EOPLAYR-PLAYER
            CALL PRINT
            RET


UNDRAW      LD A, " "            ; change graphic to empty space
            LD (PLAYER+3), A     ; store it
            CALL PRTPLAY         ; undraw graphic from screen
            LD A, 144            ; change graphic back to normal
            LD (PLAYER+3), A     ; store it


            RET ; return to basic!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

            ; Player x, y 
PLAYER      DEFB 22, 12, 15, 144 ; print at Y, X, char 144 UDG (A)
            DEFB 22, 13, 15, 145 ; print at Y+1, X, char 145 UDG (B)
            EOPLAYR EQU $

            ; Graphics UDG Character
GFX         DEFB 6, 62, 124, 52, 62, 60, 24, 60
            DEFB 126, 126, 247, 251, 60, 118, 110, 119
            

Manic Miner 精灵画得很好。然而,当按下“x”向右走时,只有上半部分移动。这要么意味着未绘制不起作用,要么底部字符没有增加。我对汇编程序很陌生,并试图找出我出错的地方。我怀疑这是明确告诉 DEFB 在 144 和 145 上的地方,但撤消仅在 144 上。然而,这应该由 LD BC, EOPLAYR-PLAYER 涵盖。 困惑。

【问题讨论】:

  • “但是这应该被 LD BC, EOPLAYR-PLAYER 覆盖”。您正在打印它们两者的事实并不会改变您只是在修改您正在打印的东西之一的事实。此外,在我看来,您的 GORIGHT 例程仅更新第一个字符的 X 坐标(即我假设您还需要增加 (PLAYER+6))。

标签: assembly 8-bit z80 zxspectrum


【解决方案1】:

所以你尝试自己扩展本书的例子......太好了,这样你会学到最多的东西。

您的怀疑部分正确,PRTPLAY 确实打印了所有字节。

所以它打印第一个 AT 控制代码将光标置于 (x,12),然后打印 UDG 字符“A”144,然后另一个 AT 控制代码将光标置于 (x,13) 和 UDG 字符“B”145。

UNDRAW 确实仅将顶部字符 144 修改为空格,因此它在精灵顶部打印空格并在底部再次打印 UDG 'B',以保持精灵可见。

要解决这个问题(以与原始作品相同的平凡方式):

UNDRAW      LD A, " "            ; change graphic to empty space
            LD (PLAYER+3), A     ; replace UDG A 144
            LD (PLAYER+7), A     ; replace UDG B 145
            CALL PRTPLAY         ; undraw graphic from screen
            LD A, 144            ; change graphic back to normal
            LD (PLAYER+3), A     ; store it
            LD A, 145
            LD (PLAYER+7), A
            RET                  ; return to caller

同样,修补 AT 控制代码的 X 坐标的例程现在必须修补两个位置,因为您的打印字符串中有两个 AT 控制代码:

GORIGHT     LD A, (PLAYER+2)  ; if player is at right edge, don't continue
            CP 31
            JR Z, MAINLP      ; Jump Relative Zero
            CALL UNDRAW
            LD A, (PLAYER+2)  ; get player's X coordinate
            INC A             ; add 1
            LD (PLAYER+2), A  ; update X position of upper char 144
            LD (PLAYER+6), A  ; update X position of lower char 145
            JR MAINLP

您可能想尽快学习这种使用 BASIC PRINT 例程调用 ROM 来获取图形的教程,并寻找更高级的教程,直接在没有 ROM 的情况下绘制到视频 RAM,因为这里的示例都非常慢性能方面(如果您尝试像这样为更多的精灵设置动画,会开始窒息,而通过优化的组装,您可以在每帧中移动 20+ 8x16 的精灵),并且如果您想做更大的精灵并且突然间您变得非常笨拙必须修补许多 AT 控制代码和许多 gfx 字符 (144,145),而且当您需要在精灵边缘进行剪辑时(并且您只需要打印部分字符,而不是全部字符),这会变得更加令人头疼。

我的意思是您仍然应该尝试掌握教程在做什么以及如何做,它总体上是不错的教程,您可以在上面锻炼您的 Z80 组装技能,但从 demo-scener 的角度来看,多年来一直在做 ZX 演示(并针对高性能全屏 gfx 技巧) - 此代码仅用于学习如何不编写 ZX 代码。 :)

此外,如果您熟悉 ZX BASIC 以及 PRINT 在 BASIC 中的工作原理,那么学习本教程可能会更容易一些。如果您完全不了解 ZX BASIC 并且您只是学习 Z80 组装,那么这种打印例程可能比直接将代码写入视频 RAM 而不使用 ROM 例程更加混乱。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多