I have my Box2D project almost completely done, however, when I try the first obstacle to appear randomly and repeat itself infinitely using the while loop, the while loop doesn't work and instead it just appears once, I would like my game to appear like this as shown in this video, "https://www.youtube.com/watch?v=X-jEZHDN-gw"The while loop is not working, what am I doing wrong? could somebody please help me?
Box2D class:
package com.circlecrashavoider.scene2d;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.Vector;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.circlecrashavoider.BaseScreen;
import com.circlecrashavoider.MainGame;
/**
* Created by Felipe on 2/19/2016.
*/
public class Box2DScreen extends BaseScreen {
public Box2DScreen(MainGame game) {
super(game);
}
private World world;
private Box2DDebugRenderer renderer;
private OrthographicCamera camera;
private Body playerBody, floorBody, obstacleBody, obstacle2Body;
private Fixture playerFixture, floorFixture, obstacleFixture, obstacle2Fixture;
private boolean mustJump, playerJumping, playerAlive = true;
#Override
public void show() {
world = new World(new Vector2(0, -10), true);
renderer = new Box2DDebugRenderer();
camera = new OrthographicCamera(16, 9);
camera.translate(0, 1);
world.setContactListener(new ContactListener() {
#Override
public void beginContact(Contact contact) {
Fixture fixtureA = contact.getFixtureA(), fixtureB = contact.getFixtureB();
if ((fixtureA.getUserData().equals("player") && fixtureB.getUserData().equals("floor")) ||
(fixtureA.getUserData().equals("floor") && fixtureB.getUserData().equals("player"))) {
if (Gdx.input.isTouched()) {
mustJump = true;
}
playerJumping = false;
}
if ((fixtureA.getUserData().equals("player") && fixtureB.getUserData().equals("obstacle")) ||
(fixtureA.getUserData().equals("obstacle") && fixtureB.getUserData().equals("player"))) {
playerAlive = false;
}
if ((fixtureA.getUserData().equals("player") && fixtureB.getUserData().equals("obstacle2")) ||
(fixtureA.getUserData().equals("obstacle2") && fixtureB.getUserData().equals("player"))) {
playerAlive = false;
}
}
#Override
public void endContact(Contact contact) {
Fixture fixtureA = contact.getFixtureA(), fixtureB = contact.getFixtureB();
if (fixtureA == playerFixture && fixtureB == floorFixture) {
playerJumping = true;
}
if (fixtureA == floorFixture && fixtureB == playerFixture) {
playerJumping = true;
}
}
#Override
public void preSolve(Contact contact, Manifold oldManifold) {
}
#Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
});
playerBody = world.createBody(createplayerBodyDef());
floorBody = world.createBody(createfloorBodyDef());
obstacleBody = world.createBody(createobstacleBodyDef(0.5f));
obstacle2Body = world.createBody(createobstacle2BodyDef(-0.5f));
CircleShape playerShape = new CircleShape();
playerShape.setRadius(0.5f);
playerFixture = playerBody.createFixture(playerShape,1);
playerShape.dispose();
PolygonShape floorShape = new PolygonShape();
floorShape.setAsBox(500,1);
floorFixture = floorBody.createFixture(floorShape, 1);
floorShape.dispose();
obstacleFixture = createobstacleFixture(obstacleBody);
obstacle2Fixture = createobstacle2Fixture(obstacle2Body);
playerFixture.setUserData("player");
floorFixture.setUserData("floor");
obstacleFixture.setUserData("obstacle");
obstacle2Fixture.setUserData("obstacle2");
}
private BodyDef createobstacleBodyDef(float x) {
while (true) {
BodyDef def = new BodyDef();
def.position.set(0, 0.5f);
return def;
}
}
private BodyDef createobstacle2BodyDef(float x) {
BodyDef def = new BodyDef();
def.position.set(6,2.5f);
return def;
}
private BodyDef createfloorBodyDef() {
BodyDef def = new BodyDef();
def.position.set(0,-1);
return def;
}
private BodyDef createplayerBodyDef() {
BodyDef def = new BodyDef();
def.position.set(-5 ,0);
def.type = BodyDef.BodyType.DynamicBody;
return def;
}
private Fixture createobstacleFixture(Body obstacleBody) {
while (true) {
Vector2[] vertices = new Vector2[3];
vertices[0] = new Vector2(-0.5f, -0.5f);
vertices[1] = new Vector2(0.5f, -0.5f);
vertices[2] = new Vector2(0, 0.5f);
PolygonShape shape = new PolygonShape();
shape.set(vertices);
Fixture fix = obstacleBody.createFixture(shape, 1);
shape.dispose();
return fix;
}
}
private Fixture createobstacle2Fixture(Body obstacle2Body) {
Vector2[] vertices = new Vector2[3];
vertices[2] = new Vector2(-0.5f, 0.5f);
vertices[1] = new Vector2(0.5f, 0.5f);
vertices[0] = new Vector2(0, -0.5f);
PolygonShape shape = new PolygonShape();
shape.set(vertices);
Fixture fix = obstacle2Body.createFixture(shape, 1);
shape.dispose();
return fix;
}
#Override
public void dispose() {
playerBody.destroyFixture(playerFixture);
obstacleBody.destroyFixture(obstacleFixture);
world.destroyBody(playerBody);
world.destroyBody(obstacleBody);
world.dispose();
renderer.dispose();
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(mustJump) {
mustJump = false;
jump();
}
if (Gdx.input.justTouched()) {
mustJump = true;
}
if (playerAlive) {
float velocityY = playerBody.getLinearVelocity().y;
playerBody.setLinearVelocity(8, velocityY);
}
world.step(delta, 6, 2);
camera.update();
renderer.render(world, camera.combined);
}
private void jump () {
Vector2 position = playerBody.getPosition();
playerBody.applyLinearImpulse(0, 6, position.x, position.y, true);
}
}
return fix; will return; exiting the first iteration on the while loop.
Related
how to stopped the forces acting AFTER the collision of a dynamic body with a dynamic body?
I expect that at the moment of collision, one body will be able to move body2, and after the collision, body2 will stop.
I tried really many times to solve this with ContactListener, ground friction and player active states. Unfortunately, I have not been able to solve this. Does anyone know how this should work?
I don't see the point in attaching the code, but I'll do it anyway:
public class GameScreen implements Screen {
...
Player player;
Player player2;
#Override
public void show() {
...
world = new World(new Vector2(0, 0f), true);
player = new Player(world);
player2 = new Player(world);
moveDirection = new MoveDirection(player);
shotDirection = new ShotDirection(player);
...
}
#Override
public void render(float delta) {
world.step(1f/60f, 6, 2);
player.update();
player2.update();
...
}
...
}
public class Player {
private final float PIXELS_TO_METERS = 100f;
private Sprite sprite;
private World world;
private Body body;
...
public Body getBody()
public void createBody() {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.fixedRotation = true;
bodyDef.position.set(
sprite.getX() / PIXELS_TO_METERS,
sprite.getY() / PIXELS_TO_METERS
);
body = world.createBody(bodyDef);
CircleShape shape = new CircleShape();
shape.setRadius((long) (20) / PIXELS_TO_METERS);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 0.1f;
body.createFixture(fixtureDef);
shape.dispose();
}
public void update() {
if(!isBodyCreated) {
createBody();
isBodyCreated = true;
}
//Previously used:
/*if(!isActive()) {
body.setLinearVelocity(0, 0);
}*/
...
}
...
}
Thanks for reading.
EDIT: Ok, I found a solution, but it works with a delay, what can I do to fix it?
public class GameScreen implements Screen {
...
#Override
public void render(float delta) {
world.step(1f/60f, 6, 2);
player.update();
player2.update();
...
}
...
}
public class MoveDirection extends Actor {
...
addListener(new InputListener() {
...
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
...
player.setActive(true);
...
}
...
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
...
player.setActive(false);
player.getBody().setLinearVelocity(0, 0);
}
...
}
public class Player {
private boolean active = false;
...
public void createBody() {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.fixedRotation = true;
bodyDef.position.set(
(sprite.getX()) / PIXELS_TO_METERS,
(sprite.getY()) / PIXELS_TO_METERS
);
body = world.createBody(bodyDef);
CircleShape shape = new CircleShape();
shape.setRadius((long) (20) / PIXELS_TO_METERS);
fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 0.1f;
//fixtureDef.restitution = 0;
body.createFixture(fixtureDef);
shape.dispose();
body.setBullet(true);
body.setUserData("player");
}
public void setActive(boolean bool) {
this.active = bool;
}
public boolean isActive() {
return this.active;
}
public boolean isContact() {
boolean isContact = false;
for(Contact contact : world.getContactList()) {
if((contact.getFixtureA().getBody() == this.body || contact.getFixtureB().getBody() == this.body) && (contact.getFixtureA().getBody().getUserData() == "player" && contact.getFixtureB().getBody().getUserData() == "player")) {
isContact = true;
break;
}
}
return isContact;
}
public void update() {
...
if(!isContact() && !isActive()) {
body.setLinearVelocity(0, 0);
}
}
}
I haven't got any experience with box2d, so I can not give a detailed answer. But perhaps this is where the EndContact and PostSolve methods are ment to be implemented.
https://www.iforce2d.net/b2dtut/collision-anatomy
Contact Collision box2D wont run on collision i want the bullet to be able to run the WorldContactListener beginContact when it begins contact and when it ends contact runningendContact
iv'e looked through a lot of places and i cant get a system print
This is my contact listener class:
package com.mygdx.game;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Manifold;
public class WorldContactListener implements ContactListener {
#Override
public void beginContact(Contact contact) {
//called when 2 fixtures collide
System.out.println("Begin Contact");
}
#Override
public void endContact(Contact contact) {
//called when the 2 fixtures connected gets split apart
System.out.println("end Contact");
}
#Override
public void preSolve(Contact contact, Manifold oldManifold) {
//gives power to change the characteristics of fixture
collision
}
#Override
public void postSolve(Contact contact, ContactImpulse impulse) {
//gives results of what happened because of collision like
angles ext
}
}
play screen class:
package com.mygdx.game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.badlogic.gdx.utils.viewport.StretchViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.mygdx.game.Sprites.Bullet;
import com.mygdx.game.Sprites.InversePlayer;
import com.mygdx.game.Sprites.Player;
#SuppressWarnings("unused")
public class PlayScreen implements Screen {
private main game;
private TextureAtlas atlas;
private OrthographicCamera gamecam;
private Viewport gamePort;
private Hud hud;
private TmxMapLoader maploader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private World world;
private Box2DDebugRenderer b2dr;
private Player player;
private InversePlayer inversePlayer;
private Bullet bullet;
public PlayScreen(main game) {
atlas = new TextureAtlas("BurningShooterPlayer.pack");
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(main.V_WIDTH / main.PPM, main.V_HEIGHT / main.PPM, gamecam);
hud = new Hud(game.batch);
maploader = new TmxMapLoader();
map = maploader.load("map1.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 1 / main.PPM);
gamecam.position.set(gamePort.getWorldWidth()/2, gamePort.getWorldHeight()/2, 0);
world = new World(new Vector2(0,-10), true);
b2dr = new Box2DDebugRenderer();
new B2WorldCreator(this);
player = new Player(this);
inversePlayer = new InversePlayer(this, .32f, .32f);
bullet = new Bullet(this, .64f, .64f);
}
public TextureAtlas getAtlas() {
return atlas;
}
#Override
public void show() {
//world.setContactListener(ContactListener listener) .
}
public void handleInput(float dt) {
if(Gdx.input.isKeyJustPressed(Input.Keys.W))
player.b2body.applyLinearImpulse(new Vector2(0, 4f), player.b2body.getWorldCenter(), true);
if(Gdx.input.isKeyPressed(Input.Keys.D) && player.b2body.getLinearVelocity().x <= 2)
player.b2body.applyLinearImpulse(new Vector2(0.1f , 0), player.b2body.getWorldCenter(), true);
if(Gdx.input.isKeyPressed(Input.Keys.A) && player.b2body.getLinearVelocity().x >= -2)
player.b2body.applyLinearImpulse(new Vector2(-0.1f , 0), player.b2body.getWorldCenter(), true);
if(Gdx.input.isKeyJustPressed(Input.Keys.RIGHT)) {
bullet.b2body.setLinearVelocity(0, 0);
bullet.b2body.setTransform(new Vector2((float)(player.b2body.getPosition().x+player.getWidth()-(3/main.PPM)), (float)(player.b2body.getPosition().y)), 0);
bullet.b2body.applyLinearImpulse(new Vector2(Bullet.BULLET_SPEED, 0), bullet.b2body.getWorldCenter(), true);
Bullet.Right = true;
}
if(Gdx.input.isKeyJustPressed(Input.Keys.LEFT)) {
bullet.b2body.setLinearVelocity(0, 0);
bullet.b2body.setTransform(new Vector2((float)(player.b2body.getPosition().x-player.getWidth()+(3/main.PPM)), (float)(player.b2body.getPosition().y)), 0);
bullet.b2body.applyLinearImpulse(new Vector2(-Bullet.BULLET_SPEED, 0), bullet.b2body.getWorldCenter(), true);
Bullet.Right = false;
}
//if(Gdx.input.isKeyJustPressed(Input.Keys.SPACE)) {
//bullet.b2body.setBullet(true);
//world.destroyBody(bullet.b2body);
//}
}
public void update(float dt) {
handleInput(dt);
world.step(1/60f, 6, 2);
player.update(dt);
inversePlayer.update(dt);
bullet.update(dt);
gamecam.position.x = player.b2body.getPosition().x;
gamecam.update();
renderer.setView(gamecam);
}
#Override
public void render(float delta) {
update(delta);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, gamecam.combined);
game.batch.setProjectionMatrix(gamecam.combined);
game.batch.begin();
player.draw(game.batch);
inversePlayer.draw(game.batch);
bullet.draw(game.batch);
game.batch.end();
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
}
#Override
public void resize(int width, int height) {
gamePort.update(width, width);
}
public TiledMap getMap() {
return map;
}
public World getWorld() {
return world;
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
map.dispose();
renderer.dispose();
world.dispose();
b2dr.dispose();
hud.dispose();
}
}
Bullet code (i want to detect if it collides with another body):
package com.mygdx.game.Sprites;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.utils.Array;
import com.mygdx.game.PlayScreen;
import com.mygdx.game.main;
public class Bullet extends projectile{
private float stateTime;
private Animation<TextureRegion> walkAnimation;
private Array<TextureRegion> frames;
public static float BULLET_SPEED = 1f;
public static boolean Right = true;
public Bullet(PlayScreen screen, float x, float y) {
super(screen, x, y);
frames = new Array<TextureRegion>();
frames.add(new TextureRegion(screen.getAtlas().findRegion("BurningShooterPlayer"),111, -1, 15, 8));
walkAnimation = new Animation<TextureRegion>(0.1f, frames);
stateTime = 0;
setBounds(getX(), getY(), (float) (7.5/ main.PPM), 4 / main.PPM);
}
public void update(float dt) {
stateTime += dt;
setPosition((b2body.getPosition().x - getWidth() / 2), b2body.getPosition().y - getHeight() / 2);
setRegion(walkAnimation.getKeyFrame(stateTime, true));
if((!Right) && !walkAnimation.getKeyFrame(dt).isFlipX()) {
walkAnimation.getKeyFrame(dt).flip(true, false);
}
else if((Right) && walkAnimation.getKeyFrame(dt).isFlipX()) {
walkAnimation.getKeyFrame(dt).flip(true, false);
}
}
#Override
protected void defineProjectile() {
BodyDef bdef = new BodyDef();
bdef.position.set(64 / main.PPM, 64 / main.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
PolygonShape shape = new PolygonShape();
shape.setAsBox((float) (7.5 / 2 / main.PPM), 4 / 2 / main.PPM);
fdef.filter.categoryBits = main.ENEMY_BIT;
fdef.filter.maskBits = main.GROUND_BIT |
main.ENEMY_BIT |
main.OBJECT_BIT;
fdef.shape = shape;
fdef.density = 100;
b2body.setBullet(true);
b2body.createFixture(fdef);
b2body.setUserData(this);
}
}
You create the World but you forget to set your ContactListener to your world:
private World world;
private WorldContactListener worldContactListener;
public PlayScreen(main game) {
...
world = new World(new Vector2(0,-10), true);
worldContactListener = new WorldContactListener();
world.setContactListener(worldContactListener);
...
}
I would like to add a zoom and pan mechanic to my game but everything I have looked up on the web has been complete and utter failure.
If you could give me a good example of implementing these functions that would be sweet.
Here is the class I'm trying to get it to work in.
package com.adam.finis.screens;
import com.adam.finis.Main;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class Play extends ApplicationAdapter implements Screen, GestureListener, ApplicationListener{
//Core Variables
private Main game;
public static InputMultiplexer inputMultiPlex;
//Texture Variables
Texture Title;
private TmxMapLoader mapLoader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
//Sprite Variables
public static boolean spawnSprite = false;
//Font
private BitmapFont font;
//Window Variables
private OrthographicCamera gameCam;
private Viewport gamePort;
private PlayHud hudPlay;
private int mapX = 1952;
private int mapY = 1952;
private int mapHalfX = mapX / 2;
private int mapHalfY = mapY / 2;
public static boolean GAME_PAUSED = false;
//Random Variables
private Vector2 dragOld, dragNew;
public static Vector2 worldSize;
//DEBUG
private String message;
private Texture debugTexture;
private Sprite debugSprite;
public Play(Main game){
this.game = game;
gameCam = new OrthographicCamera();
gameCam.setToOrtho(false, Main.V_WIDTH, Main.V_HEIGHT);
gamePort = new FitViewport(Main.V_WIDTH, Main.V_HEIGHT, gameCam);
hudPlay = new PlayHud(game.sb);
mapLoader = new TmxMapLoader();
map = mapLoader.load("images/level1.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
gameCam.position.set(mapHalfX, mapHalfY, 0);
GestureDetector gd = new GestureDetector(this);
inputMultiPlex = new InputMultiplexer();
inputMultiPlex.addProcessor(hudPlay.stage);
inputMultiPlex.addProcessor(hudPlay.debugStage);
inputMultiPlex.addProcessor(gd);
Gdx.input.setInputProcessor(gd);
debugTexture = new Texture(Gdx.files.internal("images/house.png"));
debugSprite = new Sprite(debugTexture);
worldSize = new Vector2(mapX, mapY);
font = new BitmapFont(Gdx.files.internal("fonts/lemonMilk.fnt"),false);
font.setColor(Color.RED);
}
#Override
public void show() {
}
public void handleInput(float dt){
//Keyboard Settings
if (Gdx.input.isKeyPressed(Input.Keys.W)) {
gameCam.position.y += 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.A)) {
gameCam.position.x -= 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.S)) {
gameCam.position.y -= 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.D)) {
gameCam.position.x += 350 * dt;
}
//ZOOM
if (Gdx.input.isKeyPressed(Input.Keys.O)) {
gameCam.zoom += 1.5f * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.P)) {
gameCam.zoom -= 1.5f * dt;
}
//CAMERA BOUNDS
gameCam.zoom = MathUtils.clamp(gameCam.zoom, 0.1f, mapX / gameCam.viewportWidth);
//|
float camX = gameCam.position.x;
float camY = gameCam.position.y;
//|
Vector2 camMin = new Vector2(gameCam.viewportWidth, gameCam.viewportHeight);
Vector2 camMax = new Vector2(1952, 1952);
//|
camMin.scl(gameCam.zoom/2);
camMax.sub(camMin);
//|
camX = Math.min(camMax.x, Math.max(camX, camMin.x));
camY = Math.min(camMax.y, Math.max(camY, camMin.y));
gameCam.position.set(camX, camY, gameCam.position.z);
//------------------------------------------------------------------------------------
//Touch Settings
if (Gdx.input.justTouched()){
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
dragOld = dragNew;
}
if (Gdx.input.isTouched()){
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
if (!dragNew.equals(dragOld)){
gameCam.translate(dragOld.x - dragNew.x, dragNew.y - dragOld.y);
dragOld = dragNew;
}
}
}
public void update(float dt){
handleInput(dt);
gameCam.update();
renderer.setView(gameCam);
}
#Override
public void render(float delta) {
if(GAME_PAUSED == false){
update(delta);
//CLEAR SCREEN - BLACK
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//INIT ALL INPUT
Gdx.input.setInputProcessor(inputMultiPlex);
//RENDER MAP
renderer.setView(gameCam);
renderer.render();
//DRAW
if(spawnSprite == true){
game.sb.begin();
game.sb.draw(debugSprite, 1500, 500);
game.sb.end();
}
//DRAW HUD
hudPlay.stage.getViewport().apply();
hudPlay.stage.act();
hudPlay.stage.draw();
//debug DRAW HUD
hudPlay.debugStage.getViewport().apply();
hudPlay.debugStage.act();
hudPlay.debugStage.draw();
//PROJECTION
game.sb.setProjectionMatrix(gameCam.combined);
game.hudSb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
game.hudSb.setProjectionMatrix(hudPlay.stage.getCamera().combined);
if(Main.zoomOut == true){
gameCam.zoom += 1.5f * delta;
}
if(Main.zoomIn == true){
gameCam.zoom -= 1.5f * delta;
}
}
if(GAME_PAUSED == true){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.input.setInputProcessor(inputMultiPlex);
game.sb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
hudPlay.debugStage.getViewport().apply();
hudPlay.debugStage.act();
hudPlay.debugStage.draw();
}
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
gameCam.viewportWidth = width/5f; //We will see width/32f units!
gameCam.viewportHeight = gameCam.viewportWidth * height/width;
hudPlay.stage.getViewport().update(width, height, true);
hudPlay.debugStage.getViewport().update(width, height, true);
}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void hide() {}
#Override
public void dispose() {
game.sb.dispose();
renderer.dispose();
hudPlay.dispose();
font.dispose();
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
message = "TAP";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean longPress(float x, float y) {
message = "LONG PRESS";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
message = "Pinch performed";
Gdx.app.log("INFO", message);
return true;
}
}
Your own answer is right, but here is an improved version where zooming a second time is performed upon the previous zoom.
Also, camera translation speed is proportional to the current camera zoom.
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
gameCam.translate(-deltaX * currentZoom,deltaY * currentZoom);
gameCam.update();
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
gameCam.zoom = (initialDistance / distance) * currentZoom;
gameCam.update();
return true;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
Gdx.app.log("INFO", "panStop");
currentZoom = gameCam.zoom;
return false;
}
I fixed the issue sorry im new to all of this and its making me think a little too much.
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
gameCam.translate(-deltaX, deltaY);
gameCam.update();
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
gameCam.zoom = (initialDistance / distance) * ZOOM;
gameCam.update();
return true;
}
In my first game I used Scened2d + Box2d rendering my bodies independently without extending Actor. It works, but it is messy and not recommended.
Now in my second game, I would like to do it properly and create a bridge between Scened2d and Box2d by using a physics stage Stage.
I found this code http://pastebin.com/rNpxvT80 what does pretty much what I need. However, the stage and box2d cameras are not aligned even if used mDebugRenderer.render(world, camera.combined) in the Draw() method of my Stage class called GameStage.
I have taken a look on this, but I had no luck libGdx How to use images or actor as body.
I know it may be something simple, but is wrecking my head...
Here is the result:
Here is the full "working" source code:
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
public class Box2D_Platformer extends Game {
public World mBoxWorld;
public Box2DDebugRenderer mDebugRenderer;
public OrthographicCamera mCam;
public AssetManager mManager;
public sprite_actor mBall;
public GameStage stage;
public SpriteBatch batch;
public static final float PIXEL_TO_METER_RATIO_DEFAULT = 32f;
static final float one_over_60 = 1f / 60f;
#Override
public void create() {
init();
batch = new SpriteBatch();
stage = new GameStage();
Gdx.input.setInputProcessor(stage);
stage.setupStage(mCam, mBoxWorld, mDebugRenderer);
stage.addActor(mBall);
}
#Override
public void render() {
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
render_physics();
stage.draw();
}
#Override
public void dispose() {
stage.dispose();
mManager.dispose();
}
private void init() {
mManager = new AssetManager();
mCam = new OrthographicCamera(1024, 768);
mCam.update();
init_physics();
init_ball();
}
private void init_physics() {
mBoxWorld = new World(new Vector2(0, -200), true);
mDebugRenderer = new Box2DDebugRenderer();
create_static_object_floor();
}
private void init_ball() {
TextureAtlas atlasSprites;
mManager.load("data/atlas.txt",TextureAtlas.class);
mManager.finishLoading();
atlasSprites = mManager.get("data/atlas.txt");
TextureRegion t = atlasSprites.findRegion("bar");
//
mBall = new sprite_actor(mBoxWorld, new Sprite(t));
}
private Body create_dynamic_object_ball() {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(100 / PIXEL_TO_METER_RATIO_DEFAULT,5000 / PIXEL_TO_METER_RATIO_DEFAULT );
Body body = mBoxWorld.createBody(bodyDef);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(1f*PIXEL_TO_METER_RATIO_DEFAULT);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 0.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 1f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = body.createFixture(fixtureDef);
circle.dispose();
return body;
}
private Body create_static_object_floor() {
BodyDef groundBodyDef = new BodyDef();
groundBodyDef.position.set(new Vector2(0, 10));
Body groundBody = mBoxWorld.createBody(groundBodyDef);
PolygonShape groundBox = new PolygonShape();
groundBox.setAsBox(mCam.viewportWidth, 10.0f);
groundBody.createFixture(groundBox, 0.0f);
groundBox.dispose();
return groundBody;
}
private void render_physics() {mDebugRenderer.render(mBoxWorld, mCam.combined);}
private float to_world_x(float size) {return size /PIXEL_TO_METER_RATIO_DEFAULT;}
private float to_world_y(float size) {return size /PIXEL_TO_METER_RATIO_DEFAULT;}
private class sprite_actor extends Actor {
private Body mBody = null;
private Sprite mSprite;
public sprite_actor(World world, Sprite sprite) {
this.mSprite = sprite;
create_body();
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
// TODO Auto-generated method stub
setRotation(MathUtils.radiansToDegrees * mBody.getAngle());
setPosition(to_world_x(mBody.getPosition().x),to_world_y(mBody.getPosition().y));
batch.draw(mSprite, getX(), getY());
System.out.println("("+to_world_x(mBody.getPosition().x)+","+to_world_y(mBody.getPosition().y)+")");
}
private void create_body() {
mBody = create_dynamic_object_ball();
}
}
private class GameStage extends Stage {
private World world;
private OrthographicCamera camera;
public void setupStage(OrthographicCamera cam, World box_world,Box2DDebugRenderer renderer) {
this.world = box_world;
this.camera = cam;
}
#Override
public void act(float step) {
world.step(one_over_60, 6, 2);
super.act(step);
}
#Override
public void draw() {
mDebugRenderer.render(world, camera.combined);
super.draw();
}
}
}
I am creating a very simple game, because I am new to developing on the android platform, but not programming, in general. Anyway, when I run the app via the emulator, or sometimes through an actual device, all I see are the two paddles being drawn, including ball, on the screen, and when I touch the screen, or simulate touching with a mouse, the event onTouch, doesn't get fired. I do not know why, can anyone point me to the right direction, I am new to developing on android devices.
Code:
package main.game;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.*;
public class DrawingArea extends SurfaceView
{
private Ball ball = null;
private Paddle player = null;
private Paddle computer = null;
private Vector2 playerPos = Vector2.Zero;
private boolean startGame = false;
private boolean initiated = false;
private Paint paint;
public DrawingArea(Context context, Paint paint) {
super(context);
setOnTouchListener(new Touch());
setWillNotDraw(false);
this.paint = paint;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
if (initiated == false)
{
ball = new Ball(getWidth() / 2.0f, getHeight() / 2.0f, 32, paint);
player = new Paddle(playerPos.getX(), playerPos.getY(), 32, 128, paint);
Paint p = new Paint();
p.set(paint);
p.setColor(Color.GREEN);
computer = new Paddle(getWidth() - 32, 0, 32, 128, p);
GameLoop gloop = new GameLoop(this);
gloop.start();
UpdateLoop uloop = new UpdateLoop(this);
uloop.start();
initiated = true;
}
ball.draw(canvas);
player.draw(canvas);
computer.draw(canvas);
}
class GameLoop extends Thread
{
private DrawingArea area;
private boolean running = true;
public GameLoop(DrawingArea area)
{
this.area = area;
}
#Override
public void run() {
int frame = 0;
while(running)
{
this.area.invalidate();
if(frame == Integer.MAX_VALUE) { frame = 0;}
frame++;
}
}
public void closeThread()
{
running = false;
}
}
class Touch implements View.OnTouchListener
{
#Override
public boolean onTouch(View v, MotionEvent event) {
startGame = true;
playerPos = new Vector2(0, event.getY());
if (playerPos.getY() < (player.getY() + 256))
{
player.translateY(-0.5f);
}
else if (playerPos.getY() > (player.getY() + 256))
{
player.translateY(0.5f);
}
return true;
}
}
class UpdateLoop extends Thread
{
private DrawingArea area;
private boolean running = true;
private boolean forward = true;
public UpdateLoop(DrawingArea area)
{
this.area = area;
}
#Override
public void run() {
int frame = 0;
while(running)
{
if (startGame == true)
ball.translate(0.5f, 0.5f, 45.0f, forward);
if (ball.getX() < 0 || ball.getY() < 0 || ball.getX() > area.getWidth()|| ball.getY() > area.getHeight()|| ball.Intersects(computer) || ball.Intersects(player))
{
if(forward == true)
forward = false;
else
forward = true;
}
if(frame == Integer.MAX_VALUE) { frame = 0;}
frame++;
}
}
}
}
Update:
DrawingArea area = new DrawingArea(this, paint);
setContentView(R.layout.main);
LinearLayout main = (LinearLayout)findViewById(R.id.main);
main.addView(area, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
main.setOnTouchListener(this);
Instead of registering your listener to surfaceview
setOnTouchListener(new Touch());
Try attaching the listener to the layout for the view something like this
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.yourlayout);
//the whole screen becomes sensitive to touch
mLinearLayoutMain = (LinearLayout) findViewById(R.id.layout_main);
mLinearLayoutMain.setOnTouchListener(this);
}