Create a battleback for the 3D camera
This guide explains how to build a battleback for PSDK's dynamic 3D battle camera: a Ruby class that stacks sprite layers, animates them, and is selected by the battle's background name.
This is an advanced guide. You should already be comfortable adding a custom script to your project and writing a small Ruby class. It builds on the idea of a regular 2D battleback, which is just an image.
Enabling the 3D camera
The dynamic 3D battle camera is a project setting, off by default. It is exposed in code as Battle::BATTLE_CAMERA_3D, which reads Configs.settings.is_use_battle_camera_3d (the isUseBattleCamera3d key in Data/configs/settings_config.json). Turn it on in your project settings.
With it on, the battle uses Battle::Visual3D instead of the flat Battle::Visual.
How a 3D battleback works
Without the 3D camera, a battleback is a single flat image. With it on, the battle is a 3D scene the camera pans and tilts through, so one flat image no longer works: the background is rebuilt as a stack of sprite layers, the sky far back, the ground in the middle, the trees up front, and the camera moves through them to create depth.
Each battleback is therefore a small Ruby class, a subclass of BattleUI::Battleback3D, that does up to three things:
- declares where its images live, through
resource_path, - stacks its sprite layers, in
create_graphicswithadd_battleback_element, - and, optionally, animates them in
create_animations.
The engine ships one example to study, BattleUI::BattleBackGrass, in 5 Battle/01 Scene/0 BattleUI/700 BattleBackForest3D.rb. This guide builds up to the same shape, one step at a time.
Placing the resources
Put your images under your project's graphics/battlebacks/ folder. Keep one subfolder per battleback, here graphics/battlebacks/animated_camera/BattleBack Forest/. That stays manageable once a project has dozens of them.
A minimal battleback
Start with the smallest possible battleback: a single full-screen layer. Subclass Battleback3D, point resource_path at your subfolder (relative to graphics/battlebacks/), and add one element in create_graphics:
module BattleUI
class BattleBackForest < Battleback3D
def resource_path
'animated_camera/BattleBack Forest/'
end
def create_graphics
@field = add_battleback_element(@path, 'field')
end
end
end
add_battleback_element(@path, 'field') loads field.png from your folder as a full-screen layer. You never call create_graphics yourself: the base class runs it when the battleback is created. (If your battleback needs the battle scene, store it with @scene = scene in your own initialize that calls super; the base class does not keep it.)
This class exists but no battle uses it yet. The next step wires it in.
Showing it in a battle
A 3D battleback is chosen by Battle::Visual3D#create_background, from the battle's background_name. By default the 3D camera uses the built-in grass background for every battle, so to show yours, prepend create_background and return your class for the name you want, falling back to the default with super:
module Battle
class Visual3D
module ForestBackground
def create_background
if background_name == 'back_grass' # the name your battleback answers to
@background = BattleUI::BattleBackForest.new(viewport, @scene)
else
super
end
end
end
prepend ForestBackground
end
end
Start a battle on grass and your single-layer battleback appears. From here, you add depth and motion to the same class.
Adding layers
A convincing battleback stacks several layers. Add them in create_graphics, back to front: each new element sits in front of the previous one. Store each sprite in an instance variable so you can animate it later:
def create_graphics
@field = add_battleback_element(@path, 'field')
@ground = add_battleback_element(@path, 'ground')
@sky = add_battleback_element(@path, 'sky')
@cloud1 = add_battleback_element(@path, 'cloud1')
@cloud2 = add_battleback_element(@path, 'cloud2')
@trees1 = add_battleback_element(@path, 'trees1')
@trees2 = add_battleback_element(@path, 'trees2')
end
add_battleback_element(path, name, x, y, z, zoom) takes:
path: the folder, normally@path(yourresource_path).name: the image filename, without extension.x,y: the position, measured from the center of the visible area. They default to a centered full-screen layer, which is what most layers want.z: how far back the layer sits.1is full scale, a higher value pushes it further away and smaller, and0is not allowed.zoom: the scale, used to compensate forz.
Only path and name are required; the rest have sensible defaults.
Animating the layers
To make a layer move, such as drifting clouds, override create_animations. Call super first, push Yuki::Animation players into @animations, and start them. The battleback updates @animations on its own every frame, so you do not wire the update loop yourself:
def create_animations
super
start_x = -(Graphics.width / 2 + MARGIN_X)
@animations << create_animation_cloud(@cloud1, start_x, Graphics.width / 2 + MARGIN_X, 60)
@animations << create_animation_cloud(@cloud2, start_x, 2 * start_x, 60)
@animations.each(&:start)
end
create_animation_cloud here is a small helper that builds a looping move animation for one sprite; the shipped BattleBackGrass contains its full code. Building the animations themselves belongs to PSDK's animation system, a topic of its own. What matters for the battleback is the contract above: create and start the animations in create_animations, keep them in @animations, and the class drives them.
Choosing a background name
background_name is resolved from the battle: the explicit battleback set on the map (the RPG Maker XP "Change Battle Back" command, or a BattleInfo), otherwise the map's zone type. The names PSDK knows by default are listed in Battle::Logic::BattleInfo::BACKGROUND_NAMES:
back_building(the default when nothing else matches)back_grass,back_tall_grass,back_taller_grassback_cave,back_mount,back_sandback_pond,back_sea,back_under_waterback_ice,back_snow
For a one-off battleback, such as a specific trainer or a legendary encounter, set a custom battleback image with the "Change Battle Back" command before the battle, then match its name in create_background. The name is the image filename without its extension: choosing battleback legendary arceus.png makes background_name equal to 'battleback legendary arceus'.
Day and night, and limitations
add_battleback_elementswaps an image for a time-of-day variant when one exists. With the day and night system active, it looks for a_morning,_day,_sunsetor_nightsuffix on the image name and uses that file if it is present, otherwise the plain image. So shippingfield_night.pngnext tofield.pngis enough to get a night version..gifbattlebacks are not handled under the 3D camera. Animated gifs only work with the flat 2D visual; under the 3D camera, animate sprites throughcreate_animationsinstead.
Conclusion
- Enable the 3D camera with the
is_use_battle_camera_3dproject setting; battlebacks then become Ruby classes. - Start minimal: subclass
BattleUI::Battleback3D, setresource_path, add one layer increate_graphics, and register it by prependingBattle::Visual3D#create_background. - Add depth by stacking more layers with
add_battleback_element, back to front. - Add motion in
create_animations(callsuper, fill@animations, start them); the class updates them each frame. - Study the shipped
BattleBackGrass(700 BattleBackForest3D.rb) as the reference implementation.