Author Topic: Character Moves Towards Mouse Click  (Read 5395 times)

AGP

• Posts: 1639
Character Moves Towards Mouse Click
« on: August 26, 2008, 09:17:15 pm »
I'm trying to make an RPG with 2D backgrounds and a 3D hero. When the player clicks on the screen, the hero has to move that way. The following's what I did (for translation, rotation is something else). Is it wrong, because it's not working?
Code: [Select]
`SimpleVector heroCenter = Interact2D.project3D2D(theCamera, buffer, hero.getTransformedCenter());SimpleVector destination = Interact2D.reproject2D3D(theCamera, buffer, mousePoint.x-(int)heroCenter.x, mousePoint.y-(int)heroCenter.y, hero.getTransformedCenter().z);destination.z = destination.y;destination.y = 0;hero.translate(destination);`

EgonOlsen

• Posts: 12027
Re: Character Moves Towards Mouse Click
« Reply #1 on: August 26, 2008, 09:44:11 pm »
At least it manages to confuse me... What exactly isn't working? What's the outcome?

AGP

• Posts: 1639
Re: Character Moves Towards Mouse Click
« Reply #2 on: August 26, 2008, 09:47:25 pm »
Hah, as opposed to my other overly simple questions? : -)

What's not working is that the translation value is wrong (hero goes somewhere else).

EgonOlsen

• Posts: 12027
Re: Character Moves Towards Mouse Click
« Reply #3 on: August 26, 2008, 09:59:02 pm »
What puzzles me is the "destination.z = destination.y; destination.y = 0;"-part...but apart from that, you are feeding the deltas into the reproject2D3D-method where i think you should simply give it mouseX and mouseY. The method works with absolute screen coordinates, not with some deltas. The translation should then be the difference vector between the current translation and the projected point in 3D.
« Last Edit: August 26, 2008, 10:27:34 pm by EgonOlsen »

AGP

• Posts: 1639
Re: Character Moves Towards Mouse Click
« Reply #4 on: August 26, 2008, 10:30:17 pm »
I guess I misunderstood the documentation, because it says it will assume z to be 1. And the hero should move on the x and z planes. So I figured the z value would instead be placed on the y coordinate (some orientation problem someone with more spacial perception than I would understand!). But you're right, of course, about the delta. It should be calculated on the call to transform (between destination and hero.getTransformedCenter()). The following still doesn't work:
Code: [Select]
`SimpleVector heroCenter3D = hero.getTransformedCenter();SimpleVector destination = Interact2D.reproject2D3D(theCamera, buffer, mousePoint.x, mousePoint.y);hero.translate(destination.x-heroCenter3D.x, destination.y-heroCenter3D.y, destination.z-heroCenter3D.z);`
Note that the hero shouldn't even move in the y axis anyway, but I suppose I would just change the y and z values later (after I at least saw the hero appearing to be in the right place).

EgonOlsen

• Posts: 12027
Re: Character Moves Towards Mouse Click
« Reply #5 on: August 26, 2008, 10:41:11 pm »
Maybe setting the picking plane to heroCenter3D.z wasn't that bad. Does it help to add it again? I'm sorry, but i have no real imagination how your screen looks like and how the hero is intended to move in it, which is why i'm a little confused about what is correct in this case.

AGP

• Posts: 1639
Re: Character Moves Towards Mouse Click
« Reply #6 on: August 26, 2008, 11:05:06 pm »
I sent you an e-mail with a screenshot. If we find a solution, I will post it on this thread.

As for the picking plane, I expect you mean for me to add destination.z = destination.y; destination.y = 0; again. But if that's not it, please explain. And should I pass any value for z on reproject2D3D() call?

EgonOlsen

• Posts: 12027
Re: Character Moves Towards Mouse Click
« Reply #7 on: August 27, 2008, 07:52:49 pm »
Ok, I've got the screen shot. I understand the problem better now. The reproject2D3D is not suitable for this, because it assumes a fixed Z. You don't have a fixed Z, you have a fixed Y. I tried to adjust the formula for reprojection but it didn't work as expected. There has to be an error somewhere, but sadly, i don't have access to the code ATM. I'll look into it tomorrow.
Another solution would be to use a plane in the X-Z-plane and some ray casting... i have a working version of this, but again: No access until tomorrow...
« Last Edit: August 27, 2008, 07:55:46 pm by EgonOlsen »

AGP

• Posts: 1639
Re: Character Moves Towards Mouse Click
« Reply #8 on: August 28, 2008, 12:56:00 am »
Cool. I await your solution, pal. Thanks.

EgonOlsen

• Posts: 12027
Re: Character Moves Towards Mouse Click
« Reply #9 on: August 28, 2008, 02:19:39 pm »
Here's the code (a small demo to be exact) of the plane-based solution. The drawback is, that you need that plane and have to orientate it correctly. The pro is, that you can do this with any kind of geometry, i.e. you can add ramps and such easier.
The reprojection solution should be doable too, but i got lost in the magic of converting between spaces, got wrong results and ran out of time. I hope that this solution is appropriate for your problem:

Code: [Select]
`import javax.swing.*;import java.awt.*;import java.awt.event.*;import com.threed.jpct.*;import com.threed.jpct.util.*;public class MouseFollow extends JFrame implements MouseMotionListener {    private final static long serialVersionUID=1L;      private Graphics g = null;    private FrameBuffer fb = null;    private World world = null;    private Object3D plane = null;    private Object3D ramp = null;    private Object3D cube = null;    private Object3D cube2 = null;    private Object3D sphere = null;    private boolean doloop = true;    private int x=320;    private int y=240;    public MouseFollow() {        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        pack();        setSize(640, 480);        setResizable(false);        setLocationRelativeTo(null);        setVisible(true);        this.addMouseMotionListener(this);        g = getGraphics();    }    public void mouseMoved(MouseEvent m) {        x=m.getX();        y=m.getY();    }    public void mouseDragged(MouseEvent m) {}    private void initStuff() {        fb = new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_NORMAL);        world = new World();        fb.enableRenderer(IRenderer.RENDERER_SOFTWARE);        ramp = Primitives.getCube(20);        ramp.setAdditionalColor(Color.red);        plane = Primitives.getPlane(1, 200);        plane.setAdditionalColor(Color.GREEN);        sphere=Primitives.getSphere(30);        sphere.setAdditionalColor(Color.CYAN);        sphere.translate(-50,10,50);        cube2=Primitives.getCube(20);        cube2.setAdditionalColor(Color.ORANGE);        cube2.translate(60,-20,60);        plane.rotateX((float) Math.PI / 2f);        ramp.rotateX((float) Math.PI / 2f);        cube = Primitives.getCube(2);        plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);        ramp.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);        sphere.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);        cube2.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);        world.addObject(plane);        world.addObject(ramp);        world.addObject(cube);        world.addObject(sphere);        world.addObject(cube2);        cube.translate(-50, -10, -50);        Light light = new Light(world);        light.setPosition(new SimpleVector(0, -80, 0));        light.setIntensity(40, 25, 22);        world.buildAllObjects();    }    private void follow() {        SimpleVector ray=Interact2D.reproject2D3D(world.getCamera(), fb, x, y);                if (ray!=null) {            SimpleVector norm=ray.normalize();            Matrix mat=world.getCamera().getBack();            mat=mat.invert3x3();            norm.matMul(mat);            SimpleVector ws=new SimpleVector(ray);            ws.matMul(world.getCamera().getBack().invert3x3());            ws.add(world.getCamera().getPosition());            float f=world.calcMinDistance(world.getCamera().getPosition(), norm, 1000);            if (f!=Object3D.COLLISION_NONE) {                SimpleVector offset=new SimpleVector(norm);                norm.scalarMul(f);                norm=norm.calcSub(offset);                cube.getTranslationMatrix().setIdentity();                cube.translate(norm);                cube.translate(world.getCamera().getPosition());            }        }    }    private void doIt() throws Exception {        Camera cam = world.getCamera();        cam.moveCamera(Camera.CAMERA_MOVEOUT, 100);        cam.moveCamera(Camera.CAMERA_MOVEUP, 160);        cam.lookAt(plane.getTransformedCenter());        world.getLights().setOverbrightLighting(Lights.OVERBRIGHT_LIGHTING_DISABLED);        while(doloop) {            follow();            fb.clear();            world.renderScene(fb);            world.draw(fb);            fb.update();            fb.display(g);            Thread.sleep(10);        }        fb.disableRenderer(IRenderer.RENDERER_OPENGL);        System.exit(0);    }    public static void main(String[] args) throws Exception {        MouseFollow cd = new MouseFollow();        cd.initStuff();        cd.doIt();    }}`

AGP

• Posts: 1639
Re: Character Moves Towards Mouse Click
« Reply #10 on: August 28, 2008, 09:58:10 pm »
Thanks for the solution, my friend. But I don't understand why it is that the collision-detection line makes it work. If I take it out for the plane, it doesn't work on the plane. But if the other objects are still calculating the collision, it works on them. Why is that?

EgonOlsen

• Posts: 12027
Re: Character Moves Towards Mouse Click
« Reply #11 on: August 28, 2008, 10:00:08 pm »
Because it casts a ray into the scene that hits either the objects or the plane. If you disable the plane, it can't be hit any longer.

AGP

• Posts: 1639
Re: Character Moves Towards Mouse Click
« Reply #12 on: August 28, 2008, 10:14:11 pm »
OK, that'll take me a little while. It's a little humbling discussing this with you, dude!

Here's a question: why does the cube translate to the camera's position? And then, why does the camera see something whose center is the same as its?