screen offset when following mouse

I have an obejct that creates a “walker” object used to create another object. It has two bugs for me:

one ifI do not set a startPOS then it breifly creates the walker at 0,0,0 and then jumps to the mouse giving an unprofessional flicker.

two if I set the walker to spawn at the mouse coordinate’s then it is offset from the mouse a good distance. How can I get around this?

 def followmouse(Task):
            mouseDummyNP = render2d.attachNewNode('mouse')
            myTexture = loader.loadTexture("textures/gravestone1.png")#an empty image to walk the mouse to where image will go
            cm = CardMaker('gravewalker_1')
            self.gravewalker_1 = render.attachNewNode(cm.generate()) 
            self.gravewalker_1.setTexture(myTexture)
            self.gravewalker_1.setTransparency(1)
            self.gravewalker_1.setScale(0.1)   
#this is where I have the problem:  How do I have it spawn at the mouse and follow without offset?
            self.gravewalker_1.reparentTo(mouseDummyNP)

            
            base.mouseWatcherNode.setGeometry(mouseDummyNP.node())
           

            def mousePut():
                mposY=base.mouseWatcherNode.getMouseY()     
                mposX=base.mouseWatcherNode.getMouseX() 
                myTexture = loader.loadTexture("textures/outhouse.png")
                cm = CardMaker('gravestone_1')
                self.gravestone_1 = render.attachNewNode(cm.generate()) 
                self.gravestone_1.setTexture(myTexture)
                self.gravestone_1.setTransparency(1)
                self.gravestone_1.setBin("fixed",20)
                self.gravestone_1.reparentTo(render2d)
                self.gravestone_1.setScale(0.1)
                self.gravestone_1.setX(mposX)
                self.gravestone_1.setZ(mposY)
                return Task.done
            
            base.accept("mouse1", mousePut)       #left-click puts a piece
            
            return Task.cont
            
        followmouse(Task)

    

def callzbimkr1():
    
    zbmkr=zombiemaker1()


zombiebutton1 = DirectButton(image='textures/grave1icon.png', scale=0.08, pos=(-1.225,0,-0.891), relief=None, command=callzbimkr1)

It’s a little bit odd that you’ve structured your followmouse function as if it were a task function, even though you don’t actually add it as a task; you in fact call it exactly once. (Which is the right thing to do in this case–you wouldn’t want to do that work every frame. It’s just confusing to read because it looks like you intend that function to be called every frame, which would be wrong.)

Anyway, to answer your question: I think the offset you’re referring to is due to the CardMaker, which creates its geometry by default with (0, 0) in the lower-left corner. This means that the lower-left corner of your image tracks the mouse position.

If you want to put the center at (0, 0) instead, you can make this call:

cm = CardMaker('gravewalker_1')
cm.setFrame(-0.5, 0.5, -0.5, 0.5)

This tells the CardMaker to move the card to -0.5 … -0.5, putting (0, 0) at the center of the card.

David

I had started out to do it every frame- but changed I guess I was too lazy to change the setup

anyway this did not fix it.

let me graph it for you


…x<----where the walker object first spawns before following mouse a half second later


  • <---------- zombiebutton1 and mouse cursor location ehere the walker should spawn

x = is where the object first shows up for about a .5 seconds before it follows mouse.

  • = is where it is supposed to start

but after a .5 second it folows the mouse correctly- so if I try to spawn the object where either mouse is or the button location then it does not follow the mouse correctly but instead has an offset.

As follows:

If I set to either:

self.gravewalker_1.setPos(zombiebutton1.getPos())

or

self.gravewalker_1.setX(…getMouseX())
. . . etc

either way still offsets the object following the mouse so that it looks like this (m is the mouse cursor x is the following object)


… m<-----mouse cursor

… x<-----walker object


  • <----(xombiebutton1 pos)

x=should be at same point as m not offset over

Thanks

Wait, the problem is just the initial placement of the walker object? And after the initial appearance it shows in the correct place?

Well, just hide it initially:

self.gravewalker_1.hide()

The MouseWatcher will show it again when it has a good position for it.

David

it still doesn’t work- I now get no object shown. So I tried adding .show() after the setGeometry command:

base.mouseWatcherNode.setGeometry(mouseDummyNP.node())
self.gravewalker_1.show()

But it just does what it did before.

This probably is not the best way but here is what I did:

def showmouse(Task):
                self.gravewalker_1.show()    
            
taskMgr.doMethodLater(0.5,showmouse, 'MyTaskName', extraArgs=[], appendTask=True))