It is currently Sun Dec 09, 2018 5:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: player movement
PostPosted: Tue May 09, 2006 4:43 pm 
Offline
User avatar

Joined: Tue Jan 17, 2006 10:39 am
Posts: 143
Location: North Carolina
Hello,


I've been talking to Tokumaru a lot recently about the players movement inside screens/name tables. I'd just like to get some other opinions on how others are handling this situation. I'm currently working on a side scroller with two screens right now (starting small). I'd like to have my character start out at the beginning of NT0 and once the character reaches 128 (middle of the screen) stay there until it reaches 384 (in NT1) where the background will stop scrolling and the character will walk to the end of the screen. I had done some testing with comparing when the hotspot my character was > 128. Once the character reached 128 I just stopped updating the sprites tiles on the screen but kept the animation going and the coordinates of the player on the screen updating. This worked out okay except for when the player goes in the opposite direction. The sprite tiles then update to the coordinates of the last position of the previous location on the screen. So the player just "jumps" to that coordinate (in the wrong direction).
So anyway, what advice can you give me about keeping the character in the middle of the screen during movement except when they reach the ends of the screen?

Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 09, 2006 5:06 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
This is what I do for my games (not for NES, but it should still work for NES):

Keep vars for X scroll, Y scroll, X,Y position of player -- in addition to Sprite data which is to be DMA'd

C-esque psuedo code to give the idea:

Code:
X_scroll = X_player - 128;
if(X_scroll < X_min)
  X_scroll = X_min;
if(X_scroll > X_max)
  X_scroll = X_max;

Sprite_X = X_Player - X_scroll;

// ditto for Y


All enemies and other sprites will need to be adjusted according to X and Y scroll of course, but that's something you'd have to do anyway.


With your example of only having 2 screens, X_min would probably be 0, and X_max would proably be 256.

The '128' here could probably be better adjusted to center the player better. The actual value you should probably use would be:

(256 - player_width) / 2


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 5:37 am 
Offline
User avatar

Joined: Tue Jan 17, 2006 10:39 am
Posts: 143
Location: North Carolina
Disch wrote:

Code:
X_scroll = X_player - 128;
if(X_scroll < X_min)
  X_scroll = X_min;
if(X_scroll > X_max)
  X_scroll = X_max;

Sprite_X = X_Player - X_scroll;

// ditto for Y



Hi Disch!

Thanks for your response. This maybe a dumb question but what exactly is your Sprite_X for? The position of the sprite tile on the screen? (X value)


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 5:40 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11010
Location: Rio de Janeiro - Brazil
The position of the player's sprite(s). I do not mean to butt in, but that's basically what I told you... =)

I guess Disch can explain it more directly, though...! =)


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 6:07 am 
Offline
User avatar

Joined: Tue Jan 17, 2006 10:39 am
Posts: 143
Location: North Carolina
tokumaru wrote:
The position of the player's sprite(s). I do not mean to butt in, but that's basically what I told you... =)

I guess Disch can explain it more directly, though...! =)


Yep, you're right. I believed you the whole time, just wanted to see what others were doing :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 6:14 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11010
Location: Rio de Janeiro - Brazil
I'm kidding... You are more than right to ask more than one opinion... they just happend to coincide this time! =)


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 8:48 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7597
Location: Chexbres, VD, Switzerland
I agree with Dish.
Your game engine should be able to totally sparate the position of the player in the level, and the part of the level that is shown on the screen, even if the second varies in function of the first.

_________________
Life is complex: it has both real and imaginary components.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 10:25 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11010
Location: Rio de Janeiro - Brazil
I like to have scrolling totally separated from player movement. The physics has priority, meaning the game is technically playable, even if nothing is displayed on the screen.

Then, when the graphics routines are added they have to "watch" the player, to implement scrolling and proper rendering.

Of course I don't actually do it like this, it would be really boring to implement the physics with no display at all, but the concep is still the same in the end: the physics engine is completely independent from rendering, and the camera (scrolling position) acts based on player's movement, wich it constantly watches.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 11:02 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11010
Location: Rio de Janeiro - Brazil
Guys, maybe you can tell me what you think about this.

While talking to lynxsolaris, it was decided that he would use the following method for scrolling the levels:
-the level map is stored in the form of consecutive columns, for easier rendering;
-whenever the "camera" completes 16 pixels of movement (the size of a metatile), a new column of metatiles is to be rendered;
-if the camera was moving left, the index of the column to render is X_scroll/CameraX/whatever divided by 16;
-if the camera was moving right, the index is X_scroll divided by 16 + 16;
-the destination address of the column in the name tables is also defined by these values, where the 5th bit defines the name table and the other 4 define the column;

Now, if he was to use a formula (such as the one Disch suggested) for the location of the camera, that would mean the scroll is not directly manipulated, but is calculated from another value. What would you say is the best method to detect when the 16 pixels have gone by? Keeping a copy of the old X_scroll and comparing it to the new one? The bits after the first 4 would be the interesting ones to compare, as depending on wich (old or new) is greater we know if the camera moved left or right. I they are equal, there is no need to draw a new column.

I'd do something like this. What do you think?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 6:28 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20848
Location: NE Indiana, USA (NTSC)
tokumaru wrote:
What would you say is the best method to detect when the 16 pixels have gone by? Keeping a copy of the old X_scroll and comparing it to the new one? The bits after the first 4 would be the interesting ones to compare, as depending on wich (old or new) is greater we know if the camera moved left or right.

Easy enough:
Code:
  lda oldXScroll
  eor newXScroll
  and #%11110000
  beq @notChanged
  jsr updateMetaTile
@notChanged:


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 7:29 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11010
Location: Rio de Janeiro - Brazil
But you also gotta check if the column to update is at the left or at the right. For that you'll have to check wich value (old or new) is bigger. So maybe it'd be better to make a direct comparison?

I guess this could work:
Code:
   lda newX
   and #$F0
   pha
   cmp oldX
   beq NoUpdate
   ;set up column index
   bcc UpdateLeft      ;skip addition if updating the leftmost column
   ;add 16 to the column index
UpdateLeft:
   ;render the column to a buffer
NoUpdate:
   pla
   sta oldX
   ;go on with logic

That was so so so quickly written... it may have errors...


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 11, 2006 11:03 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11010
Location: Rio de Janeiro - Brazil
And what about scrooling like in Sonic games? The camera is not "attached" to the player, it tries to follow the player, but it moves on it's own. I played Sonic for years, but until this day I can not properly describe the behaviour of that camera. Wich means I'd probably have trouble implementing it in case I wished to.

I really like the camera in Sonic. It tries to give you the best view of the surroundings, without beeing one of those annoying cameras that try to predict your actions. Like when you are facing left and right when you turn right the camera moves a lot to the right to show what's in front of you. That's a bit annoying.

I never played paying much attention to that, though. Maybe if I spend some time with the game and keep the camera in mind, I might figure something out.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 11, 2006 2:18 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20848
Location: NE Indiana, USA (NTSC)
tokumaru wrote:
Like when you are facing left and right when you turn right the camera moves a lot to the right to show what's in front of you. That's a bit annoying.

It's also annoying in real life. Turn your head by 180 or even 90 degrees and you get a completely different scene.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 11, 2006 2:58 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Quote:
It's also annoying in real life. Turn your head by 180 or even 90 degrees and you get a completely different scene.


But in real life we're given separate controls over camera (head) and movement (legs). Think of the Torchlight Trouble level in Donkey Kong Country, where Squawks carries the lamp and switches which side of the screen is illuminated every time you change direction, complete with a bright flash as the lamp shines directly at the player during each switch. Playing that level requires minimization of direction changes, perhaps an intentional challenge from the designers.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 11, 2006 3:31 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
tokumaru wrote:
And what about scrooling like in Sonic games? The camera is not "attached" to the player


Sonic scrolling style is what I call "slack" scrolling. It doesn't make the camera rigid to Sonic, rather, it keeps Sonic within a designated rectangle on the screen. When Sonic leaves that rectangle, the screen scrolls in the appropriate direction to keep him in the rectangle. This actually works out to be a little worse than "attached" or "rigid" scrolling (the method I previously described) in some situation, but better in others.

Although the Sonic engine is tricky in that it allows Sonic to actually leave the rectangle if he's going too fast for the drawing to keep up. Rather than doing what's intuitive and just slowing Sonic (and the whole game) down until the drawing can keep up.



Sonic in paticular gives lots of vertical slack (Sonic can get high on the screen, or low on the screen before the screen will actually start scrolling), but doesn't give much horizontal slack (Sonic is stuck pretty close to center at all times). This works well for flat areas, so that when you jump, the ground you're trying to jump to is less likely to scroll off the bottom of the screen. However it ends up being worse for falling long distances or moving upwards long distances since you're very close to the screen edge in both cases.

Some NES games have slack scrolling with lots of Horizontal slack which is just AWFUL. Wai Wai World comes to mind -- you have to get right up to the edge of the screen before it starts scrolling -- making it very difficult to see what you're walking into. I think Goonies 2 has a little more horizontal slack than I'd like, too... but it's not nearly as bad.


Accomplishing slack scrolling is a bit more complex than rigid scrolling. To give the idea (this could probably be improved/optimized a lot, especially with use of constants):

Code:
draw_x = player_x - scroll_x;
if(draw_x < (centerscreen_x - x_slack))
  scroll_x = player_x - (centerscreen_x - x_slack);
else if(draw_x > (centerscreen_x + x_slack))
  scroll_x = player_x - (centerscreen_x + x_slack);

if(scroll_x < x_min) scroll_x = x_min;
if(scroll_x > x_max) scroll_x = x_max;

//ditto for y



I usually stick to rigid scrolling because it's easier. Though really, I prefer a sort of "preemptive" scrolling. Much like the type of scrolling tokumaru didn't like -- except the way I'd impliment it is that it would only scroll left when you MOVE left (rather than just face left). So that when you're moving left, the screen gradually scrolls so that your player gets closer to the right-hand side, showing more of what's to your left.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 27 posts ]  Go to page 1, 2  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