Problem setting up split-screen play

Following the code posted here on the forums, I am setting up a split screen mode in my game like this:

base.camNode.setActive(0)
base.makeCamera(base.win, displayRegion=(0,.5,0,1))
base.makeCamera(base.win, displayRegion=(.5,1,0,1))

I then add two player models and upgrade the two cams in a task like this:

for i in (1,2):
	base.camList[i].setPos(self.ships[i].model.getX(), self.ships[i].model.getY()-6, 16)
	base.camList[i].lookAt(self.ships[i].model)

So far, so non-controversial. The thing is that both cameras seem to follow the ships, i.e. the lookAt commands seem to work. But the cams seem to stay in the same place, instead of following the models. The result looks like a surveillance camera, or rather two of them. I don’t see any error messages, so the cameras must follow something?!

My gut feeling is that the default camera is still active. I tried to understand what the attributes: base.camNode, base.camList, base.camera and base.cam mean in ShowBase, but so far I only understand that the camList is a list of all cameras. Adding the two additional cameras extends the camList to three elements, which feels weird to me. I guess camNode, cam or camera refer to the default cam, which I have de-activated (I guess). Do I have to delete these attributes explicitely and re-create them for my additional cams?

What am I missing?

First of all, have you had this working with only a single window, using the same means of getting the ship position? If not, my suspicion is that the problem lies not with the camera, but with how you’re going about placing them.

Specifically, what are the entries in the “self.ships” list, and to what is each “self.ships[i].model” parented? I think that if the ships are at the origin of their parent node - if, for example, each ship has a “manipulator” NodePath to which the “model” NodePath is parented at the origin - then your calls to “self.ships[i].model.get<X, etc.>()” will return 0, leaving your cameras in place.

If you want to test this hypothesis, simply print the result of “self.ships[0].model.getPos()” - if I’m correct, then the result should be at or near (0, 0, 0), on the x- and y- axes, at least.

If I am correct, then I see two options:

  1. Get the position of the model relative to render, perhaps like so:
pos = self.ships[i].model.getPos(render)
pos.setY(pos.y-6)
pos.setZ(16)
base.camList[i].setPos(pos)
  1. set the camera’s position relative to the model, perhaps like so:
base.camList[i].setPos(self.ships[i].model, 0, -6, 16)

I don’t think that’s the problem. The code I posted here is only the split screen variant, using custom-made cameras. In non-split-screen mode I am using the default setup with no problems:

base.camera.setPos(self.ships[1].model.getX(), self.ships[1].model.getY()-6, 16)
base.camera.lookAt(self.ships[1].model)

Doing something like

base.camera.setPos(self.ships[i].model, (0,-6,16))

would not yield the look that I desire for my game. As you can see from videos I posted in the past, the cam does move with the ship, but does not pick up it’s rotation.

I’m pretty sure that I just need a handle to the camera node. Note that base.camList[i].lookAt(node) works! Just not .setPos(), though David does exactly that here. The print of base.camList is:

[render/camera/cam, render/camera/custom_cam1, render/camera/custom_cam2]

Stuff like camList[i].node(), .getChild(0) or .getChild(1) sadly do not provide such handle an just crash.

Yeah, got it, using this for the setup:

base.camNode.setActive(0)

render.attachNewNode(ModelNode("camera1"))
cam1 = base.makeCamera(base.win, displayRegion=(0,.5,0,1), camName="custom_cam1", scene=render)
cam1.reparentTo(render.find("camera1"))

render.attachNewNode(ModelNode("camera2"))
cam2 = base.makeCamera(base.win, displayRegion=(.5,1,0,1), camName="custom_cam2", clearDepth=1)
cam2.reparentTo(render.find("camera2"))

mylens = PerspectiveLens()
mylens.clear()
mylens.setFov(55)
mylens.setAspectRatio(0.8)
base.camList[1].node().setLens(mylens)
base.camList[2].node().setLens(mylens)

and this for the update task:

for i in (1,2):
	base.camList[i].getParent().setPos(self.ships[i].model.getX(), self.ships[i].model.getY()-6, 16)
	base.camList[i].getParent().lookAt(self.ships[i].model)

Now I got a new problem. Using the base.cam standard camera the background graphic is fine, using my two custom cams however you can fly in and out of the background model. I am using the same code however for said background in both cases:

background = loader.loadModel("../gfx/geometry/invertedsphere/invertedsphere")
	background.reparentTo(camera)
	background.setScale(5) # persp vs ortho lens
	background.setHpr(0,0,0)
	background.setBin("background", 10)
	background.setDepthWrite(False)
	background.setDepthTest(False)

where “invertedsphere” is a sphere model with normals pointing inwards. With just one cam it looks like in my videos. With my two custom cams it looks like:

Guess I have to load two background graphics and reparent them to the two cameras, flagging them out for each other?

That’s what I’d do.