Camera following two characters simultaneously

Hi guys, I need a little help here please. I need to make a camera following two characters simultaneously in BGE 2.49. Anyone knows how to do this withouth python?
I use logic bricks…
The thing is I´m making a coop game restricted in x and z (not y) And what I need to know is how to make the camera follow the two players until one dies, and then it follows only the remaining player.

Please, I will be very happy if you can help me…Thanks guys!

I don’t quite understand the question. But to make a camera follow objects, select the camera and then select the object and press Ctrl P to parent them. Then switch to the camera view and start camera, it will follow the character(s)

If you meant something else, can you give me more detail?

He meant that he wanted the camera to follow two objects simultaneously, like Super Smash Brothers, Castle Crashers, or any other co-op game where the camera zooms out to fit two (or more) separate characters on the screen at once. I don’t think it’s possible with logic bricks.

With python it would be easy. And I quit bricks for the very reason that things like this are difficult or next to impossible with bricks (for me anyway).

You say it’s restricted “in” x and z. Maybe it’s a 2d or 2.5d platform or side scrolling game. By coop do you mean 2 player objects using AI to assist each other? Or do you mean the game is played by two people each with a gamepad. Or maybe that one person controls the movements of two player objects, WASD for one and arrow keys for the other.

You could try this. At game start you’ve got two player objects and a camera. Your camera could be given a half of whatever movement or velocity is given to each player. It could run off copies of the same sensors attached to the player objects and be given actuators that are set to half the values.

The human player/s might need to manually “zoom” in or out, if player objects look like leaving the screen, by moving the camera along it’s local z-axis. But if it’s coop that could be part of the game to either stick together if a close up view is needed or at times be prepared to zoom out to keep both player objects in shot.

@Equip - That sounds like it might work, but it seems like it would be more efficient to simply get the difference between the two player positions and set the camera to be half-way in between them. Also, for the zooming in and out, you can use the camera object’s getScreenPosition function to see how close to the edge the player objects are, and then zoom out until they are no longer near the edge (and zoom in until they are).

Yo SolarLune. That’s exactly how I’d do it. If a beginner wants do do something like this hopefully it will motivate them to try a few simple scripts.

Yeah. It’s too bad that Python scares a lot of people away - certain game ideas are next to impossible to do without Python, and it helps to make even simple game concepts easy (like moving around with keypresses).

About a year ago when I tried to learn how to use messages, properties, expressions etc in bricks I thought - Nah, forget it… there’s gotta be a better way. Now it’s frustrating sometimes to know how easily something can be done in python yet not know how to do it with bricks alone.

Also there seem to be a lot of noobs that clamour and grab with their grubby little hands for a mouselook script yet they go green and cry for their mamas if you suggest python for anything else.

Yup, the basic idea is to set the position of the camera to the average x and z position of the two players. The y position of the camera, the zoom, is a little bit more tricky. I spent a while trying to determine an exact formula for it and it seems that none exists, so I made a function to approximate it based on the field of view.

The following code is pretty straight forward, all you need to worry about is setting the names of player1 and player2.

import bge
from math import pi, atan

scn = bge.logic.getCurrentScene()

player1 = scn.objects['player 1']
player2 = scn.objects['player 2']
cam = scn.active_camera

fov = 380/180 * atan(16/cam.lens) - 0.2;

def get_cam_y(pos, p1, p2):
    v1 = pos-p1
    v2 = pos-p2
    diff = fov - v1.angle(v2)
    if abs(diff) < 0.05:
        return pos.y
    else:
        pos.y += diff*0.75
        return get_cam_y(pos, p1, p2)

avg_pos = (player1.worldPosition + player2.worldPosition) / 2
cam.worldPosition.x = avg_pos.x
cam.worldPosition.z = avg_pos.z
cam.worldPosition.y = get_cam_y(cam.worldPosition.copy(), player1.worldPosition, player2.worldPosition)

Andrew’s is a good script (if aggemcore is game). It’s a nice tutorial in itself. And cam.lens is good value (I rediscovered that answering a post earlier). This script adjusts field of view and world coords but doesn’t seem to move the camera on it’s local z-axis. The player objects could become so widely separated that fov wouldn’t do or would look too strange. Maybe some allowance should be made that beyond a certain lens value the camera moves out on it’s local z-axis.

Hey, Andrew, isn’t it possible for that script to get stuck in an infinite loop? At the bottom of the get_cam_y function, it calls itself, again. Wouldn’t this continue to happen until Blender froze, since the variables that you’re calling the function with don’t change? Each time it calls itself, it calls itself again, etc.

That’s recursion, it should have a condition whereby the function will break, and pass the value back up the chain of functions, to the first (this can be used instead of recursion (for loops)… enough theory:
I read about the average point stuff (beat me to it :P)
Would it not be better to parent the Camera to an empty, place the empty at the average of the 1+ players and use a scale IPO (old school… :D) to control the zoom, because by scaling the parent of the Camera, as long as you don’t go 0, the FoV of the Camera remain intact, but the camera will be moved closer/futher away… anyways, I’ll post a blend in a minute…

Wow, longest… minute… ever…

here’s the Blend, I tried to implement the character dying (almost got it) but I’ve just given up because it was only supposed to be a bit of help :spin:)

co-opCam.blend (152 KB)

keyboard:
WSAD
NUMPAD Arrows
standard arrows
^all control the three seperate cubes.

The idea is that you can have as many players as you like; as long as you use the naming conventions and change the value of “players” attribute on the camera’s parent… (it’s position is the same as the planes, so you may miss it, but it exists…)

EDIT:It can easily be edited to restrict it to 2d, and I’ll just add the rotation tracking now…

EDIT:
here’s the file with rotation tracking:
co-opCamRot.blend (167 KB)

Great guys! I´ll test your suggestions and tell you how is it going!
Thanksssss!

@Equip; The script doesn’t change the field of view, it moves the camera along the Y axis until the objects fit nicely inside the fov. The script does change the z position of the camera, this is based on the average position of the two players.

@SolarLune; Hacker23 is right, the function will keep calling itself and it may fall into a fairly deep call stack but it shouldn’t get stuck in an infinite loop due to the escape clause (when the difference is less than 0.05 radians) at which point that y value will get pushed back up through the call stack.

Thanks to all and thanks Haker23 for the files!!!

I was just working on a similar camera control. It’s like the one in smash bro’s.

-you need to collect your camera (or what its attached too ex: Cboom) players 1 & 2.
-the distance between them

I use a limit on how close the camera can get. In my case it pans on X and Z and zooms on Y (it stays on the negative axis). It is set at -14 on y-axis. I want it to zoom out when the players are more than 5 units apart.
-some algebra… player distance * x = camera distance
in my case 5 * -2.8 = -14
-so if the distance is greater than 5 do the math otherwise set the camera distance to -14

-the next step is to center the camera where it needs to be so, find the mid point between players for (in my case) x and z

more math: middle = 0.5 * (point1 + point2)

so the camera’s position is: middleX, zoom(Y), middleZ

Works smoothly. Only 20ish lines of code.


scene = GameLogic.getCurrentScene()
objList = scene.objects
cam = objList["OBCboom"]
p1 = objList["OBp1"]
p2 = objList["OBp2"]

#simple zoom
dist = p1.getDistanceTo(p2)
#if distance is greater then 5 zoom-fix
if dist > 5:
    camadj = dist * -2.8
    
else:
    camadj = -14    
    
#find the center
p1pos = p1.worldPosition
p2pos = p2.worldPosition

#get and set center x,y,z
center = 0.5 * (p1pos[0] + p2pos[0]), camadj,0.5 * (p1pos[2] + p2pos[2])
cam.worldPosition = center

Here’s the blend. Arrow keys.

Attachments

smash camera.blend (187 KB)