简体   繁体   中英

Java snap to grid

Okay so I'm trying to make things snap to a grid I have.

This is how I snap to the screen itself:

int finalCalcX = (mouseX / Handler.gridSpace32) * Handler.gridSpace32;
int finalCalcY = (mouseY / Handler.gridSpace32) * Handler.gridSpace32;

The variable names speak for themselves I think. Mouse coordinates divided by my tiles being 32x32 pixels, times that again to get the snap-to-grid functionality.

Now this works fine for the screen, but when I want to add it to the "map" itself, I can't just add my map x and y offsets to that, it gets messed up.

I've played around with it for about two days, and I also got it to snap to the map itself, but when I'm say, halfway in the map on both axis, the mouseX and mouseY messes the grid thing up. It's kind of hard for me to explain, but the offset from the 0, 0 (every origins position, even the screen) PLUS the maps offset when you move away from the origin, gets added to the distance between the cursor itself and the transparent snap-to-grid tile that I'm using to test. Basically the offset between the maps origin, and the camera, is for some reason the same offset between the cursor and the transparent tile. So the further into the map i move, the further away the tile gets from the cursor, and eventually moves outside the screen width and height... When I move further into the map, I want the snap-to-grid functionality to stay corret, no matter where on the map I am.

Render method:

for (int y = startY; y < endY; y++) {
    for (int x = startX; x < endX; x++) {
        gridSpace(graphics, (int) (x * Handler.gridSpace32 - handler.getCamera().getOffsetX()),
                    (int) (y * Handler.gridSpace32 - handler.getCamera().getOffsetY()));

        checkHighlight(graphics);
    }
}

The gridSpace is the grid itself. Here is what's in the highlight at the moment:

int finalCalcX = (mouseX / Handler.gridSpace32) * Handler.gridSpace32;
int finalCalcY = (mouseY / Handler.gridSpace32) * Handler.gridSpace32;

graphics.setColor(new Color(100, 200, 100, 3));
graphics.fillRect(finalCalcX, finalCalcY, Handler.gridSpace32, Handler.gridSpace32);

Sorry for my terrible explanation skills, but that's the best I can do. What am I doing wrong?

I think I recreated what you are getting, and the problem lies with usage of incorrect sign in calculations of camera position and translation. Executing code below you should get similar behavior to what you described, while uncommenting commented lines (while commenting out the ones that follow them) should give you correct behavior.

package test;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.*;

public class SnapToGrid extends JPanel implements MouseMotionListener{

    private int[] camera;
    private int[] mouse;
    private final int gridSize = 16;

    SnapToGrid() {
        camera = new int[2];
        mouse = new int[2];
        setFocusable(true);
        addMouseMotionListener(this);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        //g2.translate(-camera[0], -camera[1]);
        g2.translate(camera[0], camera[1]);

        //draw background
        for (int i = 0; i < 9; i++)
            for (int j = 0; j < 9; j++)
            {
                Color c = ((j*9) + i) % 2 == 0 ? Color.black : Color.white;
                g2.setColor(c);
                g2.fillRect(i*gridSize, j*gridSize, gridSize, gridSize);
            }
        g2.setColor(Color.blue);
        int[] snappedPos = getSnappedMousePosition();
        g2.fillRect(snappedPos[0], snappedPos[1], gridSize, gridSize);
    }

    private int[] getSnappedMousePosition() {
        return new int[] {
            camera[0] + mouse[0] - ((camera[0] + mouse[0]) % gridSize),
            camera[1] + mouse[1] - ((camera[1] + mouse[1]) % gridSize)  
        };
    }

    public static void main (String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SnapToGrid());
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        //camera[0] -= e.getX() - mouse[0]; 
        //camera[1] -= e.getY() - mouse[1];
        camera[0] += e.getX() - mouse[0]; 
        camera[1] += e.getY() - mouse[1];

        mouse[0] = e.getX();
        mouse[1] = e.getY();
        repaint();

    }

    @Override
    public void mouseMoved(MouseEvent e) {
        mouse[0] = e.getX();
        mouse[1] = e.getY();
        repaint();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(gridSize * 18, gridSize * 18);
    }

}

One thing that I really don't like with your code, is that you are not using transformations. Using transformations allows you to separate world from viewport, submits to far easier debugging of issues like this here, and most importantly, if you want to add things like scaling or rotating later on, you only need to add few lines, as opposed to rewriting half of your render method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM