How was this done?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
lillapojkenpåön
Posts: 30
Joined: Sat Jul 04, 2020 5:27 pm

How was this done?

Post by lillapojkenpåön »

I recently saw a video that featured a cool looking NES game called Kingdom Crisis, it had a nice smooth camera, the kind you usually use linear interpolation to achieve, and I found an 8-bit lerp funcrion on SO
(A*(256-X)+B*X) /256

I tried to implement it in a game, but unlike the modern platforms that I've used lerp/floating point with before, this one doesn't seem to change speed based on the distance, am I suppose to change X based on the distance between center of camera and playerX?

Another difference is that on those modern platforms playerX just keeps increasing, on a 8-bit system you would need to scroll playerX back so it doesn't roll over, Ive tried alot of things but I can't get the camera to change speed and catch up to the player, does anyone have any experience with implementing smooth camera on a 8-bit system?
User avatar
Controllerhead
Posts: 314
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: How was this done?

Post by Controllerhead »

Yes, you can use another byte for X and Y camera values for 256 subpixels, and the math is super quick; even a nibble of 16 subpixels can smooth it out decently, but you'll have to do some shifting every frame. Floating point is very slow.
Image
lillapojkenpåön
Posts: 30
Joined: Sat Jul 04, 2020 5:27 pm

Re: How was this done?

Post by lillapojkenpåön »

Ok, I'm using 16 bits now, should I include playerX fraction in the calculation too? Do I need to change something else because I just have a glitchfest deluxe, I fell thru the floor..
Here's what it looks like now

Code: Select all

temp1 = (#cameraX / 256)    'remember camera pos int
#cameraX = (#cameraX*(256-128)+#playerX*128) /256    'lerp between camera/player
scrollX = temp1 - (#cameraX / 256)    'get difference between old/new pos
fineScrollX = fineScrollX + scrollX    'scroll that distance, max 8
#playerX = #playerX + scrollX * 256    'scroll player too

and I init cameraX to 88 before that
#cameraX = 88 * 256
User avatar
Controllerhead
Posts: 314
Joined: Tue Nov 13, 2018 4:58 am
Location: $4016
Contact:

Re: How was this done?

Post by Controllerhead »

I mean, i don't know what the rest of your code looks like, so i couldn't say why you're having issues exactly; ...however i do see some #immediate values in #cameraX and #playerX that my gut tells me might not be correct...

Having two bytes as a "camera" position allows you to have a smooth scrolling camera, but it's up to you to implement it based on the rest of your code. You could have camera X/Y acceleration values and nudge them towards player position, for example...
Image
lillapojkenpåön
Posts: 30
Joined: Sat Jul 04, 2020 5:27 pm

Re: How was this done?

Post by lillapojkenpåön »

Controllerhead wrote: Sat May 20, 2023 6:36 pm I mean, i don't know what the rest of your code looks like, so i couldn't say why you're having issues exactly; ...however i do see some #immediate values in #cameraX and #playerX that my gut tells me might not be correct...
Yeah I caught that right after posting.
Controllerhead wrote: Sat May 20, 2023 6:36 pm Having two bytes as a "camera" position allows you to have a smooth scrolling camera, but it's up to you to implement it based on the rest of your code. You could have camera X/Y acceleration values and nudge them towards player position, for example...
I allready had that before, I'm after a specific ramp up/ramp down camera using lerping.
lillapojkenpåön
Posts: 30
Joined: Sat Jul 04, 2020 5:27 pm

Re: How was this done?

Post by lillapojkenpåön »

Nevermind, it was alot easier than I thought
User avatar
wonder
Posts: 59
Joined: Sat Aug 31, 2019 2:12 pm
Contact:

Re: How was this done?

Post by wonder »

lillapojkenpåön wrote: Sat May 20, 2023 4:30 pm I recently saw a video that featured a cool looking NES game called Kingdom Crisis, it had a nice smooth camera, the kind you usually use linear interpolation to achieve, and I found an 8-bit lerp funcrion on SO
(A*(256-X)+B*X) /256

I tried to implement it in a game, but unlike the modern platforms that I've used lerp/floating point with before, this one doesn't seem to change speed based on the distance, am I suppose to change X based on the distance between center of camera and playerX?

Another difference is that on those modern platforms playerX just keeps increasing, on a 8-bit system you would need to scroll playerX back so it doesn't roll over, Ive tried alot of things but I can't get the camera to change speed and catch up to the player, does anyone have any experience with implementing smooth camera on a 8-bit system?
Hi there! Kingdom Crisis dev here! :D

Glad to know that you found a solution, there are indeed many ways of achieving this effect.
My camera code is a little bit messy due to optimization, but here's the relevant part:

Code: Select all

  // Move the camera if it's off target
  diff_x = (camera.target_x - camera.x) - HALF_SCREEN;
  if (!diff_x) { camera.vx = 0; return; }

  // Pre-calc the direction
  zp_SIGNED = sign_of(diff_x);
  zp_TMP = ABS(diff_x);

  // Update the camera velocity (smooth camera)
  if      (zp_TMP <  2) camera.vx = zp_SIGNED * (!(frame % 13));
  else if (zp_TMP <  3) camera.vx = zp_SIGNED * (!(frame %  8));
  else if (zp_TMP <  5) camera.vx = zp_SIGNED * (!(frame %  5));
  else if (zp_TMP <  8) camera.vx = zp_SIGNED * (!(frame %  3));
  else if (zp_TMP < 13) camera.vx = zp_SIGNED * (!(frame %  2));
  else camera.vx = zp_SIGNED;

  // Move the camera (follow the player sprite)
  camera.x += camera.vx;
  CLAMP(int, camera.x, CAM_MIN_X, CAM_MAX_X);
  camera.ox = camera.x + HALF_SCREEN;
Image
Post Reply