glTranslatef not working?

Started by ChaoticCactus, April 14, 2013, 15:27:21

Previous topic - Next topic

ChaoticCactus

Hello,

I'm currently working on making a game somewhat like terraria.  In the sense that it's randomly generated and a sandbox game.  I've followed The Coding Universe's tutorials for a 2D Minecraft and then I added random map generation.  Now I want to add a player that doesn't move independently but stays fixed in the same position in the screen, while the world scrolls.  So I tried using this:

glPushMatrix();
			if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && canMove) {
				glTranslatef(moveSpeed, 0, 0);
			}
         glPopMatrix();


Nothing happens.  If you need me to post more code I'll do so, as I'm not sure what you might want to see.  But if you could give me some help that would be great!

Thanks for your time!

quew8

glPushMatrix() and glPopMatrix() work like saving and loading the current matrix. So what you are doing there is saving the matrix, translating it, then loading the matrix from before it was translated. Hence nothing happens.
Read this chapter from the red book: http://www.glprogramming.com/red/chapter03.html or there are huge numbers of relevant tutorials scattered across the web.

ChaoticCactus

Ok, I'll be sure to check that out as it seems rather interesting.  I never realized how similar C/C++ and Java were.  Anyway, I got rid of the glPush and glPop Matrices aaaaand it did nothing.  But if I get also change moveSpeed to: 

    moveSpeed * delta

then the sky background moves a little bit to the right and then moves back after I release the right key.  I feel like this is a step in the right direction, but I'm not sure what to add next. 

quew8

Presumably you are calling glInitMatrix() at some point. This sets the current matrix to the identity matrix (which means no transforms). Either make a variable recording the player position and translate to this each frame (I consider this to be better) or get rid of glInitMatrix().

ChaoticCactus

I don't have the glInitMatrix() anywhere.  But for the translating to the players position would I just do this?
[s]if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && canMove) {
			x += 1;
                        glTranslatef(x, 0, 0);
		}[/s]
 
EDIT:  Ok, scratch that.  I just tried it and it doesn't work at all.  The image in the background that I have for the "sky" just follows the player everywhere.  As in the top left corner of the sky is where the top left corner of the player is.  So, if you could explain, quew, that would be great!

quew8

Ok so here is a basic class:
public class Foo {
    private Player player = new Player();
    public void render() {
        //Setup Projection. If you do this in initialization then don't touch the proj matrix then this is unnecessary.
        glMatrixMode(GL_PROJECTION);
        glInitMatrix();
        glOrtho(-1, 1, -1, 1, -1, 1);//This is actually the id matrix but sub in your values.

        //Setup Modelview
        glMatrixMode(GL_MODELVIEW);
        glInitMatrix();
        
        //Draw the player with no translation at the centre of the screen.
        player.draw(); 

        //Translate to player pos.
        glTranslatef(player.x, player.y);
        
        //Draw the rest of the scene.
        renderScene();
    }
    public void update(int delta) {
        if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && player.canMove) {
	    player.x += (delta * PLAYER_SPEED);
        }
    }
}

ChaoticCactus

Uh oh.  For whatever reason that doesn't work.  Here's the PasteBin to the important parts of the project (Sorry for the length of the paste), because I can't see what's wrong and it would probably be for the best if you could see all of my code.  Sorry if I'm being a bother, I would just really like for this to work :-\!

http://pastebin.com/dX9NC2ZK

Thanks for your time again.

quew8

Ok, two things I noticed relating to camera pos.
1) A little trick we programmers like to play is to never translate the player. Which is what all my examples show. Ever noticed how the player is always in the centre of the screen? Essentially we draw the player then we translate to the position and draw the rest of everything. Change your player render to:
@Override
        public void render() {         
                glBegin(GL_QUADS);
                        glTexCoord2f(0, 0);
                                glVertex2f(0, 0); //Sorry you'll want to change this to render in the centre of the screen probably
                        glTexCoord2f(1, 0);       //I don't think 0, 0 is your centre from memory.
                                glVertex2f(width, 0);
                        glTexCoord2f(1, 1);
                                glVertex2f(width, height);
                        glTexCoord2f(0, 1);
                                glVertex2f(0, height);
                glEnd();
               
               
        }

Then get rid of the final glTranslatef in player.update() and add in another method in player to do this call. Then your display loop becomes:
int delta = getDelta();
                       
glClear(GL_COLOR_BUFFER_BIT);
                       
input();
player.update(delta);

glInitMatrix();

Player.player = Player.loadTexture("player_outline"); //Just noticed this? You're reloading a static texture each frame??????
player.render();

player.translateToPosition();

render();
                               

grid.generateWorld();
                       
Display.update();
Display.sync(60);


And fingers crossed that should work.

quew8

Also forgot to say: for the sake of the big man upstairs, get rid of all those casts to floats and ints. If you need so many, you're doing something wrong. Store them as the type you need them to be accessed as. Please, it doesn't help anyone, especially not you, which is tragic. Sorry but this is a bit of a pet hate. (One of many). Sometimes they're necessary, but I promise you, never in that volume.

ChaoticCactus

Yeah, I noticed that as I was casting something and realized what a huge pain in the butt it is.  But I have a question about the revision to the code.

in my while(!Display.isCloseRequested) loop I tried to call player.translateToPosition();  But it wont let me, as it says that it is undefined by the type entity which is the base for my player class.


Also, I can't find the glInitMatrix() method anywhere.  I even did some googling, but I couldn't find it.  Not sure what to do about that...

EDIT: Scratch that first part out, I figured it out.  But when I run it the Sky in the background is the only thing that moves when I press the arrow keys.  And the player sprite just stays in the center of the screen. 

quew8

Oh my god, I feel like a complete fool. It's not glInitMatrix, it's glLoadIdentity(). How the hell could I have made this mistake? They are nothing alike and there isn't any other api I use that has anything like InitMatrix. This wasn't even a single mistake I said the same name in a previous post. I'm am so sorry for wasting your time like that, all I can say is that it has been too long since I've used fixed function pipeline.

The player staying in the same pos is the intended result. Think of games like terraria (which has the same sort of gameplay as your's I believe) or any side scroller for that matter. Sure it appears like the player is moving but he never actually moves on your screen, it is in fact the scenery that moves around him, so this is how we render stuff in games (generally). The only other alternative (gameplay wise) is to have the player move around but the camera doesn't follow him, but then you don't actually have a camera or any kind of translation other than that of the player.

ChaoticCactus

Ah, that makes much more sense  ;).  However, what I meant was that all that moves is the sky.  The landscape itself doesn't move at all. 

Gah, I fell bad for making this such a big deal, I just would like to find an answer.  I'm not sure why it doesn't work either....  ???

quew8

That is intensely strange. Just to check, you do not do anything between drawing the sky and drawing the landscape? You don't in the pastebin so really, have you changed anything there? At the moment that is all I can think of. Unless it is translating and you are just not noticing (unlikely) in which case there would be something wrong with your terrain generation code. Again I think this is unlikely. Perhaps post the new code - you can leave out anything not related to rendering or matrix stuff. It just takes a while to scroll through.

Don't feel bad. It makes my day when I can actually help someone. And someday one of the people I have helped will become a billionaire and famous and I will be there at his front door demanding payment for services rendered.

ChaoticCactus

Ah, sorry it took so long to reply.  Anyway, here's all the necessary code.

http://pastebin.com/rSVGRvuD

I'm pretty sure that all of the necessary code is in there. 
Thanks again for your time!

quew8

OK, I see a problem. In your render() method in Block, you translate to the block's x, y position but then you don't translate back. So the next block gets translated relative to the previous block. Say you have 2 blocks. The first 1, x = 1 and the second one x = 2 (ie they are horizontally next to one another) You render the first one: you translate by 1 in the x so the block is drawn at 1. You render the second one: you translate by 2 in the x (So now you are at x = 3) so the block is drawn at 3. You see the problem? and it just gets worse and worse, until you call glLoadIdentity at start of the next frame.
So you have 3 options that I can think of:
1) Rather than translating to the position then drawing the block at the origin, just draw the block at its position (add the x and y position to each glVertex call)
2) Use glPushMatrix before the glTranslate and glPopMatrix after the rendering. I think I already explained what these are to you?
3) Translate back to the position it was at before the rendering. (Call glTranslate3f(-x, -y, 0) after the rendering).

I've put these in order of how I would rate them as methods. If you're going to move on up to using vbos at some point then definitely use option 1 as this will be your only viable option at that point. Now I'm not really sure how this problem could cause the terrain not to translate at all but one thing at a time.

On last thing; good work on getting rid of the casts (there's still one unnecessary one in translateToPlayer()) but now I've noticed another thing: try catches catching Exception and not doing anything about it. I won't say anything about catching Exception as you're still in debug but know it is considered very bad. But not doing anything about the exceptions is just horrific, if you are not going to actually solve the problem then at the least you should log or print the exception. (I tend to just exit the program while in debug) All you are doing at the moment is: seeing a burning building through your window then closing the blinds and forgetting about it completely. How do you know that the bug you are experiencing isn't to do with an exception that you have just hidden away? Perhaps an ArrayIndexOutOfBoundsException indicating you're drawing the wrong geometry. Sort it asap.

Edit: Sorry to rant.