I suspect you are running into the Geom limit. Each independently-transformable object has to be sent to the graphics card as a separate Geom, but there is a severe limit to the number of individual Geoms you can have.
I’m actually a little surprised you’re running into this limit after adding only thirty cards or so, but it’s possible, I guess, depending on the rest of your scene. (A typical rule of thumb is you should aim for 300-600 Geoms in the entire scene.) It also depends on the frame rates you’re talking about: speaking of a 20 fps cost isn’t actually a qualitative measurement, because the difference between 150 fps and 170 fps (0.78 ms) is waaaay different than the difference between 20 fps and 40 fps (25 ms). For performance measurements, it’s usually best to speak in terms of milliseconds, which are in the same scale no matter what the frame rate.
If you’re up in the 60+ fps range, every little tenth of a millisecond cost will make a big difference in your measured frame rate, so be careful you don’t get too obsessed about over-optimizing too early. On the other hand, keeping things up in the 60+ fps range is a challenge, because there’s not a lot of elbow room up there; so if your goal is to produce a product that remains 60+ fps throughout, then it will be important to pay close attention to every millisecond.
As to the problem at hand, you have hit upon the fundamental conflict between game designers (who want lots of independently-controllable objects) and hardware manufacturers (who want everything to be one big static object). There are a few tricks you can use to help, but they mostly involve a compromise of one form or another.
First, I’d try putting all of your cards under one node, and calling flattenStrong() on that node. This should convert the collection of cards into a single Geom (assuming they all have the same texture and render state). It will also remove your ability to control them independently, of course, but the idea is to see just how much you’re paying for the convenience of independent Geoms.
If that makes a big difference in performance, then you have to figure out how to get the controllability back. One easy thing to try is to put them all under a RigidBodyCombiner, which will manage the vertices on the CPU and send a single Geom to the graphics card. This can end up being a tradeoff between CPU and GPU, so whether it comes out as a win for you depends heavily on what your CPU and GPU burdens already are (and this might change as you continue to develop your application).
If the RigidBodyCombiner isn’t a win, you might need to do something more elaborate, such as using a particle system or the MeshDrawer class, depending on your precise needs; or if the cards move only infrequently, you can keep a flattened version of the cards in the scene, and a non-flattened version offstage; and when you need to move a card you can duplicate and flatten it into the scene.
David