Alright so this is going to be a doozy to explain. I'm making a very basic "pseudo-3d" racing game for Android using AndEngine (and in turn, openGL - I think). I don't believe using AndEngine really has anything to do with this problem though, because I'm directly accessing openGL functions to accomplish my drawing.
Anyways, I copy-pasta'd some code that allowed the normally 2d AndEngine to have a 3d perspective (tutorial for such can be found here. This works pretty well, and I also don't believe this has much to do with my problem, but I don't fully understand openGL so it's a little hard for me to say. Here's the code from the onLoadEngine (called when app starts) that sets up the camera with a 3d perspective:
this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT) {
//other methods...
private void setFrustum(GL10 pGL) {
// set field of view to 60 degrees
float fov_degrees = 60;
float fov_radians = fov_degrees / 180 * (float)Math.PI;
// set aspect ratio and distance of the screen
float aspect = this.getWidth() / (this.getHeight());
float camZ = this.getHeight()/2 / (float)Math.tan(fov_radians/2);
// set projection
GLHelper.setProjectionIdentityMatrix(pGL);
GLU.gluPerspective(pGL, fov_degrees, aspect, camZ/10, camZ*10);
// set view
GLU.gluLookAt(pGL, 0,120f, camZ, 0, 0, 0f, 0, 1, 0); // move camera back+up
pGL.glScalef(1,-1,1); // reverse y-axis
pGL.glTranslatef(-CAMERA_WIDTH/2,-CAMERA_HEIGHT/2,0); // origin at top left
}
};
Then later in the onLoadScene (where the drawing takes place), I draw a bunch of my images like so:
for (int n=0;n<=100;n++) {
final int k = n;
final Sprite line = new Sprite(0, 0,CAMERA_WIDTH,16f, [AndEngine texture holding road img]) {
#Override
protected void applyTranslation(GL10 pGL) {
pGL.glTranslatef(this.mX, 120f, 15f*k); //16*k causes a sliver of a space between each segment
pGL.glRotatef(90f, 1, 0, 0); //**MAY BE MY ISSUE**
}
};
scene.attachChild(line); //actually draws the image to the screen
}
Which works pretty darn well as well, except for one thing! It distorts the shit out of my images. The images are simple pngs, both matching the CAMERA_WIDTH, and both looking similar to this:
And when I draw it without the rotate line, I get this:
Which has a decently straight middle line (tbh I'd be happy with them this way), but then you can see the edges of the road are all facing basically the exact opposite way they should be facing. I figured why not just flip them? I thought I would have to rotate them 180 degrees around the x axis, but instead that just makes them disappear, and instead I found that 90 degrees works (???). Anyways, Here's what I get:
So yeah. Here's where my problem lies - the middle lane divider is distorted as crap!! The lines marking the edge of the road line up wonderfully, but for whatever reason its really messing with that middle line. I get most of the math behind the 3d, but I really don't know what to make of this...it's almost like the image is being compressed because its being viewed at such a sharp angle, but I don't really know how the hell I could solve that without simply making it a top-down view? :S
Anyways... any ideas or guidance is welcome. Sorry this is such a long and convoluted post - it makes it hard when I really have no idea where the problem lies.
Also - It might be worth noting I have little to no experience with openGL or 3d graphics, and have even less interest in learning much about them in depth. I need a band-aid to this problem!
Ok so I found the solution! Turns out there is this little issue called Perspective Correct Texturing, that is basically just a flag that needs to be turned on in OpenGL to make it not skew images when they are being drawn with perspective.
Inside my Camera initializing code, I added this line to the method setFrustum(GL10 pGL):
pGL.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
That this essentially solved the problem. Lines are as straight as ever now :) I found this out on another stackoverflow post where this answer actually wasn't what the asker wanted, but it just so happened to work for me :D The thread that led me to the answer can be found here.
Related
I'm creating a 2d game using the Java version of Box2d.
I know that the engine is generally paired with a separate library to handle animation, but I'm looking for something simple, with a more rustic feel, so I'm considering handling the animation from scratch.
The animation I am trying to create is something for the collision of two objects.
I'm using openGl to handle the graphics, and I pretty much have everything set up with the fps and rendering, it's just a matter of tweaking the frames to make it look smooth.
I tried bliting images of some things that I drew myself and it looked atrocious. I think the main problem is that the animation frame images are not linked to the physics forces and so they don't blend well.
What I want to try next is a sort 'spark effect' using a small number of pixels that sort of resemble 'dust' exploding off of the colliding images. If you've ever played dxball, you may recall a similar effect when the ball collided with the paddle at high speed.
As you can see in the above image, the principles are fairly simple. I figure by creating a set of small bodies with fixtures, I can use the box2d engine to produce this effect. I already have code that grabs the point of collision for all bodies, and am familiar enough with parabolic functions that I pretty sure I can create the force direction.
I'm just not sure if there is a better way of doing this, or how to apply a polynomial function to a body like in the image.
Does anybody know how to achieve this functionality with box2d? Any built in methods or documentation that would be helpful?
As a point of reference, the following snippet of code demonstrates the drawing of a small, red box on all of the collision points.
for(Vec2 point : listener.worldmanifold.points){
glPushMatrix();
newpos = point.mul(30);
glTranslatef(newpos.x, newpos.y, 0);
glColor3f(1,0,0);
glRectf(-2, -2, 2, 2);
glPopMatrix();
}
im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.
In the two attached pictures, the desktop screenshot of libgdx functions as expected. The screenshot from my Galaxy Nexus is unfortunately not as expected. I am attempting to create a simple motion blur or trail effect.
Rendering as I expected on my desktop.
Not rendering as I expected on my Galaxy nexus.
The circle textures are drawn in a for loop during rendering and the effect is achieved with a pixmap using the RGBA of 0, 0, 0, 0.1f that is drawn before the circles.
screenClearSprite creation
Pixmap screenClearPixmap = new Pixmap(256, 256, Format.RGBA8888);
screenClearPixmap.setColor(Color.rgba8888(0, 0, 0, 0.1f));
screenClearPixmap.fillRectangle(0, 0, 256, 256);
screenClearTexture = new Texture(screenClearPixmap);
screenClearSprite = new Sprite(screenClearTexture);
screenClearSprite.setSize(screenWidth, screenHeight);
screenClearPixmap.dispose();
Render
batch.begin();
font.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 0, 20);
screenClearSprite.draw(batch);
for (int i = 0; i < circleBodies.size(); i++) {
tempPos = circleBodies.get(i).getPosition();
batch.draw(circleTexture, (tempPos.x * SCALE) + screenWidthHalf
- circleSizeHalf, (tempPos.y * SCALE) + screenHeightHalf
- circleSizeHalf);
}
batch.end();
So, what did I do wrong? Perhaps there is a better way to get the 'motion blur' effect of movement?
Here is a different approach, where you clear your screen each time with solid color and no alpha.
This means that you will have to modify your code some. The good thing about this, is that the way you are doing it has some flaws: It will blur everything in motion, not just the balls. And can quickly produce ugly results/artefacts unless you are careful.
Do the same as you are doing now, but instead of drawing the balls to the batch, draw them onto a texture/bitmap/whatever. Then each frame add an alpha-blended image over the balls-image, and then draw the balls in their current position on top of that. Then add that image to your screen. Very much like you are doing now, except you draw to something else and keep it. This way you don't have to rely on the viewport you are drawing onto, and can keep everything separated.
This method is similar to drawing to an accumulation buffer.
Instead of doing it the way you are doing, you can keep track of the n latest positions of each ball. And then draw all of them each frame, with different alpha. This is very easy to implement. Can result in many drawing calls if you have many balls or a large n, but if it's not too much it shouldn't limit your fps and gives nice control.
Perhaps there is a better way to get the 'motion blur' effect of
movement?
in order to make motion blur in my game i use another approch "The particle effect" it works realy fine with me and i didn't have Android/Desktop problems or with different android devices
all you have to do is to use "Particle Effect Editor" of Libgdx and make your effect then load it in your project finally draw it at the same position you draw your object (and alos draw your object)
Tips to make the right effect file with Paticle Editor :
set (use) the same image of the object that you want to blur it motion in the particle effect
try to limit the count : the max number of particle allowed
Disable the "velocity" and "Angle"
parameter
Particle effect help to do motion effect
Hope this will help someone !
So I am creating a simple 3d render engine in the LWJGL, and I am having issues with the fact that when I back up from an object, it travels to the left and upwards (towards 0,0) when I really need it to travel to screenResX/2,screenResY/2 (maybe 0 I dont know). Is there a way that I can set some kind of variable that will let it fade towards the center?
Additionally, In this engine, I need to bend the polygons to render as if the player was looking at them. At the moment, I only have polygons rendering if you are looking straight at them, and I know that that's not what is needed, can anyone help me?
Thanks in advance for your help, this is my first 3d engine and I'm pretty clueless.
So for the first question: Scaling always takes place around the origin. Meaning that you have to translate your object to the origin, scale it and then translate it to its destination. This is better explained here: OpenGL: scale then translate? and how?
But the basics are something like this (from the linked question):
//this moves the scaled
glTranslatef(destCenter.x, destCenter.y, 0.0);
//scale to the desired factor
glScalef(scaleX, scaleY, 0.0);
//move the center of the scaling operation into the origin
glTranslatef(sourceCenter.x * -1.0, sourceCenter.y * -1.0, 0.0);
I still don't quite understand your second question, but I am guessing that you mean that you want something to be drawn in perspective rather than in an orthogonal fashion. Have a look at gluPerspective(...) or glFrustum(...) instead of glOrtho(...).
I'm kind of new to JOGL, and I am working on a game. I have a rocket, stars in the background, and planets. I want the rocket to remain stationary at the bottom of the screen, the GO button to be pressed, and then planets start coming down for the rocket to avoid.
I keep ending up with hitting go, the planets coming down (via translation), and the rocket also going down. I know Why this is happened with the camera moving, so the whole world is moving. I've been trying to use the pushMatrix and popMatrix, but haven't had any luck.
i.e.
if (goButtonPressed)
{
//gl.glTranslatef(0.0f,0.3f,0f); // this line just keeps the whole thing still
drawRocket(gl); // I was trying to 'undo' the translation
gl.glPushMatrix();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glTranslatef(0.0f, -0.3f, 0f);
gl.glPopMatrix();
}
Is what I am trying to do possible in opengl? Am I making it too difficult?
Instead of relying on the projection matrix to hold the state of your rockets' positions, how about storing this information in your own code and then passing absolute coordinates to JOGL? Then updating the position of an object can be done with a more obvious bit of code like rocket.y += dy;.
As a small aside, the projection matrix is not intended to be used for spatial transformations. Use GL_MODELVIEW instead to avoid subtle problems down the road.
Not exactly an answer to your question, but you should look at JMonkeyEngine if you want to make a game with opengl in Java.
http://jmonkeyengine.com/
The thing you are trying to do is certainly possible with opengl and fairly easy to do with JMonkeyEngine. They have plenty of tutorials and such on their site.