I am new to LWJGL but am slowly learning. I was wanting to make a square that rotated when you pressed the key. Like d rotates it 90 degrees as you can tell below, but when I use glRotatef(); it gives me an error and I don't know why. There error tells me I need to create a method for it, I know I don't need to though. Anything helps!
public class MainPlayer {
private Draw draw;
private int rotation;
private float WIDTH = (float) (Display.getWidth() * 0.1);
private float HEIGHT = (float) (WIDTH / 2);
private float x = Display.getWidth() / 2 - WIDTH / 2;
private float y = Display.getHeight() / 2 - HEIGHT / 2;
public MainPlayer(){
draw = new Draw(1.0f, 1.0f, 1.0f, WIDTH, HEIGHT);
}
public void update(){
}
public void render(){
glTranslatef(x, y, 0);
glRotatef(rotation,0,0,1);
draw.render();
}
public void getInput(){
if(Keyboard.isKeyDown(Keyboard.KEY_W)){
rotation = 0;
}
if(Keyboard.isKeyDown(Keyboard.KEY_S)){
rotation = 180;
}
if(Keyboard.isKeyDown(Keyboard.KEY_A)){
rotation = 270;
}
if(Keyboard.isKeyDown(Keyboard.KEY_D)){
rotation = 90;
}
}
}
You create an int rotation and I assume your render() loops the whole time, and you only set rotation in getInput().
So I am assuming that you should declare it as int rotation = 0.
glRotatef() is a OpenGL call to rotate objects, just like glTranslatef() moves them. glRotatef() does it in the same way.
glRotatef(AngleOfRotationf, 0, 1, 0) would rotate it horisontally, like in this video i just made: http://www.youtube.com/watch?v=SHsssrj9qr8& uses that line to rotate a ship.
Also in that video i demonstrated moving it with glTranslatef().
To use it you must use GL11.glRotatef(), or import static org.lwjgl.opengl.GL11.*;
That probably means that you haven't statically imported glRotatef
Either use
GL11.glRotatef(rotation, 0, 0, 1);
or import it at the beginning of your program with
import static org.lwjgl.opengl.GL11.glRotatef
Related
I am creating a game in which there is a 10x10 map and I need to calculate the size of these squares so that they all fit on the screen.
rect_x_end, rect_y_end The size of the square by x and y
screen_x, screen_y Screen Size
len_map_x, len_map_y Map width and length = 10
I calculated the size of the square like this:
rect_x_end = screen_x / len_map_x
rect_y_end = screen_y / len_map_y
example:
64 = 640 / 10
48 = 480 / 10
In this example, everything works correctly, but as soon as I start resizing the screen, this method gives an incorrect result.
I was doing something similar to python (pygame) and everything worked there.
kucer0043.java
package com.kucer0043.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.utils.ScreenUtils;
public class kucer0043 extends ApplicationAdapter {
private ShapeRenderer shapeRenderer;
private int map_size;
#Override
public void create () {
shapeRenderer = new ShapeRenderer();
map_size = 10; // square map size
}
#Override
public void render () {
ScreenUtils.clear(0.5f, 0.5f, 0.5f, 1);
int rect_x_end = Gdx.graphics.getWidth() / map_size;
int rect_y_end = Gdx.graphics.getHeight() / map_size;
int map_x = Gdx.input.getX() / rect_x_end;
int map_y = Gdx.input.getY() / rect_y_end;
int x = map_x * rect_x_end;
int y = Gdx.graphics.getHeight() - (map_y + 1) * rect_y_end;
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(0f,1f,0f,0f);
shapeRenderer.rect(x,y, rect_x_end, rect_y_end);
shapeRenderer.end();
}
#Override
public void dispose () {
}
}
The projection matrix of your ShapeRenderer is calculated on initialization,you need to re-calculate it whenever the window changes size.
There are a few ways of achieving this, the simplest might be to just create a new ShapeRenderer when the window resizes:
#Override
public void resize(int width, int height) {
shapeRenderer = new ShapeRenderer();
}
I am creating a top-down shooter game, and whenever I move the camera, or zoom, black likes appear like a grid
I am using Tiled to create the map, and I have the camera following my centered box2d body. I have found that making the camera position equal the position of the box2d body with an int cast results in the black lines disappearing like this:
The problem though, is that because I have the game scaled down, the player will move for a second or two and then when the player reaches the next whole number on either axis, the camera snaps to the player, which is not what I want for the game as it's jarring. The player's movement is granular, but, while rounded, the camera's is not. I do not know if this is a problem with my tile sheet or if it's something I can fix by altering some code. I have tried all different kinds of combinations of padding, and values of spacing and margins. So ultimately, how can I have the camera match the player's position smoothly and not cause the black lines? I'd greatly appreciate any help or recommendations. Thank you in advance!
Where I am type casting the player's float position to an int in game class:
public void cameraUpdate(float delta) {
//timeStep = 60 times a second, velocity iterations = 6, position iterations = 2
world.step(1/60f, 6, 2); //tells game how many times per second for Box2d to make its calculations
cam.position.x = (int)playerOne.b2body.getPosition().x;
cam.position.y = (int)playerOne.b2body.getPosition().y;
cam.update();
}
Majority of player class:
public class PlayerOne extends Sprite implements Disposable{
public World world; // world player will live in
public Body b2body; //creates body for player
private BodyDef bdef = new BodyDef();
private float speed = 1f;
private boolean running;
TextureAtlas textureAtlas;
Sprite sprite;
TextureRegion textureRegion;
private Sound runningSound;
public PlayerOne(World world) {
this.world = world;
definePlayer();
textureAtlas = new TextureAtlas(Gdx.files.internal("sprites/TDPlayer.atlas"));
textureRegion = textureAtlas.findRegion("TDPlayer");
sprite =new Sprite(new Texture("sprites/TDPlayer.png"));
sprite.setOrigin((sprite.getWidth() / 2) / DunGun.PPM, (float) ((sprite.getHeight() / 2) / DunGun.PPM - .08));
runningSound = Gdx.audio.newSound(Gdx.files.internal("sound effects/running.mp3"));
}
public void definePlayer() {
//define player body
bdef.position.set(750 / DunGun.PPM, 400 / DunGun.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
//create body in the world
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(12 / DunGun.PPM);
fdef.shape = shape;
b2body.createFixture(fdef);
}
public void renderSprite(SpriteBatch batch) {
float posX = b2body.getPosition().x;
float posY = b2body.getPosition().y;
float posX2 = (float) (posX - .14);
float posY2 = (float) (posY - .1);
sprite.setSize(32 / DunGun.PPM, 32 / DunGun.PPM);
sprite.setPosition(posX2, posY2);
float mouseX = Level1.mouse_position.x; //grabs cam.unproject x vector value
float mouseY = Level1.mouse_position.y; //grabs cam.unproject y vector value
float angle = MathUtils.atan2(mouseY - getY(), mouseX - getX()) * MathUtils.radDeg; //find the distance between mouse and player
angle = angle - 90; //makes it a full 360 degrees
if (angle < 0) {
angle += 360 ;
}
float angle2 = MathUtils.atan2(mouseY - getY(), mouseX - getX()); //get distance between mouse and player in radians
b2body.setTransform(b2body.getPosition().x, b2body.getPosition().y, angle2); //sets the position of the body to the position of the body and implements rotation
sprite.setRotation(angle); //rotates sprite
sprite.draw(batch); //draws sprite
}
public void handleInput(float delta) {
setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2 + (5 / DunGun.PPM));
this.b2body.setLinearVelocity(0, 0);
if(Gdx.input.isKeyPressed(Input.Keys.W)){
this.b2body.setLinearVelocity(0f, speed);
}if(Gdx.input.isKeyPressed(Input.Keys.S)){
this.b2body.setLinearVelocity(0f, -speed);
}if(Gdx.input.isKeyPressed(Input.Keys.A)){
this.b2body.setLinearVelocity(-speed, 0f);
}if(Gdx.input.isKeyPressed(Input.Keys.D)){
this.b2body.setLinearVelocity(speed, 0f);
}if(Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.A)){
this.b2body.setLinearVelocity(-speed, speed);
}if(Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.D)){
this.b2body.setLinearVelocity(speed, speed);
}
if(Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.A)){
this.b2body.setLinearVelocity(-speed, -speed );
}if(Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.D)){
this.b2body.setLinearVelocity(speed, -speed);
}
Where I declare the pixels per meter scale:
public class DunGun extends Game{
public SpriteBatch batch;
//Virtual Screen size and Box2D Scale(Pixels Per Meter)
public static final int V_WIDTH = 1500;
public static final int V_HEIGHT = 800;
public static final float PPM = 100; //Pixels Per Meter
Game render and resize methods:
#Override
public void render(float delta) {
cameraUpdate(delta);
playerOne.handleInput(delta);
//clears screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
cam.zoom -= .01;
}
if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
cam.zoom += .01;
}
mapRenderer.render();
b2dr.render(world, cam.combined); //renders the Box2d world
mapRenderer.setView(cam);
//render our game map
//mapRenderer.render(); // renders map
//mapRenderer.render(layerBackround); //renders layer in Tiled that p1 covers
game.batch.setProjectionMatrix(cam.combined); //keeps player sprite from doing weird out of sync movement
mouse_position.set(Gdx.input.getX(), Gdx.input.getY(), 0);
cam.unproject(mouse_position); //gets mouse coordinates within viewport
game.batch.begin(); //starts sprite spriteBatch
playerOne.renderSprite(game.batch);
game.batch.end(); //starts sprite spriteBatch
//mapRenderer.render(layerAfterBackground); //renders layer of Tiled that hides p1
}
#Override
public void resize(int width, int height) {
viewport.update(width, height, true); //updates the viewport camera
}
I solved it by fiddling around with the padding of the tilesets in GDX Texture Packer. I added 5 pixels of padding around the 32x32 tiles. I set the margins to 2, and spacing to 4 in Tiled. I had tried a lot of different combinations of padding/spacing/margins that didn't work which made me think it was a coding problem, but those settings worked, and I didn't have to round the floats.
I am making a game in Libgdx, in which I want to fall a ball from up word to down word and move background towards up word and update camera according to it. My code is given below...
public WorldRenderer(SpriteBatch spriteBatch, World world){
this.world = world;
this.camera = new OrthographicCamera(FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
this.camera.position.set(FRUSTUM_WIDTH/2, FRUSTUM_HEIGHT/2, 0);
this.spriteBatch = spriteBatch;
positionBGY1 = 0;
positionBGY2 = 0;
}
public void render(World world, float deltaTime){
if(world.ball.position.y > - camera.position.y){
camera.position.y = world.ball.position.y;
}
if(camera.position.y<0)
camera.position.y=world.ball.position.y;
camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
renderBackground();
renderObjects(world, deltaTime);
}
private void calculateBGPosition(){
positionBGY2 = positionBGY1 + (int)FRUSTUM_HEIGHT;
if(camera.position.y >= positionBGY2){
positionBGY1 = positionBGY2;
}
}
private void renderBackground() {
spriteBatch.disableBlending();
spriteBatch.begin();
spriteBatch.draw(Assets.gamebackgroundRegion, camera.position.x - FRUSTUM_WIDTH / 2, positionBGY1 - FRUSTUM_HEIGHT / 2, FRUSTUM_WIDTH, 1.5f * FRUSTUM_HEIGHT);
spriteBatch.draw(Assets.gamebackgroundRegion2, camera.position.x - FRUSTUM_WIDTH / 2, positionBGY2 - FRUSTUM_HEIGHT / 2, FRUSTUM_WIDTH, 1.5f * FRUSTUM_HEIGHT);
calculateBGPosition();
spriteBatch.end();
}
Problem with my code is background screen is not moving and camera is not updated with ball movement and ball fall down out of screen.
Well, first thing you need to do is change one of the bg variables, so in render somehwere do something like:
float speed = 1;
positionBGY1+=deltaTime*speed;
positionBGY2+=deltaTime*speed;
As far as the camera moving with the ball I would just do this:
camera.position.y = Math.min(ball.y,0);
And I would in turn omit all of this:
if(world.ball.position.y > - camera.position.y){
camera.position.y = world.ball.position.y;
}
if(camera.position.y<0)
camera.position.y=world.ball.position.y;
Best way to achieve this is using ParrallaxLayer and ParrallaxBackground classes
it optimised the background operation so that u dont have to worry about the performance
I have a simple game animation made in java. It is of three planets rotating around an axis. Each planet is an instance of the class Planet and they have an update method which, every time it is run, the orbit's rotation angle increases and the position is updated acording to the angle and a few predetermined variables like distance from the "sun". From here, you can determine the position of the planet with simple trigonometry. In this case:
Sin(angle) = op/hyp = y/distance
therefore
Sin(angle)*hyp = op
Cos(angle) = ady/hyp = x/distance
therefore
Cos(angle)*hyp = ady
where the hypothenuse is the distance to the sun and the adyacent and oposite sides are the x and y values respectively. I figured this would work, until I tried it out. It gave me an eliptical rotation. Here is the code that updates the planet's rotation (orbit center is the sun's center position):
position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x);
position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y);
What could be wrong?
EDIT:
I realized this problem by placing an object with its center in the position specified by orbit center
Here is the full code of the planet class:
public class Planet
{
protected Image image;
protected Vector2 position;
protected final Vector2 orbitCenter;
protected float rotation;
protected Vector2 imageSize;
protected final float rotationSpeed;
protected final float orbitDistance;
protected float orbitAngle;
protected final float orbitAngleSpeed;
public Planet(Image image, float orbitDistance, float rotationSpeed, Vector2 orbitCenter, float orbitAngleSpeed)
{
this.image = image;
this.position = new Vector2(orbitCenter.x, orbitCenter.y - orbitDistance);
this.orbitCenter = orbitCenter;
this.rotation = 0;
this.imageSize = new Vector2(image.getWidth(null), image.getHeight(null));
this.rotationSpeed = rotationSpeed;
this.orbitDistance = orbitDistance;
this.isMouseOver = false;
this.isPressed = false;
this.orbitAngle = 0;
this.orbitAngleSpeed = orbitAngleSpeed;
}
public void Update()
{
orbitAngle += orbitAngleSpeed;
if(orbitAngle > Math.PI * 2)
orbitAngle %= Math.PI * 2;
position.x = ((Math.cos(orbitAngle) * orbitDistance) + orbitCenter.x);
position.y = ((Math.sin(orbitAngle) * orbitDistance) + orbitCenter.y);
}
public void Draw(Graphics2D g)
{
g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
g.drawImage(image, (int)position.x, (int)position.y, null);
g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
}
}
Here is the class that tests the planet class. You can download the jar it needs to work from here: foxtailgames.net/AppletSource.jar. Here is the tester class (you will probably have to import a few things though if you do it in eclipse or netbeans it will give you the imports):
public class PlanetTest extends AppletCore
{
public void resizeScreen() {resize(800, 800);}
Image center;
Planet p;
public void LoadContent()
{
p = new Planet(loadImage("images/GameMenuCircles/Planet1.png"), 100f, 0.02f, new Vector2(400, 400), 0.005f);
center = loadImage("images/GameMenuCircles/Center.png");
}
public void Update(GameTime gameTime)
{
p.Update();
}
public void Draw(Graphics2D g, GameTime gameTime)
{
g.drawImage(center, 400 - center.getWidth(null)/2, 400 - center.getWidth(null)/2, null);
p.Draw(g);
g.setColor(Color.green);
g.drawLine(400, 400, 500, 400);
g.drawLine(400, 400, 400, 500);
g.drawLine(400, 400, 300, 400);
g.drawLine(400, 400, 400, 300);
g.setColor(Color.white);
}
}
Your rotation is set to 0 in the above so i assume you are not rotating the picture at the moment. What i think is happening is the orbit circle you are producing is fine, but the location you are drawing the planet is off.
Below is an image of how Swing would draw the circle, so the overlap you experience is because of this.
You need to adjust the position you draw the circle by how half the width so it sits over the center of the orbit.
EDIT: You've alter some code but what you need to change is the draw method of he planet:
public void Draw(Graphics2D g) {
g.rotate(rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
g.drawImage(image, (int)position.x, (int)position.y, null); //here
g.rotate(-rotation, position.x + imageSize.x / 2, position.y + imageSize.y / 2);
}
This line needs to be:
g.drawImage(image, (int)position.x - imageSize.width, (int)position.y - imageSizee.height, null); //here
You might compare your result to this AnimationTest that uses the same parametric equation of a circle. Because the orbital radius is a function of the enclosing panel's dimensions, the orbit is circular only when w equals h. Resize the frame, or set HIGH = WIDE, to see the effect.
I have the following Java class I've written for a LibGdx OpenGL project.
The camera keeps the aspect ratio of the screen no matter how you resize it by letterboxing either the top and bottom, or the sides. So far, so good.
The issue comes when I try to obtain the mouse x, y coordinates of a click, and the letterbox is involved for that axis.
First here is the class:
public class Camera {
private static float viewportWidth;
private static float viewportHeight;
private static float aspectRatio;
private static float barSize;
/**
* Creates an orthographic camera where the "play area" has the given viewport size. The viewport will be scaled to maintain the aspect ratio.
*
* #param virtualWidth the width of the game screen in virtual pixels.
* #param virtualHeight the height of the game screen in virtual pixels.
* #return the new camera.
*
*/
public static OrthographicCamera createCamera(float virtualWidth, float virtualHeight) {
aspectRatio = virtualWidth / virtualHeight;
float physicalWidth = Gdx.graphics.getWidth();
float physicalHeight = Gdx.graphics.getHeight();
if (physicalWidth / physicalHeight >= aspectRatio) {
// Letterbox left and right.
viewportHeight = virtualHeight;
viewportWidth = viewportHeight * physicalWidth / physicalHeight;
barSize = ????;
}
else {
// Letterbox above and below.
viewportWidth = virtualWidth;
viewportHeight = viewportWidth * physicalHeight / physicalWidth;
barSize = ????;
}
OrthographicCamera cam = new OrthographicCamera(viewportWidth , viewportHeight);
cam.position.set(virtualWidth / 2, virtualHeight / 2, 0);
cam.rotate(180, 1, 0, 0);
cam.update();
Gdx.app.log("BTLog", "barSize:"+barSize);
return cam;
}
public static float getViewportWidth() {
return viewportWidth;
}
public static float getViewportHeight() {
return viewportHeight;
}
}
LibGdx supplies me the x and y coordinates when an even happens, and I need to translate these raw coordinates into the scale of my camera (the virtual height and width).
When the screen is stretched (no letterboxing at all), it's pretty easy to obtain the x and y coordinates by using:
xRelative = (int) (x / (float)Gdx.graphics.getWidth() * Camera.getViewportWidth());
yRelative = (int) (y / (float)Gdx.graphics.getHeight() * Camera.getViewportHeight());
The problem is when the letterboxes come into play, it throws off the coordinate for that axis. I know I need to take into account the width of the letterboxing, but i'm having a hell of a time figuring how to calculate it.
Above where I have "barSize = ????;" my first instinct was to do this:
barSize = physicalHeight - viewportHeight; // to use height for example
Once I get the barSize, i'm fairly sure I can use this to get the right numbers (using the y axis for example):
yRelative = (int) (y / (float)Gdx.graphics.getHeight() * Camera.getViewportHeight() - Camera.getBarSize());
But the numbers don't match up. Any suggestions would be a really appreciated!
Ray ray = camera.getPickRay(x, y);
System.out.println(ray.origin.x);
System.out.println(ray.origin.y);