It is currently Tue Oct 24, 2017 4:34 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 131 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8, 9  Next
Author Message
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Fri Aug 04, 2017 11:20 pm 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
Hello, everybody. A bit further, I have player movement working, except:

* of course, timer state needs to be extended a bit to have the pop-out action
* right now all box calculations are done with the top left x,y, which makes player movement with the sprite quite funny if you traverse an intersection and are not completely in the adjunct box.

I need to think through how best to solve the latter problem, if anyone has any ideas, feel free to reply. In the mean time, I've attached a ROM to show behavior.

Attachment:
wow-player-test.nes [40.02 KiB]
Downloaded 30 times


relevant code:

Code:
/**
 * move_players()
 */
void move_players(void)
{
  for (i=0;i<2;++i)
    {
      // Get the player's box.
      a=div24(stamps[STAMP_X(i)]-8);
      b=div24(stamps[STAMP_Y(i)]-8);
      c=(b*10)+a; // C is now the box #
      d=dungeon[c];

      if (stamps[STAMP_XTRA_A(i)]==TRUE)
        {
          // Player inside box.
          if (sec==0)  // One second has elapsed.
            {
              stamps[STAMP_XTRA_B(i)]--;
              if (stamps[STAMP_XTRA_B(i)]==0x00)
                {
                  stamps[STAMP_XTRA_A(i)]=FALSE;
                }
            }
          else
            {
              // do nothing, for now.
            }
        }
      else
        {
          // Player outside box.
          if (stamps[STAMP_XTRA_B(i)]==0x00)
            {
              // Eject player
              stamps[STAMP_Y(i)]=PIXEL_BOX_Y(5); // Place inside playfield.
              stamps[STAMP_XTRA_B(i)]=0xff; // Indicate player has been ejected.
              if (i==0)
                {
                  yellow_door_state=CLOSED;
                }
              else
                {
                  blue_door_state=CLOSED;
                }
            }
          else
            {
              // Player is free to move, move about.
              if ((stamps[STAMP_STATE(i)] == STATE_PLAYER_RIGHT_IDLE) ||
                  (stamps[STAMP_STATE(i)] == STATE_PLAYER_LEFT_IDLE)  ||
                  (stamps[STAMP_STATE(i)] == STATE_PLAYER_UP_IDLE)    ||
                  (stamps[STAMP_STATE(i)] == STATE_PLAYER_DOWN_IDLE))
                {
                  // Player is idle, do nothing, else...
                }
              else
                {
                  // Player wants to move.
                  if (stamps[STAMP_STATE(i)]==STATE_PLAYER_RIGHT)
                    {
                      if (d&1<<4)
                        {
                          // Right wall nearby.
                          if (stamps[STAMP_X(i)]==PIXEL_BOX_X(a))
                            {
                              // don't do a damned thing.
                            }
                          else
                            {
                              stamps[STAMP_X(i)]++;
                            }
                        }
                      else
                        {
                          stamps[STAMP_X(i)]++;
                        }
                    }
                  else if (stamps[STAMP_STATE(i)]==STATE_PLAYER_LEFT)
                    {
                      if (d&1<<6)
                        {
                          // Left wall nearby
                          if (stamps[STAMP_X(i)]==PIXEL_BOX_X(a))
                            {
                              // Don't do anything
                            }
                          else
                            {
                              stamps[STAMP_X(i)]--;
                            }
                        }
                      else
                        {
                          stamps[STAMP_X(i)]--;
                        }
                    }
                  else if (stamps[STAMP_STATE(i)]==STATE_PLAYER_UP)
                    {
                      if (d&1<<7)
                        {
                          // Up wall nearby
                          if (stamps[STAMP_Y(i)]==PIXEL_BOX_Y(b))
                            {
                              // Don't do anything
                            }
                          else
                            {
                              stamps[STAMP_Y(i)]--;
                            }
                        }
                      else
                        {
                          stamps[STAMP_Y(i)]--;
                        }
                    }
                  else if (stamps[STAMP_STATE(i)]==STATE_PLAYER_DOWN)
                    {
                      if (d&1<<5)
                        {
                          // Down wall nearby
                          if (stamps[STAMP_Y(i)]==PIXEL_BOX_Y(b))
                            {
                              // Don't do anything.
                            }
                          else
                            {
                              stamps[STAMP_Y(i)]++;
                            }
                        }
                      else
                        {
                          stamps[STAMP_Y(i)]++;
                        }
                    }
                }
            }
        }
    }
}


-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Sun Aug 06, 2017 11:38 pm 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
Day 3 of still trying to hammer through the controls, still stuck.

The intended behavior is to have the player traverse into an opening only if their feet are all the way at the extreme end of the box, if they aren't, then the player moves in the last successful direction until the feet touch the box extreme end.)

trying to do this without resorting to more pedestrian methods is making my head hurt.

-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 1:38 am 
Offline
User avatar

Joined: Sat Jul 12, 2014 3:04 pm
Posts: 936
Oh, pac-man/Zelda1-style moves? That's fairly simple.
Code:
//pseudocode
//once per frame...
if (any direction pressed)
   if (aligned with tile)
      move (pressed direction)
      lastmove = pressed
      alignedWithIntersection = false
   else if //not aligned
      if (pressed direction is at right angle to last moved direction)
         move (last moved)
      else
         move (pressed) //either toward or opposite last move
         lastmove = pressed
      //then check alignment with possible intersections
      //often accomplished with modulo
      //note that you only need check one coordinate
      //based on what direction lastmove is


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 11:05 am 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
The modulo is the problem here, given an integer divide by 24 such as:

Code:
;; void __fastcall__ div24(unsigned char d);
_div24: lsr
        lsr
        lsr
        sta   TEMP
        lsr
        lsr
        adc   TEMP
        ror
        lsr
        adc   TEMP
        ror
        lsr
        rts


How can I determine a modulo? Is it sitting here in temp at some point?

-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 11:14 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6304
Location: Seattle
No, the remainder is thrown away in the carry bits as it does the math.

That routine's actually calculating
TEMP = (arg/8)
TEMP += (arg/32)
TEMP += (arg/128)+!!(arg&64)

.... that's not ÷24, that's ÷6.


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 11:20 am 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
That's what I figured. I'm trying to see how I can handle the collision detection sanely, without needing to resort to a modulo, as each box is 24 pixels by 24 pixels (a 3x3 set of tiles).

-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 11:24 am 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
I am deathly afraid of how much code will be added if I use a modulo operator (%) here...

-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 11:31 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6304
Location: Seattle
I have a trivial PIC asm get-remainder routine that just works by manually doing to the long division and throwing away the quotient, something akin to

Code:
uint8 getremainder(uint8 dividend, uint8 divisor) {
  uint8 count=1;
  while (! divisor & 0x80) { divisor<<=1; count++; }
  for (; count; count--, divisor >>=1) {
    if (dividend > divisor) dividend -= divisor;
  }
  return dividend;
}
No idea if cc65's comparably efficient.

For ÷24 just unrolling that's probably not unreasonable.


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 11:49 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
The other way to do it is to represent all character positions in world space using units of 1/256 cell. This makes collision detection easier, as you have a whole number of cells and fraction of cells, and you can easily multiply by 24 for display:

Code:
; assume actor_x is in tiles and actor_xsub is in 1/256 tiles
lda actor_x,x
sta temp_hi
lda actor_xsub,x
asl a
rol temp_hi  ; temp_hi:A = X*2

adc actor_xsub,x
sta temp_lo
lda temp_hi
adc actor_x,x  ; A:temp_lo = X*3

.repeat 3
  asl temp_lo
  rol a  ; A:templo = X*6, X*12, X*24
.endrepeat

; by now, A is pixel position of sprite


As for walking into a wall edge-on, I'd recommend walking toward the center of the cell instead of walking in the same direction as before. This way, if you slighly overshoot the area between walls, you'll back up into the cell close to you instead of the next cell up. Should I draw a diagram of this suggestion to illustrate?


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 12:28 pm 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
Sure.

-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 3:26 pm 
Offline
User avatar

Joined: Sat Jul 12, 2014 3:04 pm
Posts: 936
Then just store the "distance to next cell", with 0 being aligned, decrement each time you move…and if you turn around halfway, set it to 23-last instead of decrementing it. No modulo necessary by keeping track of it (and it doubles as the "aligned" variable).


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 3:28 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
Attachment:
press_against_wall_options.gif
press_against_wall_options.gif [ 20.6 KiB | Viewed 510 times ]


A: The character stops just past the center of the cell. Then the player presses toward a wall. But because movement is blocked by a wall, the character finishes entering the cell he was last entering before turning into the next hallway.

B: The character stops just past the center of the cell. Then the player presses toward a wall. But because movement is blocked by a wall, the character inches toward the center of the cell and then proceeds down the nearest hallway.


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 3:33 pm 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
Myask wrote:
Then just store the "distance to next cell", with 0 being aligned, decrement each time you move…and if you turn around halfway, set it to 23-last instead of decrementing it. No modulo necessary by keeping track of it (and it doubles as the "aligned" variable).


Makes sense, I see this in an older page of my notes, I just didn't haven't been able to think it all the way through.

Collision detection code has always been my steep hill, and I always have to fully understand the conditions to states, before I can hammer it out.

Everybody has provided excellent info. I am going to digest it, and keep working through the problem.

Thanks,
-Thom


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Mon Aug 07, 2017 4:00 pm 
Offline
User avatar

Joined: Sat Jul 12, 2014 3:04 pm
Posts: 936
I should note that the (23-last) is assuming you're using 24-pixel cells [invert (24-last)and decrement combined], and the decrement in that and elsewhere assuming that you're moving the sprite at 1px/frame.

You'd have to add a compare vs 12 to go "should I turn around" on pressing a right-angle direction to get behavior B tepples diagrammed.
My suggestion was instead to "continue to next cell if a direction is held unless you explicitly turn around"…which I'm not sure is better. Pac-man, you rarely want to turn around because a ghost is behind you, and turning before the corner causing you to reverse course into a ghost would be bad. However, if you press it late and it doesn't turn you around, which my behavior C wouldn't, then that might also be bad.


Top
 Profile  
 
 Post subject: Re: WIP: Wizard of Wor
PostPosted: Thu Aug 10, 2017 10:42 pm 
Offline

Joined: Mon Jul 03, 2017 4:37 pm
Posts: 98
Still working through it.. sigh.. I suck.

-Thom


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 131 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8, 9  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


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 post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group