[Solved] Weird Picture offset in Parallel Projection

Hello!

So I am building a top-down 2d game and right now I have a curious problem with firing arrows.

On a mouseclick, I spawn arrows pretty much like the space shooter tutorial:

Node node = new Node("arrow");
        Picture pic = new Picture("arrow");
        Texture2D tex = (Texture2D) assetManager.loadTexture("Textures/Arrow.png");
        pic.setTexture(assetManager, tex, true);
        node.attachChild(pic);

//        adjust picture
        float width = tex.getImage().getWidth();
        float height = tex.getImage().getHeight();
        pic.setWidth(width);
        pic.setHeight(height);
        pic.move(-width / 2f, -height / 2f, 0);

// set location of the node to my archer's location
node.setLocalTranslation(archer.getWorldTranslation());

So this works fine. When I load up the game, arrows fire from the right location. It’s after I move the guy that the arrows weirdly offset so that they no longer spawn from the middle of the archer’s location. Testing, however, shows that the location of the spawn node and the archer’s location are the same. So because of this I suspect it’s a camera or graphics issue.

But there shouldn’t be because I’m in parallel projection, right?

cam = app.getCamera();
        frustumSize = 220f;
        float aspect = (float) cam.getWidth() / cam.getHeight();
        cam.setFrustum(-100, 100, -aspect * frustumSize, aspect * frustumSize, frustumSize, -frustumSize);
        //key: near, far, left, right, top, bottom
        cam.setLocation(new Vector3f(cam.getWidth() / 2, cam.getHeight() / 2, 10f));
        cam.setParallelProjection(true);
        camNode = new CameraNode("Camera Node", cam);
//This mode means that camera copies the movements of the target:
        camNode.setControlDir(ControlDirection.SpatialToCamera);
        camNode.setLocalTranslation(new Vector3f(0, 0, 10f));

// following rotations are to mimic the guiNode
        camNode.lookAt(archer.getWorldTranslation(), Vector3f.UNIT_Y);
        Quaternion q = camNode.getLocalRotation().fromAngleAxis(-FastMath.PI/2, Vector3f.UNIT_Y);
        camNode.rotate(q);
        //Attach the camNode to the target:
        archer.attachChild(camNode);

Some more info if this helps: not only does testing imply that the arrows spawn in the right location, they behave correctly too (i.e. if I move a little bit north, the arrows now appear to spawn too far north. If I then fire southerly, they will travel south and then detach as if they had collided with the edge of the screen despite not having actually reached the bottom of the screen).

Let me know if I need to share any more information. Thanks in advance!

Nothing? I’ve double/tripled checked that it wasn’t the arrows themselves; I took care to make sure that I never accidentally moved them outside of centering the picture to its node. So I believe this is a camera issue but understanding the camera seems especially difficult.

Well, that line is really strange in parallel projection. You are both moving the camera and changing where it views which in parallel projection seems wrong… but maybe I don’t understand what you are doing.

A simple single class test case illustrating the issue is probably what you need. This isn’t a Camera bug, I can nearly guarantee that.

Thank you for responding!

Yes I am moving the camera, although that one particular line is only called once (to set up the scene, whole camera block code I posted was the set-up). I did that because I had trouble actually setting up the camera. Without that line, and the rotate() line too, the entire scene would be black.

The camera is moving whenever I move the character because I want to design a navigable map larger than the screen (think Pokemon). That’s the purpose of the camNode, or at least, that’s what the wiki makes me believe.

I’ll try some more experimentation and do that test case when I get home. Thanks again!

No good. I may just not understand what you mean by a “simple single class test case” but I tried

assert (arrow.getLocalTranslation().equals(archer.getLocalTranslation())) : "not the same translation";

and it works out okay (assertions are working)

All I’m trying to do is have the location of where I spawn my arrows line up with the location of my archer, no matter where he is. The game thinks they are aligned but my visual is messed up. I don’t really know how to test the camera either…

A simple single class test case is one .java file that you can post to the forum that exhibits the issue so that we might see what you are doing wrong.

It avoids the 100 posts of back and forth as we ask you to see yet another line of code that might be in issue… and there is always the chance that the simple test case works fine and then you can figure out what’s different.

Thanks! That was actually quite an interesting experiment. I’m not a total beginner to Java, but debugging and testing is definitely new.

Unfortunately, I haven’t figured anything else out except that the problem seems to have to do with Picture being treated (?) differently from Mesh. Pictures move faster than meshes it seems?

Here’s a single class test, also, I apologize about my unfamiliarity w/ test assets. If the display is confusing, try replacing “Effects/Explosion/flame.png” at line 117 with a better png.

https://github.com/claracurrier/gameTests/blob/master/FireArrowTest.java

Thanks again

Pictures are scaled… where as the mesh is likely already the size it needs to be.

For example, if you make a Quad(100, 100) then it’s actually 100 units square. If you make a Picture and set it’s size to 100, 100 then it’s still thinks it’s only 1x1 units but has a setLocalScale() of 100. Maybe that messes up the camera node if it’s attached to a picture.

…at any rate, Picture otherwise provides no real advantage over a textured Quad except I think it saves one line of code or so.

That does seem to fix this issue. Although now there seem to be side effects such as breaking my arrow aiming mechanism. I know why that’s not working though so I think I can fix that myself. Thank you for your help! I’ll mark this as solved.