Login

Subversion Repositories NedoOS

Rev

Rev 751 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

objectslogic
        ld a,(pgmetatilemap)
        SETPGC000

        ld ix,objects
objectslogic0
        ld a,(ix+obj.y16+1)
        cp DELETEDYHIGH
        jp z,objectslogic0_skip

        ld l,(ix+obj.animaddr16+0)
        ld h,(ix+obj.animaddr16+1)
        ld e,(hl)
        inc hl
        ld d,(hl) ;de = phase
        inc hl
        dec (ix+obj.animtime)
        jr nz,logic_nonextphase
        ld a,(hl) ;new animtime
        inc hl
        ld (ix+obj.animtime),a
        ld e,(hl)
        inc hl
        ld d,(hl) ;de = phase
        ld a,d
        cp 0xc0
        jr nc,logic_nocycleanim
        ex de,hl
        ;ld e,(hl)
        inc hl
        ;ld d,(hl) ;de = phase (>=0xc000) or new animaddr (<0xc000)
logic_nocycleanim
        dec hl
        ld (ix+obj.animaddr16+0),l
        ld (ix+obj.animaddr16+1),h
logic_nonextphase

        ld l,(ix+obj.xspeed16+0)
        ld h,(ix+obj.xspeed16+1)
        ld e,(ix+obj.x16+0)
        ld d,(ix+obj.x16+1)
        add hl,de
        ld (ix+obj.x16+0),l
        ld (ix+obj.x16+1),h
        ld l,(ix+obj.yspeed16+0)
        ld h,(ix+obj.yspeed16+1)
        inc hl
        inc hl
        inc hl
        inc hl ;gravity
         ld a,h
         rla
         jr c,gravityok
         ld de,8*YSUBPIX8
         or a
         sbc hl,de
         add hl,de
         jr c,gravityok
         ex de,hl
gravityok
        ld (ix+obj.yspeed16+0),l
        ld (ix+obj.yspeed16+1),h
        ex de,hl ;de=yspeed
       
        ld l,(ix+obj.y16+0) ;*YSUBPIX8
        ld h,(ix+obj.y16+1)
        bit 7,(ix+obj.flags)
        jr nz,logic_nocheckfloor
;check floor
        push de ;yspeed
        push hl ;y
        ld c,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld b,(ix+obj.x16+1)
         ld de,32*YSUBPIX8
         add hl,de ;координата прямо под ногами
        call gettile_bycoords
        pop hl ;yspeed
        pop bc ;y
          ;ld c,(ix+obj.y16+0)
          ;ld b,(ix+obj.y16+1)
          add hl,bc
        cp FIRSTSOLIDTILE;32
         res 0,(ix+obj.flags) ;not on floor
        jr c,nofloor
         cp FIRSTOBJTILE
        jr nc,nofloor
         set 0,(ix+obj.flags) ;not on floor
;выравнивание по y на 16(пикс)*YSUBPIX8
        ld a,l
        and 16*YSUBPIX8;128
        ld l,a
        ld (ix+obj.yspeed16+0),0
        ld (ix+obj.yspeed16+1),0
        jr floorok
nofloor
        push hl ;y16

        ld l,(ix+obj.y16+0) ;*YSUBPIX8
        ld h,(ix+obj.y16+1)
        ld c,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld b,(ix+obj.x16+1)
         ;ld de,0
         ;add hl,de ;координата прямо в голове
        call gettile_bycoords
        cp FIRSTBETONTILE;64
        pop hl ;y16
        jr c,noceiling
;выравнивание по y на 16(пикс)*8 вверх
        ld a,l
        or 16*YSUBPIX8-1;127
        ld l,a
        inc hl
        ld (ix+obj.yspeed16+0),0
        ld (ix+obj.yspeed16+1),0        
noceiling
floorok
        jr logic_checkfloorq
logic_nocheckfloor
;hl=y
;de=yspeed
        add hl,de
        ld a,h
        cp METATILEMAPHGT*16*YSUBPIX8/256
        jr c,logic_nofalltohell
        ld h,DELETEDYHIGH
logic_nofalltohell
logic_checkfloorq
        ld (ix+obj.y16+0),l
        ld (ix+obj.y16+1),h
objectslogic0_skip
        ld bc,OBJSIZE
        add ix,bc
        bit 7,(ix+obj.y16+1) ;yhigh
        jp z,objectslogic0
        ret

bulletslogic
        ld a,(pgmetatilemap)
        SETPGC000

        ld ix,bullets
bulletslogic0
        bit 7,(ix+obj.y16+1) ;yhigh
        ret nz
        ;jr $
;если health=1, то это мёртвая пуля, этот слот можно использовать
        dec (ix+obj.health)
        jr nz,bulletslogic_noremove
        ld (ix+obj.y16+1),DELETEDYHIGH;0x7f ;yhigh
        inc (ix+obj.health)
        jp bulletslogic_skip        
bulletslogic_noremove
        ld l,(ix+obj.xspeed16+0)
        ld h,(ix+obj.xspeed16+1)
        ld e,(ix+obj.x16+0)
        ld d,(ix+obj.x16+1)
        add hl,de
        ld (ix+obj.x16+0),l
        ld (ix+obj.x16+1),h

;TODO каждый второй фрейм
ENEMYHGT=32*YSUBPIX8
ENEMYWID=16*XSUBPIX8 ;(in double pixels)
BULLETWID=8*XSUBPIX8 ;(in double pixels)
;TODO учесть размер врага
;попали, если enemyy<=bullety<=enemyy+ENEMYHGT и enemyx-BULLETWID<=bulletx<=enemyx+ENEMYWID
         ;<--->
;   |------|

;check enemy
        ld e,(ix+obj.y16+0) ;*YSUBPIX8
        ld d,(ix+obj.y16+1)
        ld c,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld b,(ix+obj.x16+1)
        ld a,d
        cp DELETEDYHIGH
        jp z,bulletslogic_checkenemy0q
;de=bullety
;bc=bulletx
        exx
        ld bc,OBJSIZE
        exx
        ld iy,objects+obj.sz
bulletslogic_checkenemy0
        bit 7,(iy+obj.y16+1) ;yhigh
        jr nz,bulletslogic_checkenemy0q
;enemyx-BULLETWID<=bulletx<=enemyx+ENEMYWID
;-BULLETWID<=bulletx-enemyx<=ENEMYWID
;-(ENEMYWID+BULLETWID)<=enemyx-bulletx-BULLETWID<=0
        ld l,(iy+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld h,(iy+obj.x16+1) ;enemyx
        ;ld a,l
        ;sub BULLETWID
        ;ld l,a
        ;jr nc,$+3
        ;dec h
        or a
        sbc hl,bc ;bc=bulletx
        jr nc,bulletslogic_checkenemy_skip
        ld a,l
        add a,ENEMYWID;+BULLETWID
        ld l,a
        jr nc,bulletslogic_checkenemy_skip
        inc h
        jr nz,bulletslogic_checkenemy_skip
bulletslogic_checkenemy_xok
;enemyy<=bullety<=enemyy+ENEMYHGT?
;0<=bullety-enemyy<=ENEMYHGT?
;-ENEMYHGT<=enemyy-bullety<=0?
        ld l,(iy+obj.y16+0) ;*YSUBPIX8
        ld h,(iy+obj.y16+1) ;enemyy
        or a
        sbc hl,de ;de=bullety
        jr nc,bulletslogic_checkenemy_skip
        ld a,l
        add a,ENEMYHGT-1
        ld l,a
        jr nc,bulletslogic_checkenemy_skip
        inc h
        jr nz,bulletslogic_checkenemy_skip
bulletslogic_checkenemy_yok
;попали!!!
        ld (ix+obj.y16+1),DELETEDYHIGH ;уничтожаем пулю
;отнимаем энергию
        ld a,(iy+obj.health)
        sub 10
        ld (iy+obj.health),a
         ld a,9
        jr nc,bulletslogic_enemyfound_notdead
        set 7,(iy+obj.flags) ;dead
        ld (iy+obj.yspeed16+0),-8*YSUBPIX8
        ld (iy+obj.yspeed16+1),-1
        ld (iy+obj.xspeed16+0),2*XSUBPIX8
        ld (iy+obj.xspeed16+1),0
         ld a,10 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
bulletslogic_enemyfound_notdead
        push bc
        push de
         call sfxplay
        pop de
        pop bc
bulletslogic_checkenemy_skip
        exx
        add iy,bc
        exx
        jr bulletslogic_checkenemy0
bulletslogic_checkenemy0q
;~check enemy
       
;check wall
        ld l,(ix+obj.y16+0) ;*YSUBPIX8
        ld h,(ix+obj.y16+1)
          ld c,(ix+obj.yspeed16+0)
          ld b,(ix+obj.yspeed16+1)
          add hl,bc
        push hl
        ld c,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld b,(ix+obj.x16+1)
         ld a,c
         ;add a,2*XSUBPIX8
         sub 6*XSUBPIX8
         ld c,a
         ;adc a,b
         ;sub c
         ld a,b
         sbc a,0
         ld b,a
        call gettile_bycoords
        ;inc l
        ;ld a,(hl)
        pop hl
        sub FIRSTBETONTILE;32
        cp FIRSTOBJTILE-FIRSTBETONTILE
        jr nc,bulletslogic_nocrash
        ld h,DELETEDYHIGH ;удалить
        ld (ix+obj.xspeed16+0),0
        ld (ix+obj.xspeed16+1),0
        ld (ix+obj.yspeed16+0),0
        ld (ix+obj.yspeed16+1),0
bulletslogic_nocrash
        ld (ix+obj.y16+0),l
        ld (ix+obj.y16+1),h
bulletslogic_skip
        ld bc,OBJSIZE
        add ix,bc
        jp bulletslogic0

fire
genbullet
;сначала найдём пустые места в списке пуль (т.е. где yhigh==0x7f)
;если таких нет, то добавляем в конец
        ld iy,bullets
genbullet_findempty0
        bit 7,(iy+obj.y16+1) ;yhigh
        jr nz,genbullet_findempty0q
        ld a,(iy+obj.y16+1) ;yhigh
        cp DELETEDYHIGH
        jr z,genbullet_struct
        ld bc,OBJSIZE
        add iy,bc
        jr genbullet_findempty0
genbullet_findempty0q
        ;jr $
curbulletlistend=$+2
        ld iy,bullets
        push iy
        ld de,-bulletlistend
        add iy,de
        pop iy
        ret c ;no room

        call genbullet_struct
        ld bc,OBJSIZE
        add iy,bc
genbullet_terminate
        ld (curbulletlistend),iy
        ld (iy+obj.y16+1),-1
        ret

BULLETSPEED=MAXSPEED ;(in double pixels)
genbullet_struct
         ld a,1 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call sfxplay
         
         ld a,(lastdir) ;0=right
         or a
         ld de,BULLETSPEED;4
         jr z,$+5
         ld de,-BULLETSPEED;4
         ld (iy+obj.xspeed16),e
         ld (iy+obj.xspeed16+1),d

         ld de,bulletanim_right
         jr z,$+5
         ld de,bulletanim_left
        ld (iy+obj.animaddr16),e
        ld (iy+obj.animaddr16+1),d
        ld (iy+obj.animtime),1
        ld (iy+obj.health),100
        ld a,(ix+obj.x16)
        add a,4*XSUBPIX8
        ld (iy+obj.x16),a
        ld a,(ix+obj.x16+1)
        adc a,0
        ld (iy+obj.x16+1),a
        ld a,(ix+obj.y16)
        add a,16*YSUBPIX8
        ld (iy+obj.y16),a
        ld a,(ix+obj.y16+1)
        adc a,0
        ld (iy+obj.y16+1),a
        xor a
        ld (iy+obj.yspeed16),a
        ld (iy+obj.yspeed16+1),a
        ld (iy+obj.flags),a
        ret
       

logic
        call objectslogic
        call bulletslogic
        call herocontrol
        ret
       
;hero control
herocontrol
joystate=$+1
oldjoystate=$+2
        ld bc,0
        ld a,c
        ld (oldjoystate),a
        xor b
        ld b,a
;bit - button (ZX key)
;7 - A (A)
;6 - B (S)
;5 - Select (Space)
;4 - Start (Enter)
;3 - Up (7)
;2 - Down (6)
;1 - Left (5)
;0 - Right (8)
        bit 6,c
        push bc
        call nz,kick
        pop bc
        bit 5,c
        jr z,nofire
        bit 5,b
        jr z,nofire
        push bc
        ld ix,objects
        call fire
        pop bc
nofire

        ld ix,objects
        ld l,(ix+obj.xspeed16+0)
        ld h,(ix+obj.xspeed16+1)
        bit 1,c
        jr z,noleft
        ld a,h
        or a
        jp m,nostartrunleft
        ld a,1
        ld (lastdir),a
         ld de,heroanim_runleft
        ld (ix+obj.animaddr16+0),e
        ld (ix+obj.animaddr16+1),d
nostartrunleft
        ld de,-1
        add hl,de
        ld de,-MAXSPEED
        or a
        sbc hl,de
        ld a,h
        add hl,de
        or a
        jr z,leftq
        ex de,hl
        jr leftq
noleft
        bit 0,c
        jr z,noright
        ld a,h
        or a
        jp m,startrunright
        or l
        jr nz,nostartrunright
startrunright
        xor a
        ld (lastdir),a
         ld de,heroanim_runright
        ld (ix+obj.animaddr16+0),e
        ld (ix+obj.animaddr16+1),d
nostartrunright
        ld de,1
        add hl,de
        ld de,MAXSPEED
        or a
        sbc hl,de
        ld a,h
        add hl,de
        or a
        jr nz,leftq
        ex de,hl
        jr leftq
noright
         bit 0,(ix+obj.flags) ;on floor?
         jr z,leftq ;не тормозим на лету
        ld a,h
        or l
        ld e,a
         bit 7,h
         jr z,$+3
         inc hl
         sra h
         rr l
         ld a,h
         or l
         jr nz,leftq
         ld a,e
         or a
         jr z,leftq ;уже стояли
lastdir=$+1
         ld a,0 ;/1
         or a
         ld de,heroanim_standright
         jr z,$+5
         ld de,heroanim_standleft
        ld (ix+obj.animaddr16+0),e
        ld (ix+obj.animaddr16+1),d
leftq
        ld (ix+obj.xspeed16+0),l
        ld (ix+obj.xspeed16+1),h
;проверить, что не въехали в стену в текущем направлении и отскочить
       push bc
        bit 7,h
        jp nz,checkleftwall
        ld l,(ix+obj.y16+0) ;*YSUBPIX8
        ld h,(ix+obj.y16+1)
        ld c,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld b,(ix+obj.x16+1)
         ld de,16*YSUBPIX8
         add hl,de ;координата на уровне пояса
        call gettile_bycoords
        dec l
        ld a,(hl) ;правее центра
        cp FIRSTBETONTILE;64
        jp c,checkleftwallq ;not beton
         cp FIRSTOBJTILE
         jr nc,checkwall_obj
;врезались справа, выравниваем x = (x&0xf0) - 1
         ld de,heroanim_standright
        ld (ix+obj.animaddr16+0),e
        ld (ix+obj.animaddr16+1),d
         ld (ix+obj.xspeed16+0),0
         ld (ix+obj.xspeed16+1),0
        ld l,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld h,(ix+obj.x16+1)
        ld a,l
        and -8*XSUBPIX8
        ld l,a
        dec hl
        ld (ix+obj.x16+0),l ;*XSUBPIX8 (in double pixels)
        ld (ix+obj.x16+1),h        
        jp checkleftwallq
checkwall_obj
;берём объект!!!
        ld (hl),0
        ex de,hl
        push de
         ld a,3 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call sfxplay
         
;нельзя восстанавливать графику в течение 2 следующих отрисовок
        ld a,2+1
        ld (skipfastredraws),a
         
        pop de
       
        ;call uvscroll_filltilemap
        call countmetatilemap ;hl=metatilemap + (yscroll/16*METATILEMAPWID) + (x2scroll/8)
;de=тайл, который мы только что изменили
;мы должны пропустить по y ровно столько строчек, чтобы hl пересёк тот тайл, который мы только что изменили

        ld a,d
        sub h ;a=y
        cp TILEMAPHGT/2
        jr nc,getobjnofill
       
        ;ld a,3 ;y по умолчанию
       
        ;push af
        ;add a,h
        ;ld h,a ;hl=metatilemap+
        ;pop af
        ld h,d
        push af ;y
       
        ex de,hl
        ld hl,TILEMAP
        ld bc,TILEMAPWID*2
        or a
        jr z,getobjfill0q
getobjfill0
        add hl,bc
        dec a
        jr nz,getobjfill0
getobjfill0q
        ex de,hl
        call uvscroll_filltilemap_line
       
        ;call uvscroll_showtilemap
        call uvscroll_showtilemap_counthlde
        pop af ;y
        or a
        jr z,getobjshow0q
        ld b,a
getobjshow0
        push bc
        ld bc,16*(UVSCROLL_WID/512)
        add hl,bc ;y*(UVSCROLL_WID/512) ;allscroll+...
        ex de,hl
        ld bc,TILEMAPWID*2
        add hl,bc ;tilemap+...
        ex de,hl
        pop bc
        djnz getobjshow0
getobjshow0q
        ld b,1
        call uvscroll_showtilemap_b
getobjnofill
        jr checkleftwallq
checkleftwall
        ld l,(ix+obj.y16+0) ;*YSUBPIX8
        ld h,(ix+obj.y16+1)
        ld c,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld b,(ix+obj.x16+1)
         ld de,16*YSUBPIX8
         add hl,de ;координата на уровне пояса
        call gettile_bycoords
        inc l
        ld a,(hl) ;левее центра
        cp FIRSTBETONTILE;64
        jr c,checkleftwallq ;not beton
         cp FIRSTOBJTILE
         jr nc,checkwall_obj
;врезались слева, выравниваем x = (x+15)&0xf0
         ld de,heroanim_standleft
        ld (ix+obj.animaddr16+0),e
        ld (ix+obj.animaddr16+1),d
         ld (ix+obj.xspeed16+0),0
         ld (ix+obj.xspeed16+1),0
        ld l,(ix+obj.x16+0) ;*XSUBPIX8 (in double pixels)
        ld h,(ix+obj.x16+1)
        ld bc,8*XSUBPIX8-1
        add hl,bc
        ld a,l
        and -8*XSUBPIX8
        ld l,a
        ld (ix+obj.x16+0),l ;*XSUBPIX8 (in double pixels)
        ld (ix+obj.x16+1),h

checkleftwallq
       pop bc

        ld l,(ix+obj.yspeed16+0)
        ld h,(ix+obj.yspeed16+1)
        bit 7,c
        jr z,nojump
        bit 7,b
        jr z,nojump ;не изменилась кнопка
       
;check floor
        bit 0,(ix+obj.flags) ;on floor
        jr z,nojump

        ld hl,-60
        ld (ix+obj.yspeed16+0),l
        ld (ix+obj.yspeed16+1),h
        ld e,(ix+obj.y16+0)
        ld d,(ix+obj.y16+1)
        add hl,de
        ld (ix+obj.y16+0),l
        ld (ix+obj.y16+1),h
       
       
nojump

        ret

KICKDIST_X=8*XSUBPIX8
KICKDIST_Y=32*YSUBPIX8
kick
;герой толкает ближайшего врага
        ld ix,objects
        ld l,(ix+obj.x16+0)
        ld h,(ix+obj.x16+1)
        ld e,(ix+obj.y16+0)
        ld d,(ix+obj.y16+1)
       
        ld ix,objects+OBJSIZE
kick0
        bit 7,(ix+obj.y16+1) ;yhigh
        ret nz
        push de
        push hl
        ld c,(ix+obj.x16+0)
        ld b,(ix+obj.x16+1)
        or a
        sbc hl,bc
        ld bc,KICKDIST_X
        add hl,bc
        ld bc,KICKDIST_X*2
        or a
        sbc hl,bc
        jr nc,kick_xskip
        ex de,hl
        ld c,(ix+obj.y16+0)
        ld b,(ix+obj.y16+1)
        or a
        sbc hl,bc
        ld bc,KICKDIST_Y
        add hl,bc
        ld bc,KICKDIST_Y*2
        or a
        sbc hl,bc
        jr nc,kick_xskip
         ld a,11 ;3 перезвяк, 5 диньк, 7 тормоз, 9 миниприз, 10 приз, 11 бум
         call sfxplay
        pop hl
        pop de
        ld (ix+obj.yspeed16+0),-80
        ld (ix+obj.yspeed16+1),-1
        ld (ix+obj.xspeed16+0),8
        ld (ix+obj.xspeed16+1),0
        ret
kick_xskip
        pop hl
        pop de

        ld bc,OBJSIZE
        add ix,bc
        jp kick0

gettile_bycoords
        dup 3
        srl h
        rr l
        edup
        dup 4
        add hl,hl
        edup
        dup 3
        srl b
        rr c
        edup
        dup 3
        srl b
        rr c
        edup
        ld a,c
         sub 3
        cpl
        ld l,a
        ld a,h
         sub 3 ;проверять будем тайл в ногах, а не в голове
        cpl
        ld h,a
        ld a,(hl) ;tile в ногах
        ret