-
Notifications
You must be signed in to change notification settings - Fork 161
Puppy Camera 2
Puppy Camera 2 is a fully custom camera written from the ground up to provide an alternative to SM64's standard camera system. Common attributes that you'd expect in more modern games can be freely customised in game by the player. Furthermore, developers are able to work with more advanced aspects of the camera easier than any other, using integrated systems to create custom camera angles and entirely new cutscenes.
Setup
Custom Angles
Behaviour Flags
Cutscenes
Puppy Camera 2 by default is disabled in the repo. You can enable it by going into /include/config/config_camera.h
in your repo and then looking for the line where it says // #define PUPPYCAM
. Uncomment this line and Puppy Camera 2 is now enabled. It will function over the default camera, however, vanilla cutscenes will override Puppy Camera 2 for the duration of them.
Big Boo's Haunt is a level that's comprised of a lot of custom camera angles to enhance the view. You've probably played a romhack where you're inside an enclosed indoor area and it's quite difficult to see because of how cramped it is, this is where you'd use something like this to help the player to see what they're doing.
Puppy Camera 2 comes with its own system for this, that provides a lot of useful functionality for basic users, and headroom for advanced users, without having to create a spaghetti-mess of code to make it function.
If you use visual debug, camera volumes will show up in yellow, so you can see their visuals.
Written below is an example of a camera angle node.
PUPPYVOLUME(/*X*/ 0,/*Y*/ 0,/*Z*/ 0,/*Width*/ 1000,/*Height*/ 2000,/*Depth*/ 1000,/*Yaw*/ 0,/*Function*/ &exampleFunc,/*Angles*/ &exampleAngles,/*Add Flags*/ 0,/*Remove Flags*/ 0,/*Flag Persistance*/ PUPPYCAM_BEHAVIOUR_TEMPORARY,/*Room*/ -1,/*Shape*/ PUPPYVOLUME_SHAPE_BOX,/*FoV*/ 60),
Here's a list of what each parameter means.
- X, Y, Z
The first three parameters are where the node is in the world. The size and position is all based on the centre, so you want to place this at the very middle of where you want your trigger to be. - Width, Height, Depth
The next three control the size of the node. Since the position is the middle, that means the size protrudes from each side. For example, if your Width is 1000, then that means it will be 500 units out from either side of wherever your X coordinate is. - Yaw
Yaw is the Y axis direction. Simply put, it's which way it is facing while the right way up. If you have a fully cylindrical trigger, you can leave this at zero, but a rectangular or oval shaped triggers can rotate with this yaw to orient themselves correctly, if you have a trigger you want to line up with something that might not otherwise fit. - Function
You can attach a function to this and it will execute for every frame you are inside the trigger. Since you do not pass any arguments to the function, then the type you use isvoid
. You must also make sure the function name you reference is preceded with an ampersand (&), like shown above.
If you do not wish to use a function, you simply fill that space withNULL
- Angles
Since you don't always want to use angles with camera nodes, it's relegated to a separate data structure.
Written below is an example of an angles struct.
struct sPuppyAngles testAngles = {/*Position*/{/*X*/ 500,/*Y*/ 2000,/*Z*/ 500},/*Focus*/{/*X*/ PUPPY_NULL,/*Y*/ PUPPY_NULL,/*Z*/ PUPPY_NULL},/*Yaw*/ PUPPY_NULL,/*Pitch*/ PUPPY_NULL,/*Zoom*/ PUPPY_NULL, };
Essentially, each of these values will override the cameras own values for the time you're inside this trigger. If you want a field to be ignored completely, you putPUPPY_NULL
inside, that way, the game will use its current values. So this current view will put the camera's position to these set coordinates, then keep the view on Mario, without messing with any more values. - Add Flags, Remove Flags, Flag Persistance
You can see the Behaviour Flags section below to learn more about what each one does.
"Add Flags" refers to enabling these behaviours when you are inside this trigger, while "Remove Flags" takes them away. Flag Persistence decides whether or not this trigger adding or removing flags is permanent, or just for the duration of you being inside the trigger. The two available options arePUPPYCAM_BEHAVIOUR_TEMPORARY
andPUPPYCAM_BEHAVIOUR_PERMANENT
. - Room
If you're using the rooms system, then you can assign a room to your trigger, that way, you can't accidentally trigger it while you're not in the intended room. If you want it to be triggered in all rooms, or if you're not using the rooms system at all, you can use-1
- Shape
Here you can decide the shape of your trigger. Your two options arePUPPYVOLUME_SHAPE_BOX
andPUPPYVOLUME_SHAPE_CYLINDER
. This more or less decides whether you want your trigger to be round or not. - FoV (NYI)
Current not implemented, but in the future, will allow you to override the field of view while inside the trigger. Usually, it's set to 45. When you're in tight spaces, you generally want to increase it, as it will allow you a larger radius of vision, while not making the camera have to go any further away, risking unwanted camera collision.
Puppy Camera 2's base functionality relies on these flags to know what it can and can't do. You can freely add or take them away as needed.
The camera has two values it uses for ease of use when handling behaviours. intendedFlags
and flags
. intendedFlags
will set the flags
at the beginning of every frame, meaning it will restore any modification that happens afterwards, this way you can mess with it freely, while reversing the effect is effortless. If you wish for whatever modifications you make to stick, then you change intendedFlags
instead.
-
PUPPYCAM_BEHAVIOUR_X_MOVEMENT
,PUPPYCAM_BEHAVIOUR_Y_MOVEMENT
,PUPPYCAM_BEHAVIOUR_Z_MOVEMENT
Allows the camera to update the position on the respective axis. -
PUPPYCAM_BEHAVIOUR_YAW_ROTATION
,PUPPYCAM_BEHAVIOUR_PITCH_ROTATION
,PUPPYCAM_BEHAVIOUR_ZOOM_CHANGE
Allows the camera to alter its yaw, which is its horizontal facing direction, its pitch, which is the vertical face direction, and the zoom, which is how far away the camera will be from its target position. -
PUPPYCAM_BEHAVIOUR_INPUT_NORMAL
This is the default setting when you enter a level. The camera controls will have standard functionality, which you can change in the options menu to tweak how you like. -
PUPPYCAM_BEHAVIOUR_INPUT_8DIR
If you have a level where it's important the camera remains axis aligned, like SM64's bowser stages, you'll want to set this. The horizontal movement will be overridden with 8 directional camera controls. -
PUPPYCAM_BEHAVIOUR_INPUT_4DIR
Same thing, but instead of being 8 direction locked, you're now locked to the 4 cardinal directions. -
PUPPYCAM_BEHAVIOUR_TURN_HELPER
This option enables Auto Rotation to function. By default, it's enabled, but if you really don't want autorotation, then remove this. -
PUPPYCAM_BEHAVIOUR_HEIGHT_HELPER
This option being enabled allows the camera to automatically alter its pitch based on the steepness of any inclines you are stood on. -
PUPPYCAM_BEHAVIOUR_PANSHIFT
The camera shifts outwards from wherever you're facing by default, to give more screen estate to your current facing direction. Remove this flag to disable this effect. -
PUPPYCAM_BEHAVIOUR_COLLISION
If you dislike the camera colliding with the geometry, you can completely disable it here. -
PUPPYCAM_BEHAVIOUR_FREE
This is a debug behaviour, that gives the camera free control. You can press B to toggle Mario's controls or the cameras controls, press A with the cameras controls to teleport Mario to the camera, and press L with Mario's controls to lock the camera's look position. You can enable this flag in Puppy Print Debugging's menu. It's very useful for helping to figure out where you may want to place the camera for custom views and cutscenes.
Cutscenes can give your game that cinematic feel, help explain things in between gameplay segments, or just point the player to where they need to go next. Puppy Camera 2 has its own cutscene system that tries to improve on the flaws with SM64's own system, to improve usability and code cleanliness.
Puppy Camera 2 cutscenes work by calling a function, which has another function as an argument. It will run that function until it returns a nonzero value, where it will then stop the cutscene, and return to normal play.
That function is puppycam_activate_cutscene
. The first argument is the function in which you contain your cutscene. The second argument is whether or not you want to lock Mario's inputs while this cutscene is playing. Almost always you'll want this set to TRUE
.
s32 example_scene(void) { if (gPuppyCam.sceneTimer == 30) { return TRUE; } else { return FALSE; } }
Written above is an example scene function. Puppy Camera 2, when a cutscene is running, sceneTimer
will increment. You can use this in whichever way you like. This example function will end the cutscene after it counts to 30, which translates to one second. You have more or less free control of what you can do inside these functions.
Puppy Camera 2 also comes with a system to easily integrate splines. You can use puppycam_move_spline
to make it follow a path. You simply keep calling this function, passing through the splines you want, and when it reaches the end, it will return true. The first argument is the base spline you can make it follow, with the second, optional one, being one you can make the camera look at while following the first one. The third argument decides whether to write to the focus value, if you set PUPPYSPLINE_FOLLOW
, rather than PUPPYSPLINE_NONE
. The last argument will be the first spline index it uses. Most of the time you'll set this to zero, since it will be the first one.
The spline data itself is more or less identical to Vanilla splines. If you're familiar with how b-splines work, then these are just the same. You can export splines in fast64 that will work. Vanilla splines (CutsceneSplinePoint
) can also be passed through, since they use the same data.