LWJGL开发问题:生成Tile后ArrayList为空+鼠标点击添加Quad失效
Hey there, let's work through your LWJGL problems one by one—these are all common hurdles, so I’ve got practical fixes and explanations for each:
1. Tile ArrayList Appears Empty After Generation
First up, if you’re sure the Tile objects are being created successfully and you’re reading the list after generation, the most likely culprit is variable shadowing or an incorrect reference.
Common Cause:
You might be initializing a local ArrayList<Tile> inside your generation method instead of using the class-level member variable. For example:
// Class-level member (intended list) private ArrayList<Tile> tiles; public void generateTiles() { // Oops—this creates a new local list instead of using the member variable ArrayList<Tile> tiles = new ArrayList<>(); tiles.add(new Tile(x, y, texture)); }
In this case, the member variable tiles is never actually populated—you’re just adding Tiles to a temporary list that gets discarded when the method finishes.
Fix:
- Ensure you’re initializing and modifying the same ArrayList instance across your code. Correct the generation method to use the member variable:
public void generateTiles() { tiles = new ArrayList<>(); // Initialize the member variable tiles.add(new Tile(x, y, texture)); // Verify with a print statement to confirm population System.out.println("Generated " + tiles.size() + " tiles"); } - Double-check that you’re not reinitializing the list elsewhere in your code (e.g., in a render loop) before reading it.
2. Left-Click Quad Addition Not Working (But Other Additions Are)
If your drawQuads list works for other Quad additions but fails on left-click, the issue is almost certainly in your mouse input handling logic or coordinate conversion.
Possible Causes & Fixes:
Incorrect Mouse Button Check:
Make sure you’re using the correct GLFW constant for left-click. In LWJGL, the left mouse button isGLFW_MOUSE_BUTTON_LEFT. A common mistake is using the wrong integer value (e.g.,1instead of the constant).glfwSetMouseButtonCallback(window, (window, button, action, mods) -> { // Correct check for left-click press if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { // Add your Quad here drawQuads.add(new Quad(mouseX, mouseY, 20, 20)); // Confirm the list is being updated System.out.println("Quad added! List size: " + drawQuads.size()); } });Unconverted Screen Coordinates:
GLFW returns mouse positions in screen space (top-left origin, pixel values). If yourdrawQuadsuses world/orthographic coordinates, you need to convert the screen position to match your rendering space. For example, with an orthographic projection:// Get raw screen coordinates double screenX = glfwGetCursorPosX(window); double screenY = glfwGetCursorPosY(window); // Convert to orthographic world coordinates (adjust values to match your projection) float worldX = (float)(screenX / windowWidth * orthoWidth - orthoWidth / 2); // Flip Y-axis since screen Y starts at top, but ortho Y often starts at bottom float worldY = (float)((windowHeight - screenY) / windowHeight * orthoHeight - orthoHeight / 2); drawQuads.add(new Quad(worldX, worldY, 20, 20));Invisible Quad:
If the Quad is being added but not rendering, check if its color matches the background, or if its size/position is set to 0 (making it invisible).
3. Differentiating Single Clicks vs. Long Presses
To separate single clicks and long presses, you’ll need to track the duration of the mouse press and trigger actions based on that. Here’s a robust implementation:
Step-by-Step Implementation:
Add these class-level variables to track state:
private long pressStartTime; private boolean isLongPressTriggered = false; private boolean isLeftMousePressed = false; // Adjust these thresholds to your needs (in milliseconds) private static final long LONG_PRESS_THRESHOLD = 250; // Time needed to count as long press private static final long LONG_PRESS_REPEAT_INTERVAL = 100; // Repeat interval for long press actions private long lastLongPressActionTime = 0;Update your mouse button callback to set initial state:
glfwSetMouseButtonCallback(window, (window, button, action, mods) -> { if (button == GLFW_MOUSE_BUTTON_LEFT) { if (action == GLFW_PRESS) { isLeftMousePressed = true; pressStartTime = System.currentTimeMillis(); isLongPressTriggered = false; lastLongPressActionTime = pressStartTime; } else if (action == GLFW_RELEASE) { isLeftMousePressed = false; long pressDuration = System.currentTimeMillis() - pressStartTime; // Trigger single click only if long press wasn't activated if (pressDuration < LONG_PRESS_THRESHOLD && !isLongPressTriggered) { performSingleClickAction(); } } } });Add logic to your main render loop to handle long presses:
while (!glfwWindowShouldClose(window)) { // ... Your existing render/update logic ... if (isLeftMousePressed) { long currentTime = System.currentTimeMillis(); if (!isLongPressTriggered) { // Check if we've crossed the long press threshold if (currentTime - pressStartTime >= LONG_PRESS_THRESHOLD) { isLongPressTriggered = true; performLongPressStartAction(); lastLongPressActionTime = currentTime; } } else { // Repeat long press action at the specified interval if (currentTime - lastLongPressActionTime >= LONG_PRESS_REPEAT_INTERVAL) { performLongPressRepeatAction(); lastLongPressActionTime = currentTime; } } } // ... Swap buffers, poll events, etc. ... }Replace the placeholder methods with your actual logic:
private void performSingleClickAction() { // Code for single click (e.g., place a tile) System.out.println("Single click detected!"); } private void performLongPressStartAction() { // Code for initial long press trigger (e.g., start deleting tiles) System.out.println("Long press started!"); } private void performLongPressRepeatAction() { // Code for repeated long press action (e.g., delete tiles continuously) System.out.println("Long press repeating..."); }
This setup ensures single clicks only fire if the press is short, and long presses trigger both an initial action and repeated actions if held.
内容的提问来源于stack exchange,提问作者Frost

