Hi members of Cemetech my name is Mike.(But you can refer to me by my screen name) I recently had to migrate from UnitedTI after the shut-down.

Recently, I've been working on a Physics engine and I feel fairly proud of myself before getting to this point. I've got most of the physics parts done(at least I think I do) but came to a complete stop once I got to collision detection.

Now I wanted to ask about debugging my code. I didn't see any rules against simply posting my code. In any case, if it is against the rules, or this is the wrong place for this topic
I apologize.

My Physics routine has two point/vectors stored in memory. The current position of the object and the previous position of the object represent like this


Code:
XPOS:
.db 0
YPOS:
.db 0
PREV_XPOS:
.db 0
PREV_YPOS:
.db 0


Nothing to fancy

The Physics routine first puts the current position in the previous postion and then modifies the current position based on forces and velocity. It then finds the slope of these two points and simply used that slope to see if there is a collision.

Here's the actual code to detect collisions not the physic part.

Code:

;Main Loop
SlopeLoop:
   
   call     xslope
   jr       c,Yonly
   call     yslope
   jr       c,Xonly
   
   cp       l
   ret      c
   ret      z
   
   push     af
   
   ld       a,e
   cp       h
   jr       c,Done
   jr       z,Done
   
   pop      af
   
   jr       SlopeLoop
   
Xonly:
   
    call    xslope
   
    push     af
   
    ld       a,e
    cp       h
    jr       c,Done
    jr       z,Done
   
    pop      af
   
    jr      Xonly       
   
Yonly:
   
    call    yslope
   
    push    af
   
    cp       l
    jr       c,Done
    jr       z,Done
   
    pop      af
   
    jr       Yonly


Done:

    pop     af
           
    ret


I dont think there a problem with the main but I think there a problem with the called routines xslope and yslope

here is the called routine called xslope

Code:
xslope:
;Checks to see if there is an x collision on the x-slope
;   if there is the carry flag is set otherwise reset
;INPUTS:
;   SLOPE:
;       b = y
;       c = x
;   e = PREV_XPOS
;   a = PREV_YPOS
;
;   h = XPOS
;   l = YPOS
;   ix= tilemap address
;OUPUTS:
;   Complicated
;       technically through pushing and poping all the registers
;       are preserved the only expection being e
;       e represent the prev_xpos and is incremented "c" times.
;       IF e equals a tile that is not clear, then it will stop
;       incrementing, set XPOS to e and Velocity X component to zero, and set the
;       carry flag. the carry will be reset if e is increamented "c" times.
;   Preservation:
;       This routine need to called but it destoried the registers that it needs
;       and registers other routines needs while running. To get around this problem
;       all values are pushed before being used, poped and then updated(only e) after use

    push    bc   
    ld      b,c
   
DoXslope:

    push    af
    push    bc
    push    de
    push    hl
    push    ix
   
    call    FindTile        ;Finds a tile based on a=y and e=x ix=tilemap
                            ;Destories All
   
    call    CheckClearTile  ;if tile is clear, carry is reset, otherwise set
   
    jr      c,SkipIncX
   
    pop     ix              ;If this part runs, then it represents that somewhere
    pop     hl              ;between the previous xpos and the current one there
    pop     de              ;is an object and this object is located at e in the
    pop     bc              ;x direction.
    pop     af             
   
    rl      b               ;This checks to see if e needs to be inc or dec
    jr      c,DEC_E1        ;based on wheather b is positive or negitive
                            ;respectively
    rr      b
    inc     e
    jr      SetXPOS
   
DEC_E1:
   
    rr      b
    dec     e

SetXPOS:
   
    ld      a,e             ;Simply this code runs only if a collision has happened
    ld      (XPOS),a        ;So the XPOS is set to e, which represents an x coordinate
                            ;where the collision occured     
   
    xor     a               ;Since it hit something the velocity is set equal
    ld      (Velocity),a    ;to zero
   
    pop     bc
   
    scf                     ;carry is set sense we hit something
   
    ret                     
   
SkipIncX:

    pop     ix
    pop     hl
    pop     de          ;restores everything
    pop     bc
    pop     af
   
    rl      b
    jr      c,DEC_E     ;modifies e based on b
   
    rr      b
    inc     e
   
    inc     b           ;inc and jumps if b != 0
    jr      z,DoXslope
     
    jr      xSlopeDone  ;if b = 0 then no collision occured
DEC_E:
   
    rr      b
    dec     e
 
    djnz    DoXslope
   
xSlopeDone:             
    pop     bc
   
    scf                 ;reset carry flag sense there was not a collision
    ccf
   
    ret


And here is the called routine yslope


Code:

yslope:
;Checks to see if there is an x collision on the x-slope
;   if there is the carry flag is set otherwise reset
;INPUTS:
;   SLOPE:
;       b = y
;       c = x
;   e = PREV_XPOS
;   a = PREV_YPOS
;
;   h = XPOS
;   l = YPOS
;   ix= tilemap address
;OUPUTS:
;   Complicated
;       technically through pushing and poping all the registers
;       are preserved the only expection being a
;       a represent the prev_ypos and is incremented "b" times.
;       IF a equals a tile that is not clear, then it will stop
;       incrementing, set YPOS to a and Velocity Y component to zero, and set the
;       carry flag. the carry will be reset if  is increamented "b" times.
;   Preservation:
;       This routine need to called but it destoried the registers that it needs
;       and registers other routines needs while running. To get around this problem
;       all values are pushed before being used, poped and then updated (only a) after use

    push    bc   
   
DoYslope:

    push    af
    push    bc
    push    de
    push    hl
    push    ix
   
    call    FindTile
    call    CheckClearTile  ;if tile is clear, carry is reset, otherwise set
    jr      c,SkipIncY
   
;------------------------------------------------------------------------
;************************************************************************
;------------------------------------------------------------------------

    pop     ix              ;If this part runs, then it represents that somewhere
    pop     hl              ;between the previous ypos and the current one there
    pop     de              ;is an object and this object is located at a in the
    pop     bc              ;y direction.
    pop     af             
   
    rl      b               ;determines if a needs to be inc or dec
    jr      c,DEC_A1        ;by wheather b is positive or negitive respectivly
   
    rr      b
    inc     a
    jr      SetYPOS

DEC_A1:
    rr      b
    dec     a

SetYPOS:

    push    af              ;a is saved so when the routine exits it will
    ld      (YPOS),a        ;be the same. a is set up as the current ypos
   
    xor     a               ;the y velocity is set to zero sense there was
    ld      (Velocity+1),a  ;a collision in the y direction
   
    pop     af
    pop     bc
   
    scf                     ;carry flag is set sense there was a collision
   
    ret   

;----------------------------------------------------------------------
;**********************************************************************   
;----------------------------------------------------------------------

SkipIncY:

    pop     ix
    pop     hl
    pop     de              ;restores the registers
    pop     bc
    pop     af
   
    rl      b               ;checks to see if a should be inc or dec based on
    jr      c,DEC_A         ;wheater b is positive or negitive respectively
   
    rr      b
    inc     a
   
    inc     b               ;inc and jump if b is not zero
    jr      z,DoYslope
     
    jr      ySlopeDone 
DEC_A:
   
    rr      b
    dec     a
 
    djnz    DoYslope
   
ySlopeDone:
    pop     bc
   
    scf                     ;since no collision occured, reset carry flag
    ccf
   
    ret
 


I'm not sure exactly what the error is. I am open to suggestion or even complete a completely different algorithm, even an already written routine. Any help is appreciated.
Welcome to Cemetech, Mike. Please Introduce Yourself in that thread, and be sure to say hi over on SAX and/or IRC. You've provided some code, which is always a good thing, but I'm afraid you're missing one component of a good request for programming help: you didn't describe what's wrong. You say you're not sure what the error is, but you didn't describe what happens (or doesn't), and what should (or shouldn't) happen instead.
Quote:
Welcome to Cemetech, Mike. Please Introduce Yourself in that thread, and be sure to say hi over on SAX and/or IRC. You've provided some code, which is always a good thing, but I'm afraid you're missing one component of a good request for programming help: you didn't describe what's wrong. You say you're not sure what the error is, but you didn't describe what happens (or doesn't), and what should (or shouldn't) happen instead.


Neutral Hmm.... fair enough

Ok the problem is the collision detection code won't detect collisions and as a result an object goes through tiles. sense gravity is a constant force the object simply goes down through floors instead of stopping(i.e apply the normal force and friction) when the position encounters floors/tiles.

Basically my collision detection works as if it wasn't there, as taking it out does not change how the program works.
Thanks for the clarification, now it makes sense. May I ask what debug steps you have taken thus far to try to track down the issue, if any? It sounded from your first post as though you're not sure if you have a fundamental math error or a coding/implementation error, is that correct?
Okay well after writing my routine I made sure it did one thing. Preserve the state of the registers. So this is what i assembled and ran to make sure it worked


Code:
ld   a,7
ld   b,3
ld   c,9
ld   d,19     ;random numbers
ld   e,4
ld   h,2
ld   l,5

call    xslope

ld   l,[reg you want to display]
ld   h,0
B_CALL(_DispHL)

ret


I did this for each register (with the exception of ix) and as expected e was the only one that changed.

the same was also done with yslope and a respectively.

Next I essentially did the same thing only this time I made sure ix pointed to the tilemap. Next I set a(PREV_YPOS) to row were I knew there was a tile, particularly 40 but set e(PREV_XPOS) such that the coordinates (a,e) in the form of (y,x) would point to an empty tile in the tilemap, which is pointed to by ix, e was set to 48.

I then set b(X-component of the slope) to be something small like 2 to see if e would simply increase by 2 which worked

next I set b to a big number(96) to see if it would not increment the entire 96 to e, but stop once (a,e) pointed to a Clear tile. But to my luck it added the entire 96. And that's what I have been trying to figure out.
Does CheckClearTile work properly? Try putting a jr $ after jr c,SkipIncX to make sure that the code properly detects a collision, then follow the code with a debugger. And what exactly are slope X/Y? Are they essentially velocity values? What are their normal values?

Also, jumping around a lot can waste a bit of space/clocks, you could try something like this, it's not gonna fix your issue but it looks a little neater:

Code:
    inc e
    bit 7,b
    jr      nz,SetXPOS
    dec     e
    dec     e
SetXPOS:
Or depending on what the value of slope X is, you could even just add slopeX to e (ld a,b \ add a,e). But anyway, why are you updating the X position if you hit an object? If you hit an object, shouldn't you stop and not continue moving?

I don't know if you want to give us something more to work with, i don't really know what is going on in your subroutines.
Quote:
Does CheckClearTile work properly?


I'm pretty sure CheckClearTile works. A clear tile, as I defined it, is just a tile whose pointer is 0. Any other number means that it is a solid tile.

Anyways heres CheckClearTile. It fairly simple.


Code:
CheckClearTile:
;Checks to see if a tile is clear or not
;INPUTS:
;_IX= tile pointer
;OUTPUTS:
;_sets carry flag if tile is solid
;_otherwise reset(i.e if it is clear)
;DESTORYS:
;_A
    ld  a,(ix+0)   
CheckClearTile1:

    cp  0
    jr  z,reset
   
    scf
   
    ret
reset:
    scf
    ccf
    ret


So if FindTile Works then this block of code from routine xslope should detect a tile (At least I think so)


Code:
xslope:
    call    FindTile        ;Finds a tile based on a=y and e=x ix=tilemap
                              ;Destories All
    call    CheckClearTile  ;if tile is clear, carry is reset, otherwise set
   
    jr      c,SkipIncX
;
;  code for if it isn't clear
;
SkipIncX:
;
;  code for if it is clear
;
    djnz xslope
    ret


As for FindTile It finds a tile in a tilemap who data is stored like this

Code:
tilemap:
;y dimension
.db #
;x dimension
.db #
;tile data
.db #,#,#,#,#,.......,#


And FindTile code

Code:
FindTile:
;Finds a tile that XPOS,YPOS are in
;INPUTS:
;_E = XPOS
;_A = YPOS
;_IX= tilemap address
;OUTPUT:
;_IX= Pointer to tile
;_HL= tilemap address
;DESTORYS
;_A,B,DE

    ld  d,0
   
    push    de
    ld  e,(ix+1)
   
    srl a
    srl a
    srl a
   
    call    DE_TIMES_A  ;Destories:a,b,de from learn asm in 28 days
   
    ex  de,hl
   
    push    ix
    pop hl
   
    add ix,de           ;again basic indexing. Now ix points to the exact row

    pop de
    srl e
    srl e
    srl e
    add ix,de           ;Now ix points to the row and colunm of tile we start with   

    inc ix              ;Add 2 because of the way tile data is stored     
    inc ix
   
    ret


Quote:
Try putting a jr $ after jr c,SkipIncX to make sure that the code properly detects a collision, then follow the code with a debugger.


I'll try that

Quote:
And what exactly are slope X/Y? Are they essentially velocity values? What are their normal values?


Y slope is simply (YPOS - PREV_YPOS) and X slope is (XPOS - PREV_XPOS). In essence there just Δy/Δx or slope.

At chickendude: thanks for the suggestion I'll try implementing them right away.
Do you have an emulator? You should check out WabbitEmu for Windows or TilEm2 for Linux, try taking a screenshot of what happens, as well as following it in the debuggers.

I can comment on your code, but i honestly don't know where the problem is. To me it looks like you update the x and y values even when there is a collision. And a lot of the code is unnecessary. For example, cp 0 will always reset the carry flag (so you don't need scf \ ccf), and "or a" (or "and a", but "or a" seems to be the standard) is actually a faster and smaller way of doing the same thing. And instead of scf \ ccf, you can use or a or and a, which won't change the value of a but will reset the carry. And all the jumps in SlopeLoop are making me a little dizzy Razz

I don't know if you don't want to post a full zip of your source, but it would help (me) to be able to see what your code is doing Smile

Anyway, it's always nice to see another z80 programmer Very Happy
While we're on the topic of emulators, hopefully without self-advertising too much, we have an online emulator here at Cemetech, called jsTIfied:

http://www.cemetech.net/projects/jstified
Quote:
I can comment on your code, but i honestly don't know where the problem is. To me it looks like you update the x and y values even when there is a collision.


I don't know if this is right but hear me out
The code checks to see if a position between the 2 positions(current postion and previous position) has a tile there.(at least thats what it is supposed to do)

If (a,e) in the form of (y,x) points to a tile in tilemap ix, then the code won't know it hit something until (a,e) actually points to a solid tile. If the position is actually on a solid tile I would want it to "back up" so that its not on the solid tile anymore.

Now the term "back up" is relative so I'll explain
if the difference in the x positions is negative and you "hit" something solid, then you want to increment the xpos once and the opposite is also true.

Likewise if the difference in y positions in negative then you want to decrement the ypos because that actually is moving in the positive direction so that the position isn't on the tile but just outside of it.

Quote:
For example, cp 0 will always reset the carry flag (so you don't need scf \ ccf), and "or a" (or "and a", but "or a" seems to be the standard) is actually a faster and smaller way of doing the same thing. And instead of scf \ ccf, you can use or a or and a, which won't change the value of a but will reset the carry. And all the jumps in SlopeLoop are making me a little dizzy


Thanks, I've use some of these little "tricks" and rewrote my routine.

Quote:
I don't know if you don't want to post a full zip of your source, but it would help (me) to be able to see what your code is doing


Simply put, it just not that organized to give out yet. I lot of old version of the code and numerous other things. Until it gets more organized, I feel that I can only throw out pieces of code. Not to say I won't but....

Quote:
Do you have an emulator? You should check out WabbitEmu for Windows or TilEm2 for Linux, try taking a screenshot of what happens, as well as following it in the debuggers.


I do have emulator as and I've taken a screenshot, but I'm having a little trouble with picasaweb.google.com to get my image up

I'm working on it


At KermMartian: Online huh, I'll try it
Will the object ever be able to move more than one tile at a time? I mean, if your tiles are 8 pixels by 8 pixels, will you ever be able to move 9 or more pixels at a time? I don't know if it's normal to use two variables (for old and new position). I think your slope variables are what i've been calling velocity. What i do is take the player's current position then add the X and Y velocity ("slope") to the X/Y coordinates, and pass these values to the collision detection routine. Check if there is a nonpassable tile, and if there is, block the player's movement (usually set the player's coordinates so that they are aligned against that tile). If the tile is free, then just store those coordinates back to the player's coordinates and continue.
For example:
http://www.mirari.fr/hBcx?.gif

Also, srl a uses 2 bytes and 8 t-states. It's not a huge deal, but rra is one byte and 4 t-states. It'd be quicker to do something like:
and %11111000 ;clear out bottom three bits
rra
rra
rra ;rotate 3 times/divide by 8

And looking through again, you might have reversed your dec e/inc e statements. If the value is negative (meaning the player is going up), you dec e, when maybe you should inc e. Again, i'm not sure how everything's set up, but usually a negative value means going up or left, and positive means going down or right.

EDIT: I don't know why the image isn't showing up, but it's not really that important.
Quote:
Will the object ever be able to move more than one tile at a time? I mean, if your tiles are 8 pixels by 8 pixels, will you ever be able to move 9 or more pixels at a time? I don't know if it's normal to use two variables (for old and new position). I think your slope variables are what i've been calling velocity. What i do is take the player's current position then add the X and Y velocity ("slope") to the X/Y coordinates, and pass these values to the collision detection routine. Check if there is a nonpassable tile, and if there is, block the player's movement (usually set the player's coordinates so that they are aligned against that tile). If the tile is free, then just store those coordinates back to the player's coordinates and continue.


Yes that was the plan to be able to move any amount of bit per frame (however I'm starting to see that maybe a little over my head)

Anyway I tried your method and I went from

this https://lh3.googleusercontent.com/-iq1h8TnkduI/T-EX-LOlQyI/AAAAAAAAAA4/RnFIUCwP2CU/s192/test.gif

to this https://lh4.googleusercontent.com/-qECauVbXDio/T-JCIQhwkoI/AAAAAAAAABI/JU6e5WsVYpw/s192/test2.gif

Thanks, this is better but I guess I had to do something wrong
The basic algorithm that I thought of was this

Add the velocity to the position
Check to see if there is a tile in that position
If there is
then set the position to the smallest/closest multiple of 8 (if the position is 41 then 40, but if its 39 then 32)
Zero the velocity in that direction

here is the actual code for detecting collisions in the y direction


Code:
    ld      a,(Velocity+1)
    neg
    ld      h,a
    ld      a,(YPOS)
    add     a,h
   
    ld      (YPOS),a
   
    ld      h,a
    ld      a,(XPOS)
    ld      e,a
    ld      a,h
   
    call    FindTile
    call    CheckClearTile
    jr      nc,YcollisionDone
   
    ld      a,(YPOS)
    ld      h,a
    and     7
    ld      d,a
    ld      a,8
   
    sub     d
    ld      d,a
   
    ld      a,(Velocity+1)
    bit     7,a
    jr      z,addDY
   
    ld      a,h
    sub     d
   
    jr      YcollisionDone
   
addDY:
    ld      a,h
    add     a,d
   
YcollisionDone:

   ret


May I ask how you would do it, or anybody. appreciate the help.

http://www.mirari.fr/hBcx?.gif
Did you make that, if so fairly impressive.
Velocity+1 is velocityY? Why do you negate it (2's complement it)?
Btw, the "jr YcollisionDone" can be replaced by a ret.

Instead of:

Code:
ld      a,(Velocity+1)
    neg
    ld      h,a
    ld      a,(YPOS)
    add     a,h
     
    ld      (YPOS),a
     
    ld      h,a
    ld      a,(XPOS)
    ld      e,a
    ld      a,h
Try:

Code:
ld      a,(Velocity+1)
    neg
    ld      hl,YPOS
    add     a,(hl)
;    ld (hl),a

    ld      hl,XPOS
    ld      e,(hl)
I also wouldn't store the result back into YPOS, if you want you can push af and pop it later, store the result in an unused register, or switch to the shadow registers. Then if you can pass, store the result. Otherwise, and %11111000 and store that back (at least, for going down). For going up, you could do that then add 8.
After many, many rewrites I finally got it working (mostly)

Notably, I still have 2 problems.
The first is fairly simple I have to make sure that the position doesn't go below zero
I tried this code when I am adding the Velocity to the postion...


Code:
;--------------------------------------------------
;Add Velocity to Position
;--------------------------------------------------
    ld      a,(Velocity)
    ld      h,a
    ld      a,(XPOS)
    add     a,h
    jp      po,XSkip
   
    xor     a
    ld      (Velocity),a

XSkip:
       
    ld      (XPOS),a
   
    ld      a,(Velocity+1)
    neg
    ld      h,a
    ld      a,(YPOS)
    add     a,h
    jp      po,YSkip
   
    xor     a
    ld      (Velocity+1),a
   
YSkip:

    ld      (YPOS),a


But not working. I'm sure it's simple but haven't figured it out (yet)

Now at first glance this appears to work flawlessly. just simple.


Gravity working. It fall on the first platform and then fall to the ground
Normal Force is working. It stops once it hits a ground
Friction working.

The problem is that it only falls off of platform one way not the other
Here's a screenshot of what I mean



It code let you fall off the right but not the left. It think it might be a bug in the physics code and not the collision detection.

Here another demonstration with the platform moved



This code is the updated collision detection


Code:
;assuming ix points to the tilemap
Collisions:
    ld      a,(YPOS)
    ld      hl,Velocity+1
    add     a,(hl)
    ld      (YPOS),a
   
    ld      hl,XPOS
    ld      e,(hl)
   
    push    ix
   
    call    FindTile
    call    CheckClearTile
   
    jr      nc,SkipYCollision
   
   
    ld      a,(YPOS)
    and     %11111000
   
    ld      hl,Velocity+1
    bit     7,(hl)
    jr      z,skipYadd8
    add     a,8
skipYadd8:
    ld      (YPOS),a
    xor     a
    ld      (Velocity+1),a

SkipYCollision:

    pop     ix
   
    ld      a,(XPOS)
    ld      hl,Velocity
    add     a,(hl)
    ld      (XPOS),a
    ld      e,a
   
    ld      a,(YPOS)
   
    call    FindTile
    call    CheckClearTile
   
    jr      nc,SkipXCollision
   
    ld      a,(XPOS)
    and     %11111000
   
    ld      hl,Velocity
    bit     7,(hl)
    jr      z,skipXadd8
    add     a,8
skipXadd8:
    ld      (XPOS),a
    xor     a
    ld      (Velocity),a
SkipXCollision:
    ret


Quote:
Velocity+1 is velocityY? Why do you negate it (2's complement it)?


Yes Velocity+1 is veloctityY. I negate it because I calculate the velocity based on the more used x,y plane rather than a computer plane.[/img]
So a negative velocity means the player falls down?

Also, keep in mind that if you are going to be using smooth (pixel by pixel) scrolling, you will need to test TWO tiles if the sprite is not aligned (or only check for collisions when the sprite is aligned, which might be a little complicated if your sprite can move more than 1 pixel at a time). For example, if your sprite is at X position 4, then you have 4 pixels in the first tile and 4 pixels overlapping into the second tile.

Try adding something like:

Code:
push af
push bc
push de
push hl
push ix
ld a,(ix)
ld hl,0000
ld (curRow),hl ;updates currow and curcol, not sure if this is necessary or not, but i think disphl might update currow
ld l,a
bcall(_DispHL)
pop ix
pop hl
pop de
pop bc
pop af

after the call FindTile (and before CheckClearTile) in the x detection routine to see if it's checking the right tile (you should see the tile number blinking up at the top somewhere).
I seemed to have created some sort of pseudo-physics

In the x-collision part, by changing this

Code:
ld      a,(YPOS)
   
    call    FindTile
    call    CheckClearTile
   
    jr      nc,SkipXCollision
   
    ld      a,(XPOS)
    and     %11111000
   
    ld      hl,Velocity
    bit     7,(hl)
    jr      z,skipXadd8
    add     a,8


by dec a after ld a,(YPOS) and before call FindTile, and changing the jump instruction to jr c,SkipCollision I get this...



This appears to be working even better but it is not working as originally intended.
If you look closely whenever it jumps and descends it only moving in increments of 8, when it should be moving based on acceleration.

and if the add a,8 is changed to add a,7 (or any number smaller than 8 ) then it won't move. This has led me to believe that the acceleration nor the velocity is responsible for its movement (going down) but the add a,8 is.

chickendude, I used what you said but I think it is checking the tile to the left and not the right (at least that what I see) so.. anyway heres what it looks like (with the original code and no changes besides yours)

based on this (and from my own tiledata) the standard floor is 9, the left and right edges of the the platforms are 22 and 25 respectively and blank space is 0. And from what I can tell, it checks the tile right below the bottom of the block.

Lastly when it is on the right platform, on its left edge, the number is zero and not 9 or 22, indicating that it is checking tile immediately to the left of the right platform.

What would it mean if it was checking the right tile? I'm slightly confused.

I gonna try post something later today.
When you're on the platform and it shows 0, is that when you are pressing left? It looks like the x detection is testing the row below the character. You might try also putting a block (with a different id, maybe 26 or 23) on the floor to see if it detects that or if it detects what's below it. When pressing left/right, it should tell you the id of the tile the sprite wants to enter.

And in FindTile, what is the "ld e,(ix+1)" for? Why +1?

Another thing to keep in mind is that ix (and iy) is much slower than the other registers, if you want to use it it's often a good idea to do as much as you can with the other registers before storing the value into ix. Like in your FindTile routine, you could save a couple bytes/clocks by adding de to hl first then pushing hl and popping it into ix.
Quote:
When you're on the platform and it shows 0, is that when you are pressing left?

Yes it is
Quote:
And in FindTile, what is the "ld e,(ix+1)" for? Why +1?

I do that because tile data is stored like this...

Code:
tilemap1:;tile-address
 .db 8; rows=y
 .db 12;col =x
;tiledata
 .db $00,$00,$00,.....,$00,$00,$00

basically, it's just indexing, multiply the number of columns by the y-coordinate (or de*a) to get the row the tile in and then add the x-coordinate to get the exact tile. ix+1 simply points to the number of columns. I know this is just the screen size map so it could be

Code:
ld  h,0
ld  l,e
ld  b,h
ld  c,l

add hl,hl
add hl,bc
add hl,hl

or something along those lines to do quick multiplication by 12 but I want it to work for any tilemap

Quote:
You might try also putting a block (with a different id, maybe 26 or 23) on the floor to see if it detects that or if it detects what's below it. When pressing left/right, it should tell you the id of the tile the sprite wants to enter.


I tried that this is what happened

which make me conclude that it is looking at the tile to the left and not the right. Notice that if you going fast enough you do fall off.

I Think I figured out the problem. I wanted to say that there is something wrong with FindTile but apperently not as it show me the correct tile. I think it has something to do with AND %11111000.
Actually I think I'm on to something. If you notice when the block jumps It get aligned somehow.

and with this screenshot I've made it display hl display if a collision happens or

Code:
    call    FindTile
   
    call    CheckClearTile
   
    jr      nc,SkipXCollision

;----------------------
;stuff I added
    ld      hl,$0000
    ld      (844Bh),hl
    B_CALL(_DispHL)
;-----------------------
    ld      a,(XPOS)
    and     %11111000
.....
SkipXCollision:


and again if you'll notice, It only says theres a collision while in the air, which is werid so maybe theres something wrong with CheckClearTlie
Well, you want it to be aligned if there is a collision, i think it's just checking the wrong tile for a collision. If you put the tile that is beside the platform on the ground, will the block stop? Also, remember that if the X velocity is negative, you need to check the tile to the left. Dividing by 8 should be fine. But if the X vel is positive, you'll need to add 8 (before dividing) or 1 (after dividing) to check the tile to the right.

Where is the player at YPOS=0? At the top or at the bottom?
Quote:
If you put the tile that is beside the platform on the ground, will the block stop

It should. This screen shot is taken using my modified code of the x-collision(dec a,jr c instead of jr nc) and this is what happens

When it displays zero then it means that I'm pressing left but the object can't go left because of a collision. While the screenshot doesn't do a good job showing it, the object will do the same if coming from the left but it will let 7/8 of the sprite through. This is due to the fact that the sprite is drawn from the bottom up, left to right, so the code needs to check 8 from the sprite position in x and y direction when it checks movement (obviously I knew that I was just trying to solve the gravity problem first) but I think it might be time to just go ahead and do those changes now anyway.

So a basic algorithm for this would be..

Do y collision
Find the tile the position is located it
check to see if that tile is clear
if theres a collision, align it
subtract 8 from the y position (since the ypostion is at the bottom of the sprite
Do y collision again
repeat all steps for x

Or is there a different way to think about it.

Although I'm pretty sure I'm not the first I Also figured out the simple zero problem
if you add 8(or the width of the sprite) to the xpos and the number isn't bigger than 8 then set it to zero

and you can do the same with the ypos to with no changes other than your dealing with the y and not the x

chickendude though I haven't quoted you I belive I've answered your question, and I tried to post this as early as I could.

I'm going to try to Implement the changes and post something today
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement