I develop 2D game using libGDX and box2D. Camera is following with body.I want to scroll background (png 3200X48) too. Now the camera works fine in box2D world but background is not moving. I searched and tried many solutions but didn't help. What is the best solution for it? Maybe makes two cameras one for physics world and second for libgdx scene? Has someone got the similar problem? Thanks for help.
Here are a parts of my code
float w = 320;
float h = 480;
#Override
public void show() {
camera = new OrthographicCamera();
camera.setToOrtho(false, w/2, h/2);
world = new World(new Vector2(0, -20), true);
box2DDebugRenderer = new Box2DDebugRenderer();
background = new Texture(Gdx.files.internal("gfx/forklift/background.png"));
bg = new Sprite(background);
......}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
moveCamera(dynamicBody.getPosition().x);
moveBody();
batch.begin();
batch.draw(background, 0, 0, 3200, 480);
batch.end();
Gdx.app.log("", ""+dynamicBody.getPosition());
world.step(1/60f, 6, 2);
box2DDebugRenderer.render(world, camera.combined);}
public void moveCamera(float x){
camera.position.set(x, dynamicBody.getPosition().y, 0);
camera.update();
}
#Override
public void resize(int w, int h) {
camera = new OrthographicCamera(w, h);
camera.translate(h/2, w/2, 0);
super.resize(w, h);
}
use batch.setProjectionmatrix(camera.combined)
before batch.begin()
Related
Hi i'm new to programming, and while i was trying to do an exercise this error poped up, and i have no idea what it means and how to fix it.
it's an example in the processing.js library that after i tried to copy didn't go so well.
Mover mover;
void setup(){
size (600,600);
mover = new Mover();
}
void draw(){
mover.update();
mover.display();
mover.checkEdges();
}
class Mover {
// position, velocity, and acceleration
PVector position;
PVector velocity;
PVector acceleration;
// Mass is tied to size
float mass;
Mover(float m, float x, float y) { //<<<the error occurs here
mass = m;
position = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}
// Newton's 2nd law: F = M * A
// or A = F / M
void applyForce(PVector force) {
// Divide by mass
PVector f = PVector.div(force, mass);
// Accumulate all forces in acceleration
acceleration.add(f);
}
void update() {
// Velocity changes according to acceleration
velocity.add(acceleration);
// position changes by velocity
position.add(velocity);
// We must clear acceleration each frame
acceleration.mult(0);
}
// Draw Mover
void display() {
stroke(255);
strokeWeight(2);
fill(255, 200);
ellipse(position.x, position.y, mass*16, mass*16);
}
// Bounce off bottom of window
void checkEdges() {
if (position.y > height) {
velocity.y *= -0.9; // A little dampening when hitting the bottom
position.y = height;
}
}
}
The only problem I see in your code is that your Mover constructor takes three arguments, but you're not giving it any in this line:
mover = new Mover();
So I'd fix that error before anything else. If you're still having problems, please be much more specific about exactly how you're compiling and running this code. Are you using the Processing editor? Which version? During exactly which step do you get an error?
The following is the code for my widget which subclasses QOpenGLWidget. What should be happening is that the framebuffer object flashes between white and black between each frame, but it only displays white, which tells me it's rendering once and then never updating.
void GLWidget::paintEvent(QPaintEvent *event)
{
QRect sourceRect(0, 0, 320, 240);
QSize sourceSize = sourceRect.size();
QOpenGLFramebufferObject sourceBuffer(sourceSize);
sourceBuffer.bind();
QOpenGLPaintDevice device(sourceSize);
QPainter sourcePainter;
sourcePainter.begin(&device);
static bool flash = true;
if (flash)
{
sourcePainter.fillRect(sourceRect, QBrush(Qt::white));
}
else
{
sourcePainter.fillRect(sourceRect, QBrush(Qt::black));
}
flash = !flash;
sourcePainter.end();
sourceBuffer.release();
QPainter destinationPainter;
destinationPainter.begin(this);
destinationPainter.setRenderHint(QPainter::Antialiasing);
destinationPainter.fillRect(event->rect(), QBrush(Qt::black));
int destinationWidth = event->rect().width();
int destinationHeight = event->rect().height();
QImage sourceImage = sourceBuffer.toImage();
//sourceImage.save(&process, "bmp");
QImage scaledSourceImage = sourceImage.scaled(destinationWidth, destinationHeight, Qt::KeepAspectRatio);
int translationX = destinationWidth - scaledSourceImage.width();
int translationY = destinationHeight - scaledSourceImage.height();
destinationPainter.translate(translationX / 2, translationY / 2);
destinationPainter.drawImage(0, 0, scaledSourceImage);
destinationPainter.end();
}
Am I using the framebuffer object correctly here? Also is there a more appropriate way to draw something offscreen and then display it in a QOpenGLWidget?
I have recently started up a 3d first person shooter game in Monogame and I am having some issues with the camera controls, I am unable to figure out how I make the camera slowly turn on it's X axis when I hold down the left/right arrow keys.
At the minute, the code I have is as follows:
Matrix view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(0, 0, 0), Vector3.UnitZ);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 600f, 0.1f, 100f);
And then down in the update section I have this:
if (kb.IsKeyDown(Keys.Left))
{
view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(-2, -2, -2), Vector3.UnitZ);
}
The issue is at the minute this code simply moves the camera to the side a little then stops. I am unsure on how to keep having it move until I let go of the key?
The entire of my code will be shown below incase I forgot something (the floor verts currently don't work and the names related to a ship is due to me working from a tutorial):
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Game1
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Model model;
Vector3 ship1Location = new Vector3(40, 0, 0);
Vector3 ship2Location = new Vector3(20, 0, 0);
Matrix view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(0, 0, 0), Vector3.UnitZ);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 600f, 0.1f, 100f);
VertexPositionTexture[] floorVerts;
BasicEffect effect;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
floorVerts = new VertexPositionTexture[6];
floorVerts[0].Position = new Vector3(-20, -20, 0);
floorVerts[1].Position = new Vector3(-20, 20, 0);
floorVerts[2].Position = new Vector3(20, -20, 0);
floorVerts[3].Position = floorVerts[1].Position;
floorVerts[4].Position = new Vector3(20, 20, 0);
floorVerts[5].Position = floorVerts[2].Position;
effect = new BasicEffect(graphics.GraphicsDevice);
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
model = Content.Load<Model>("health2");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
Matrix ship1WorldMatrix = Matrix.CreateTranslation(ship1Location);
Matrix ship2WorldMatrix = Matrix.CreateTranslation(ship2Location);
if (IsCollision(model, ship1WorldMatrix, model, ship2WorldMatrix))
{
ship1Location = new Vector3(0, -20, 0);
}
KeyboardState kb = Keyboard.GetState();
if (kb.IsKeyDown(Keys.A))
{
ship1Location += new Vector3(-0.1f, 0, 0);
}
if (kb.IsKeyDown(Keys.Left))
{
view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(-2, -2, -2), Vector3.UnitZ);
}
ship2Location += new Vector3(0, 0, 0);
base.Update(gameTime);
}
private bool IsCollision(Model model1, Matrix world1, Model model2, Matrix world2)
{
for (int meshIndex1 = 0; meshIndex1 < model1.Meshes.Count; meshIndex1++)
{
BoundingSphere sphere1 = model1.Meshes[meshIndex1].BoundingSphere;
sphere1 = sphere1.Transform(world1);
for (int meshIndex2 = 0; meshIndex2 < model2.Meshes.Count; meshIndex2++)
{
BoundingSphere sphere2 = model2.Meshes[meshIndex2].BoundingSphere;
sphere2 = sphere2.Transform(world2);
if (sphere1.Intersects(sphere2))
return true;
}
}
return false;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
DrawGround();
Matrix ship1WorldMatrix = Matrix.CreateTranslation(ship1Location);
Matrix ship2WorldMatrix = Matrix.CreateTranslation(ship2Location);
DrawModel(model, ship1WorldMatrix, view, projection);
DrawModel(model, ship2WorldMatrix, view, projection);
base.Draw(gameTime);
}
void DrawGround()
{
// The assignment of effect.View and effect.Projection
// are nearly identical to the code in the Model drawing code.
float aspectRatio =
graphics.PreferredBackBufferWidth / (float)graphics.PreferredBackBufferHeight;
float fieldOfView = Microsoft.Xna.Framework.MathHelper.PiOver4;
float nearClipPlane = 1;
float farClipPlane = 200;
effect.Projection = Matrix.CreatePerspectiveFieldOfView(
fieldOfView, aspectRatio, nearClipPlane, farClipPlane);
foreach (var pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
graphics.GraphicsDevice.DrawUserPrimitives(
// We’ll be rendering two trinalges
PrimitiveType.TriangleList,
// The array of verts that we want to render
floorVerts,
// The offset, which is 0 since we want to start
// at the beginning of the floorVerts array
0,
// The number of triangles to draw
2);
}
}
private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.AmbientLightColor = new Vector3(2f, 0, 0);
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
}
}
Since the camera's position and the point it is looking at are necessary parameters to create a view matrix, you can simply rotate (think orbit) the LookAt camLookAt around the camPosition like this:
//declare class scope variables
Vector3 camPosition = new Vector3(60, 20, 10);//your starting camera position
Vector3 camLookAt = Vector3.Zero;//your starting camera focus point (look at)
Vector2 camUp = Vector3.Up;
float camYawRate = 0.004f;//set to taste
//in the Update method
float elapsed = gameTime.ElapsedGameTime.TotalSeconds;
//later in the method...
if (kb.IsKeyDown(Keys.Left))
{
camLookAt = Vector3.Transform(camLookAt - camPosition,Matrix.CreateRotationY(-camYawRate * elapsedTime)) + camPosition;);//remove the - sign from camYawRate to rotate to the right (or vice versa)
view = Matrix.CreateLookAt(camPosition, camLookAt, camUp);
}
And that's it, give it a shot. Add another similar block to rotate to the right.
I am just trying to add a click listener to the stage in libgdx but it is not working here is my code;
stage.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("CLICK", "LISTENER");
parallaxBackground.reverse();
return super.touchDown(event, x, y, pointer, button);
}
});
This is from my main game screen, which inherits from an abstract screen which calls,
Gdx.input.setInputProcessor(stage);
In the abstract class I also call,
stage.act(delta);
I am most definetely calling super.render() as well from the child class
What is causing this!
EDIT
I don't know if it matters but my stage has no actors but I just want to simply acknowledge a click.
Since you added no actors to your stage, your stage has no substance so it cannot be touched.
You can add create an actor that is the same size as the screen and is aligned with the screen to do what you're trying. Something like this (untested):
Actor screenActor = new Actor(){
public void act (float delta) {
super.act(delta);
Viewport viewport = getStage().getViewport();
width = viewport.getScreenWidth();
height = viewport.getScreenHeight();
x = viewport.getScreenX();
y = viewport.getScreenY();
}
};
stage.addActor(screenActor);
You would add this actor first, so other actors get first crack at intercepting touches, and this is the fallback.
Here is how I solved this problem:
In Photoshop I created a 100x100px image and put only one layer in it and set the opacity of that layer to 1%, I also removed the background (This made a totally transparent image) and saved it as .png to use it as texture.
I created an Actor and called it BgActor and drew the texture to it.
Here is the png image that I created
and here is how my Actor looks like:
The BgActor class:
public class BgActor extends Actor {
private float x, y, width, height;
private Texture texture = new Texture(Gdx.files.internal("images/transparent-bg.png"));
public BgActor(float x, float y, float width, float height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
setTouchable(Touchable.enabled);
}
#Override
public void draw(Batch batch, float parentAlpha) {
setBounds(x, y, width, height);
batch.draw(texture, x, y, width, height);
}
public void dispose() {
texture.dispose();
}
}
Implementation (I used your Listener):
BgActor bgActor = new BgActor(0, 0, stage.getWidth(), stage.getHeight);
bgActor.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("CLICK", "LISTENER");
parallaxBackground.reverse();
return super.touchDown(event, x, y, pointer, button);
}
});
......
stage.addActor(bgActor);
And don't forget to dispose the bgActor in your Screen's hide() method.
Good luck ..
Hi im trying to get a sprite to fade in and scale up after fading out and scaling down. For this i used an Entitiy modifier listener but its not working? Heres my code:
public class GameScene {
Scene gameScene;
Engine engine;
Activity activity;
BitmapTextureAtlas mTextureAtlas;
ITextureRegion X;
ITextureRegion O;
ITextureRegion XO;
FadeInModifier fadeIn = new FadeInModifier(2);
FadeOutModifier fadeOut = new FadeOutModifier(2);
ScaleModifier scaleDown = new ScaleModifier(3, 1, 0);
ScaleModifier scaleUp = new ScaleModifier(2, 0, 1);
Sprite XOsprite;
Random rand = new Random();
boolean XYset = false;
public GameScene(Engine eng, Activity act) {
engine = eng;
activity = act;
}
public Scene getScene() {
gameScene = new Scene();
gameScene.setBackground(new Background(0, 256, 59));
int x = 0, y = 0;
if (rand.nextInt(2) == 0) {
XO = X;
} else {
XO = O;
}
if (!XYset) {
x = rand.nextInt(MainActivity.CAM_WIDTH);
y = rand.nextInt(MainActivity.CAM_HEIGHT);
XYset = true;
}
XOsprite = new Sprite(x, y, XO, engine.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent te, final float xVal,
final float yVal) {
XOsprite.registerEntityModifier(fadeOut);
XOsprite.registerEntityModifier(scaleDown);
return true;
}
};
IEntityModifierListener fadeOutListener = new IEntityModifierListener() {
#Override
public void onModifierStarted(IModifier<IEntity> pModifier,
IEntity pItem) {
// TODO Auto-generated method stub
}
#Override
public void onModifierFinished(IModifier<IEntity> pModifier,
IEntity pItem) {
// TODO Auto-generated method stub
XOsprite.clearEntityModifiers();
XOsprite.setPosition(rand.nextInt(MainActivity.CAM_WIDTH), rand.nextInt(MainActivity.CAM_HEIGHT));
XOsprite.registerEntityModifier(fadeIn);
XOsprite.registerEntityModifier(scaleUp);
}
};
fadeOut.addModifierListener(fadeOutListener);
XOsprite.registerEntityModifier(scaleUp);
XOsprite.registerEntityModifier(fadeIn);
gameScene.attachChild(XOsprite);
gameScene.registerTouchArea(XOsprite);
return gameScene;
}
The sprite just fades out and nothing happens. I also want the sprite to change to a random position on the screen when it fades back in. Help?
If you want to do fade in and scale in parallel then you can use use parallelEntityModifier.
Similarly for fade out and scale out parallel then you can use use parallelEntityModifier.
To run these two in sequence use SequenceEntityModifier.
Try this it will work.