Guest User

PixelPerfectCamera.cs

a guest
Apr 13th, 2025
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.56 KB | Source Code | 0 0
  1. using Godot;
  2. using Godot.Collections;
  3. using System;
  4.  
  5. public enum ScrollType { SCROLL, AUTO_SCROLL }
  6.  
  7. public enum LimitDir { LEFT = 0, RIGHT = 1, UP = 2, DOWN = 3 }
  8.  
  9. public partial class Camera : Node2D
  10. {
  11.     private ScrollType _type;
  12.  
  13.     [Export]
  14.     public ScrollType Type
  15.     {
  16.         get => _type;
  17.  
  18.         set
  19.         {
  20.             _type = value;
  21.             NotifyPropertyListChanged();
  22.         }
  23.     }
  24.  
  25.     private Viewport _cameraView;
  26.     private Area2D _staticRegion;
  27.     // Not pixel perfect
  28.     private Vector2 _zoom;
  29.     private Vector2I _viewportSize;
  30.     private Vector2I _halfViewport;
  31.  
  32.     private int[] Limits = new int[4];
  33.  
  34.     private Area2D _focusArea;
  35.     private Area2D _deathFrame; // Camera went too fast and player ded!
  36.  
  37.     // AUTO SCROLL PROPERTIES:
  38.     private float _maxAutoScrollSpeed = 900; // Just a random arbitrary value, there's no rhyme or reason outside of it's a nice divisible by 3 number
  39.     private float _autoScrollSpeed = 150;
  40.     private Vector2 _autoScrollDir = Vector2.Right; // We scroll right by default
  41.  
  42.     [Export]
  43.     public float AutoScrollSpeed
  44.     {
  45.         get => _autoScrollSpeed;
  46.         set
  47.         {
  48.             _autoScrollSpeed = value;
  49.         }
  50.     }
  51.  
  52.     [Export]
  53.     public Vector2 AutoScrollDir
  54.     {
  55.         get => _autoScrollDir;
  56.         set
  57.         {
  58.             _autoScrollDir = value;
  59.         }
  60.     }
  61.  
  62.     [Export]
  63.     public Vector2 Zoom
  64.     {
  65.         get
  66.         {
  67.             return _zoom;
  68.         }
  69.         set
  70.         {
  71.             _zoom = SetZoom(value);
  72.         }
  73.     }
  74.  
  75.     // Note, this will be called in Level.CS's loop. We assume this is a type of level that affects it's camera
  76.     // This can be used for timed scrolling, this contains it's own speed because camera could speed up or slow down!
  77.     public void AutoScroll(double delta, Vector2 Direction, float autoScrollSpeed)
  78.     {
  79.         var newOrigin = _cameraView.CanvasTransform;
  80.         newOrigin.Origin = newOrigin.Origin.Lerp(newOrigin.Origin + Direction, (float)delta * autoScrollSpeed);
  81.         _cameraView.CanvasTransform = newOrigin;
  82.     }
  83.  
  84.     public void SmoothZoom(Vector2 offset, double delta, float zoomSpeed) => Zoom = Zoom.Lerp(Zoom + offset, (float)delta * zoomSpeed);
  85.  
  86.     public override void _Ready()
  87.     {
  88.         base._Ready();
  89.  
  90.         ProcessPriority = -1;
  91.  
  92.         _cameraView = GetViewport();
  93.         _viewportSize = (Vector2I)_cameraView.GetVisibleRect().Size.Round();
  94.         _halfViewport = _viewportSize / 2;
  95.     }
  96.  
  97.     public void Snap(Vector2 desiredPosition)
  98.     {
  99.         var newOrigin = _cameraView.CanvasTransform;
  100.         newOrigin.Origin = desiredPosition;
  101.  
  102.         _cameraView.CanvasTransform = newOrigin;
  103.     }
  104.  
  105.     public void SetFocus(Area2D focus)
  106.     {
  107.         _focusArea = focus;
  108.         var transform = Transform2D.Identity;
  109.  
  110.         transform.Origin = -_focusArea.Transform.Origin + (_viewportSize / 2);
  111.         _cameraView.CanvasTransform = transform;
  112.     }
  113.  
  114.     // Sets bounds of scrollable area based on Tilemap size and used rect
  115.     public void SetBounds(TileMapLayer map)
  116.     {
  117.         var bounds = map.GetUsedRect();
  118.         var tileSize = map.TileSet.TileSize;
  119.  
  120.         Limits[(int)LimitDir.LEFT] = bounds.Position.X * tileSize.X - _halfViewport.X;
  121.         Limits[(int)LimitDir.RIGHT] = bounds.End.X * tileSize.X + _halfViewport.X;
  122.         Limits[(int)LimitDir.UP] = bounds.Position.Y * tileSize.Y - _halfViewport.Y; // Y is reversed in 2D. Whyyyyyyyyyyy
  123.         Limits[(int)LimitDir.DOWN] = bounds.End.Y * tileSize.Y + _halfViewport.Y;
  124.     }
  125.  
  126.     public Vector2 SetZoom(Vector2 zoom)
  127.     {
  128.         var newTransform = _cameraView.CanvasTransform;
  129.  
  130.         GD.Print(zoom);
  131.  
  132.         newTransform.X *= zoom.X * 0.5f;
  133.         newTransform.Y *= zoom.Y * 0.5f;
  134.         _cameraView.CanvasTransform = newTransform;
  135.  
  136.         return zoom;
  137.     }
  138.  
  139.     public void Scroll()
  140.     {
  141.         //ToDo: Detect if isScrolling Based on set static area or drag bounds!!
  142.         var newOrigin = _cameraView.CanvasTransform;
  143.  
  144.         // Note that focusArea in this case is an Area2D, could make it a Node2D as well
  145.         Vector2I targetPosition = (Vector2I)_focusArea.GlobalPosition.Round();
  146.  
  147.         newOrigin.Origin = -targetPosition + _halfViewport;
  148.  
  149.         // Limits are tile map limits to keep the camera in bounds
  150.         // Currently having a small issue where the camera can't reach end of level.
  151.         int minX = Limits[(int)LimitDir.LEFT] - _halfViewport.X;
  152.         int maxX = Limits[(int)LimitDir.RIGHT] + _halfViewport.X;
  153.         int minY = Limits[(int)LimitDir.UP] - _halfViewport.Y;
  154.         int maxY = Limits[(int)LimitDir.DOWN] + _halfViewport.Y;
  155.  
  156.         // Clamp Camera to Map Limits / boundaries
  157.         newOrigin.Origin = new Vector2(Math.Clamp((int)newOrigin.Origin.X, minX, maxX), Math.Clamp((int)newOrigin.Origin.Y, minY, maxY));
  158.         _cameraView.CanvasTransform = newOrigin;
  159.     }
  160.  
  161.     // For short camera pan's and transitions
  162.     public void Pan(Vector2 Direction, float panSpeed, double delta, int time) // Not sure if time is needed
  163.     {
  164.         GlobalPosition = GlobalPosition.Lerp(GlobalPosition + Direction, (float)delta * panSpeed);
  165.     }
  166.  
  167.     public override void _Process(double delta)
  168.     {
  169.         base._Process(delta);
  170.  
  171.         switch (_type)
  172.         {
  173.             case ScrollType.SCROLL:
  174.                 Scroll();
  175.                 break;
  176.  
  177.             case ScrollType.AUTO_SCROLL:
  178.                 AutoScroll(delta, _autoScrollDir, _autoScrollSpeed);
  179.                 break;
  180.         }
  181.  
  182.     }
  183. }
  184.  
Advertisement
Add Comment
Please, Sign In to add comment