Cannot get only 1 box to move. Java 1.7 + LWJGL 2.9.1 in NetBeans

I am going through several tutorials and managed to create a display with 2 rendered squares. The problem I have is that when I move one square, the other moves at the same time. I only want one of the squares to move. I did a search here and used Google, but could not locate an article on this specific issue. Below is the code I am using, any ideas? I know I have to add a timer (ticks) and more, but I am trying to get a prototype done.


package worldofadventure;

/**
 *
 * @author Stoofus
 */

// Start imports
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

// End imports

// Start class Main
public class Main
{

    /**
     * @param args the command line arguments
     */
    
    // Start variables
    static String TITLE = "World of Adventure - PreAlpha version 0.0.1";
    static int S_WIDTH = 800; // Screen Width
    static int S_HEIGHT = 600; // Screen Height
    static final Logger LOGGER = Logger.getLogger( Main.class.getName() );
    int squareSize; // Size of the square
    int squareX; // Horizontal location of the square
    int squareY; // Vertical location of the square
    int squareZ; // Depth of the square relative to the viewer
    
    int rectSize; // Size of rectangle
    int rectX; // Horizontal location of rectangle
    int rectY; // Vertical location of rectangle
    int rectZ; // Depth of rectangle relative to the viewer
    // End variables
    
    // Add a log handler and create a log file
    static
    {
        try
        {
            LOGGER.addHandler( new FileHandler("errors.log", true));
        }
        catch( IOException ex )
        {
            LOGGER.log( Level.WARNING, ex.toString(), ex );
        }
    } // End log handler
    
    // Start main program
    public static void main(String[] args) 
    {
        // Start the main GUI
        mainGUI myGUI = new mainGUI(); // Create myGUI object
        myGUI.setTitle( TITLE ); // Set title
        myGUI.setVisible( true ); // Set visable to true
        
    } // End main program
    
    // Start class startGame
    public void startGame()
    {
        Main main = null; // Create a null object
        try
        {
            // Print out mapped keys
            System.out.println( "Keys:" );
            System.out.println( "Q = Shrink" );
            System.out.println( "E = Grow" );
            System.out.println( "W = Up" );
            System.out.println( "S = Down" );
            System.out.println( "A = Left" );
            System.out.println( "D = Right" );
            System.out.println( "Esc = Exit" );
            main = new Main(); // Create an instance of the object
            main.create(); // Create the display
            main.run(); // Run the display
        }
        // Ooops, record what went wrong
        catch( Exception ex )
        {
            LOGGER.log( Level.SEVERE, ex.toString(), ex );
        }
        finally
        {
            if (main != null )
            {
                main.destroy(); // Destroy the instance of the object
            }
        }
    } // End class startGame
    
    // Start Main constructor
    public Main()
    {
        // Initialize variables
        squareSize = 100; // Initial size of square
        squareX = 55; // Initial X (Horizontal) position of square
        squareY = 50; // Initial Y (Vertical) position of square
        squareZ = 0; // Initial Z position of square
        
        rectSize = 100; // Initial size of rectangle
        rectX = 200; // Initial X (Horizontal) position of rectangle
        rectY = 50; // Initial vertical position of rectangle
        rectZ = 0; // Initial Z position of rectangle
    } // End Main constructor
    
    // Start class create
    public void create() throws LWJGLException
    {
        // Display
        // S_WIDTH = Display Width
        // S_HEIGHT = Display Heigh
        Display.setDisplayMode( new DisplayMode( S_WIDTH, S_HEIGHT ) );
        Display.setFullscreen( false );
        Display.setTitle( TITLE ); // Same title of mainGUI
        Display.create(); // Create the display object
        
        // Create keyboard
        Keyboard.create();
        
        // Create and ungrab mouse
        Mouse.setGrabbed( false );
        Mouse.create();
        
        // Initialize OpenGL
        initGL();
        resizeGL();
    } // End class create
    
    // Start class destroy
    // This method already checks if they have been created
    // before destroying them
    public void destroy()
    {
        Mouse.destroy();
        Keyboard.destroy();
        Display.destroy();
    } // End class destroy
    
    // Start class initGL
    // Creates the background
    public void initGL()
    {
        // 2D Initialization
        glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
        glDisable( GL_DEPTH_TEST );
        glDisable( GL_LIGHTING );
        
    } // End class initGL
    
    // Start class processKeyboard
    public void processKeyboard()
    {
        // Square's X axis
        if( Keyboard.isKeyDown( Keyboard.KEY_W ) )
        {
            // Move square up
            ++squareY;
        }
        if ( Keyboard.isKeyDown( Keyboard.KEY_S ) )
        {
            // Move square down
            --squareY;
        }
        
        // Square's Z axis
        if ( Keyboard.isKeyDown( Keyboard.KEY_A ) )
        {
            // Move square left
            --squareX;
        }
        if ( Keyboard.isKeyDown( Keyboard.KEY_D ) )
        {
            // Move square right
            ++squareX;
        }
        
        // Shrink or Grow square
        if ( Keyboard.isKeyDown( Keyboard.KEY_Q ) )
        {
            // Shrink square
            --squareSize;
        }
        if ( Keyboard.isKeyDown( Keyboard.KEY_E ) )
        {
            // Grow square
            ++squareSize;
        }
    } // End class processKeyboard
    
    // Start class processMouse
    public void processMouse()
    {
        // Enter mouse code here
    } // End class processMouse
    
    // Start class render
    public void render()
    {
        glClear( GL_COLOR_BUFFER_BIT );
        glLoadIdentity();
        
        // Translate into view for square
        glTranslatef( squareX, squareY, 0.0f );
        glRotatef( squareZ, 0.0f, 0.0f, 1.0f );
        glTranslatef( -( squareSize >> 1 ), -( squareSize >> 1 ), 0.0f );
        glColor3f( 0.0f, 0.5f, 0.5f );
        
        // Square
        glBegin( GL_QUADS );
            glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f );
            glTexCoord2f( 1.0f, 0.0f ); glVertex2f( squareSize, 0.0f );
            glTexCoord2f( 1.0f, 1.0f ); glVertex2f( squareSize, squareSize );
            glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, squareSize );
        glEnd();
        
        // Translate into view for rectangle
        glTranslatef( rectX, rectY, 0.0f );
        glRotatef( rectZ, 0.0f, 0.0f, 1.0f );
        glTranslatef( -( rectSize >> 1 ), -( rectSize >> 1 ), 0.0f );
        glColor3f( 0.0f, 0.5f, 0.5f );
        
        glBegin( GL_QUADS );
            glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f );
            glTexCoord2f( 1.0f, 0.0f ); glVertex2f( rectSize, 0.0f );
            glTexCoord2f( 1.0f, 1.0f ); glVertex2f( rectSize, rectSize );
            glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, rectSize );
        glEnd();
        
    } // End class render
    
    // Start class resizeGL
    public void resizeGL()
    {
        // 2D Scene
        glViewport( 0,0, S_WIDTH, S_HEIGHT );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        gluOrtho2D( 0.0f, S_WIDTH, 0.0f, S_HEIGHT );
        glPushMatrix();
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
        glPushMatrix();
    } // End class resizeGL
    
    // Start class run
    public void run()
    {
        while( !Display.isCloseRequested() &&
                !Keyboard.isKeyDown( Keyboard.KEY_ESCAPE ) )
        {
            if ( Display.isVisible() )
            {
                processKeyboard();
                processMouse();
                update();
                render();
            }
            else
            {
                if( Display.isDirty() )
                {
                    render();
                }
                try
                {
                    Thread.sleep( 100 );
                }
                catch( InterruptedException ex )
                {
                    
                }
            }
            Display.update();
            Display.sync( 60 );
        }
    } // End class run
    
    // Start class update
    public void update()
    {
        
        int squareEdge = (squareSize / 2 ); // Find the edge via its size
        int rectEdge = ( rectSize / 2 ); // Ditto
        
        // Don't go offscreen from bottom
        if ( squareY < 50 )
        {
            squareY = 50;
        }
        // Don't go offscreen from top
        if ( squareY > S_HEIGHT - squareEdge )
        {
            squareY = S_HEIGHT - squareEdge;
        }
        // Don't go offscreen from left
        if ( squareX < squareEdge)
        {
            squareX = squareEdge;
        }
        // Don't go offscreen from right
        if ( squareX > S_WIDTH - squareEdge )
        {
            squareX = S_WIDTH - squareEdge;
        }
        
        // Don't get too small to see
        if ( squareSize < 5 )
        {
            squareSize = 5;
        }
        // Don't get bigger than the screen
        if ( squareSize > S_HEIGHT )
        {
            squareSize = S_HEIGHT;
        }
    } // End class update
    
} // End class Main

Thanks to Troubleshoots for the code tag suggestion! I kept comments to assist with the troubleshooting.

Please wrap the code in [“code”] … [/“code”] tags. It’ll make it much easier for us to read.
Note: Remove the quotation marks.

Also, removing some of the comments might make it slightly easier to read.

Instead of translating into view for each one, why not draw the square and rectangle at their coordinates?

Thanks for the suggestion but when I comment out the translate code for both, it only shows 1 white unmovable square instead of 2 blue squares which would move in unison.

No one yet? :wink:

I created a block class and extended that class. created two more blocks using the classes but still the same issue remains. Also, it seems that OpenGL (the way I am implementing it) is setting the X location relative to the last block.

How would I set it so that the blocks are in their absolute position? Also, any more ideas on the movement issue?

Thanks again!

The issue is with the rendering. OpenGL uses matrices for translating vertices. The translation, rotate and scale transformations all change the state of the modelview matrix; that is the combined model and view matrix which is used to hold transformations of the vertices relative to the camera. By that I mean, if you wanted the camera to be at (50, 0, 0) in the world, then you would call glTranslatef(-50f, 0f, 0f). That would change the state of the modelview matrix, meaning that all vertices are drawn at (-50f, 0f, 0f). This would be effectively moving the world instead of the camera, since the camera is at a fixed position, giving the same effect as if you were to move the camera +50f. These transformations however stack up, which is why they’re not moving independently.

If you want all your transformations to occur from the origin, you need to do the inverse of them after drawing your vertices. So where you call [icode]glTranslatef( squareX, squareY, 0.0f )[/icode], you will then want to call [icode]glTranslatef( -squareX, -squareY, 0.0f )[/icode] after you’ve drawn the square. This will effectively transform the matrix back to the origin. You do the same with scale and rotate operations.

The function [icode]glLoadIdentity()[/icode] changes the state of the matrix back to the identity matrix; a matrix which in simple you can think of as a number 0; it effectively resets the matrix.

I’ve tried to explain all of this in laymans terms, but if you want to read more about the matrix transforms and if you want to see how the matrices are effected, read here. Don’t worry if you’re extremely confused by the way; as a beginner to OpenGL just 5 weeks ago I was too. At the moment you seem to be learning the fixed function pipeline which is version 1.1 to 1.5, and that is fine because it’s a good way to get to know the basics, but the fixed function pipeline is very old and slow. The programmable pipeline begins at version 2.0 and is a lot more complicated, as you have to deal with all the matrices yourself, so for future reference when you want to progress to version 2.0, here’s a good book to read and the LWJGL code for the chapters. Definitely bookmark it. :slight_smile:

Oh and here’s a really good tutorial series by SHC which mainly uses the fixed function pipeline, but is a nice introduction to LWJGL.

don’t do the inverse operation, use the matrix push and pop functions before and after rendering a object.

Thank you for your suggestions! I will check out the links and try your suggestions today then will reply with the results.

While programming is not entirely new to me, using LWJGL with Java is. :slight_smile:

I tried the inverse operation and it only rendered one square. Then I tried the matrix push and pop method, still drew all three squares and they moved in unison.

My rendering code for the push and pop method, which I am sure are called in the wrong spots:


public void render()
    {
        glClear( GL_COLOR_BUFFER_BIT );
        glLoadIdentity();
        
        // Translate into view for square

        glTranslatef( squareX, squareY, 0.0f );
        glRotatef( squareZ, 0.0f, 0.0f, 1.0f );
        glTranslatef( -( squareSize >> 1 ), -( squareSize >> 1 ), 0.0f );
        glColor3f( 1.0f, 0.5f, 0.5f );

        glPushMatrix();
        glPopMatrix();
        
        // Square
        glBegin( GL_QUADS );
            glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f );
            glTexCoord2f( 1.0f, 0.0f ); glVertex2f( squareSize, 0.0f );
            glTexCoord2f( 1.0f, 1.0f ); glVertex2f( squareSize, squareSize );
            glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, squareSize );
        glEnd();
        
        glPushMatrix();
        glPopMatrix();
        
        // Translate into view for myBlock
        glTranslatef( myBlock.getX(), myBlock.getY(), 0.0f );
        glRotatef( myBlock.getZ(), 0.0f, 0.0f, 1.0f );
        glTranslatef( -( myBlock.blockSize >> 1 ), -( myBlock.blockSize >> 1 ), 0.0f );
        glColor3f( 0.0f, 0.5f, 0.5f );
        
        glPushMatrix();
        glPopMatrix();
        
        // myBlock
        glBegin( GL_QUADS );
            glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f );
            glTexCoord2f( 1.0f, 0.0f ); glVertex2f( myBlock.blockSize, 0.0f );
            glTexCoord2f( 1.0f, 1.0f ); glVertex2f( myBlock.blockSize, myBlock.blockSize );
            glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, myBlock.blockSize );
        glEnd();

        glPushMatrix();
        glPopMatrix();
        
        // Translate into view for myDirt

        glTranslatef( myDirt.getX(), myDirt.getY(), 0.0f );
        glRotatef( myDirt.getZ(), 0.0f, 0.0f, 1.0f );
        glTranslatef( -( myDirt.blockSize >> 1 ), -( myDirt.blockSize >> 1 ), 0.0f );
        glColor3f( 0.0f, 0.5f, 0.5f );
        
        glPushMatrix();
        glPopMatrix();
        
        
        // myDirt
        glBegin( GL_QUADS );
            glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f );
            glTexCoord2f( 1.0f, 0.0f ); glVertex2f( myDirt.blockSize, 0.0f );
            glTexCoord2f( 1.0f, 1.0f ); glVertex2f( myDirt.blockSize, myDirt.blockSize );
            glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, myDirt.blockSize );
        glEnd();
        
        glPushMatrix();
        glPopMatrix();
        
    } // End class render

Upon further reading, it appears that when I move, it moves the camera, not the block. It would appear to move the block when it is the only thing drawn on the screen. But when there are more blocks on the screen, the perspective appears to change and all appear to move. Would it be safe to say that it is the camera I am moving and not the block? If so, I would need to modify the code to make it more apparent that it is the camera that is being moved and not the block.

do a push before rendering and a pop after (push save matrix, pop load). So the other way around.

The camera is fixed at (0, 0) in the window space. You can not move the camera.
You’re using push and pop in the wrong way.

You have to wrap all the transformations and draw calls between push and pop. Push essentially creates a copy of the matrix for you to modify, then when you pop it, it means that it hasn’t modified the existing matrix. This is designed to allow you to easily apply a uniform transformation for the camera. As I said in my previous reply, applying a uniform transformation for the camera is essentially uniformly transformation the world by the negative camera transformation, giving the perception that the camera has moved.

Edit: Just to try and be clear, when I say the world, I mean 'all the vertices that are to be drawn’. Again, the world can’t move; it is just a theoretical undefined space. When you draw a vertex, you’re drawing that relative to the origin which is (0, 0, 0), and the scale of each axis is essentially defined by glViewport(), else it goes from (-1, +1) on the X and Y axis in window space and (0, +1) on the Z axis. The scale of the viewport is defined relative to the camera definition, which for 2D is glOrtho. Therefore, when you specify the parameters of glOrtho(), that essentially tells OpenGL the standard position on the axis’ which you can see. When you defined glViewport(), it specifies how those range of values should map to the screen, which allows OpenGL to calculate how to scale the axis’ of the world, and how to map the vertices that you want to draw to the screen.

Thanks Troubleshoots, that worked! Now I have a square that moves by itself and I can set absolute positioning for other blocks. Of course, hand building levels via code will not work, need to read up more about:

Level building in Java / LWJGL (OpenGL) and applying text to the rendering window.

I will be checking out the tutorials on here, and along with my prior programming knowledge, hopefully it won’t be too long before I am linking you guys to a prototype.

Thanks again for your assistance and I welcome other suggestions in this thread for matrix manipulations.

Level building isn’t specific to LWJGL, so you won’t find much specifically pertaining to that. What you need to look up is how to build a good parser, and choose what kind of files you’ll use. XML? Just text files? Images? LWJGL is just a wrapper for OpenGL that just draws vertices to the screen, nothing more, so you won’t find anything to do with level loading.

As for text rendering, look at Slick-Util. Its a nice utility library that you can easily draw text with in just a few lines of code.

I am following SHC’s tutorial and I am learning a lot.

As for level building or loading, I am not quite there yet. Still need to be able to draw competently to the screen, even if it is a still background with one moving player.

Goal would be for the player to generate a character and move it around the screen. Hopefully, with a menu and a clean way to exit the game.

After that, maybe saving player state and loading a simple level.