Enemy Class
public class Enemy extends Sprite{
private Vector2 velocity = new Vector2(0,0);
private float speed = 30, gravity = 30 * 1.8f;
public Enemy(Sprite sprite){
super(sprite);
}
public void draw(SpriteBatch spriteBatch){
update(Gdx.graphics.getDeltaTime());
super.draw(spriteBatch);
}
public void update(float delta) {
velocity.y -= gravity * delta;
setY(velocity.y + speed * delta);
}
}
PlayScreen Class
public class PlayScreen implements Screen {
private Player player;
private OrthographicCamera camera;
private OrthogonalTiledMapRenderer renderer;
private TiledMap map;
private Rectangle rightRectangle, leftRectangle, playerRectangle;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
renderer.getSpriteBatch().begin();
player.draw(renderer.getSpriteBatch());
boolean wallLeft = leftRectangle.overlaps(player.rectangle);
boolean wallRight = rightRectangle.overlaps(player.rectangle);
if(wallLeft){
System.out.println("wallLeft Overlap");
player.velocity.x = 0;
}
else if(wallRight){
System.out.println("wallRight Overlap");
player.velocity.x = 0;
}
enemies = new ArrayList<Enemy>();
enemy = new Enemy(new Sprite(new Texture("img/player.png"))));
enemies.add(new Enemy(new Sprite(new Texture("img/player.png"))));
enemies.add(new Enemy(new Sprite(new Texture("img/player.png"))));
for(it = enemies.iterator(); it.hasNext();){
enemy.draw(renderer.getSpriteBatch());
enemy.setOrigin(500, 500);
}
renderer.getSpriteBatch().end();
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();
}
#Override
public void show() {
camera = new OrthographicCamera();
map = new TiledMap();
renderer = new OrthogonalTiledMapRenderer(map);
player = new Player(new Sprite(new Texture("img/player.png")));
rightRectangle = new Rectangle(1280,0,0,720);
leftRectangle = new Rectangle(0,0,0,720);
player.setPosition(
Gdx.graphics.getWidth()/2f - player.getWidth()/2f,
Gdx.graphics.getHeight()/2f - player.getHeight()/2f
- Gdx.graphics.getHeight()/5f);
}
}
So if I were to run this, the application would just freeze up and would not respond anymore. I believe the problem is when I try adding the 'Enemy' into the PlayScreen class. It ran fine before, when I didn't put the 'Enemy' class into the project. What I'm trying to do is, to draw each enemy within the array of enemies then set their position.
Yes, you are missing an it.next() in here to advance the loop.
for(it = enemies.iterator(); it.hasNext();){
enemy.draw(renderer.getSpriteBatch());
enemy.setOrigin(500, 500);
}
I think you dont want to be drawing the same enemy each time either, so you should set enemy = it.next() at the beginning of this loop
Also, Im not %100 sure on how the backend of this works, but I'm pretty sure you don't want to load up 3 copies of the same sprite in the following snippet. You should load the sprite once, and use the same one for each enemy
enemy = new Enemy(new Sprite(new Texture("img/player.png"))));
enemies.add(new Enemy(new Sprite(new Texture("img/player.png"))));
enemies.add(new Enemy(new Sprite(new Texture("img/player.png"))));
Related
I have a animation which i want to flip to the left if key LEFT is pressed, but it doesnt stay flipped. It only flips like 1 frame then turns back again.
Here is my GameScreen where i draw everything:
public class GameScreen extends ScreenManager{
//For the view of the game and the rendering
private SpriteBatch batch;
private OrthographicCamera cam;
//DEBUG
private Box2DDebugRenderer b2dr;
//World, Player and so on
private GameWorld world;
private Player player;
private Ground ground;
//player animations
private TextureRegion currFrame;
public static float w, h;
public GameScreen(Game game) {
super(game);
//vars
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
//view and rendering
batch = new SpriteBatch();
cam = new OrthographicCamera();
cam.setToOrtho(false, w/2, h/2);
//debug
b2dr = new Box2DDebugRenderer();
//world, bodies ...
world = new GameWorld();
player = new Player(world);
ground = new Ground(world);
}
#Override
public void pause() {
}
#Override
public void show() {
}
#Override
public void render(float delta) {
//clearing the screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//updating
update(Gdx.graphics.getDeltaTime());
player.stateTime += Gdx.graphics.getDeltaTime();
//render
batch.setProjectionMatrix(cam.combined);
currFrame = Player.anim.getKeyFrame(Player.stateTime, true);
batch.begin();
batch.draw(currFrame, Player.body.getPosition().x * PPM - 64, Player.getBody().getPosition().y * PPM- 72);
batch.end();
//debug
b2dr.render(GameWorld.getWorld(), cam.combined.scl(PPM));
}
#Override
public void resize(int width, int height) {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
#Override
public void onKlick(float delta) {
}
public void update(float delta){
world.update(delta);
updateCam(delta);
Player.keyInput(delta);
System.out.println("X-POS" + Player.getBody().getPosition().x);
System.out.println("Y-POS" + Player.getBody().getPosition().y);
}
public void updateCam(float delta){
Vector3 pos = cam.position;
pos.x = Player.getBody().getPosition().x * PPM;
pos.y = Player.getBody().getPosition().y * PPM;
cam.position.set(pos);
cam.update();
}
}
and this is the Player class where the animation is:
public class Player {
public static Body body;
public static BodyDef def;
private FixtureDef fd;
//textures
public static Texture texture;
public static Sprite sprite;
public static TextureRegion[][] region;
public static TextureRegion[] idle;
public static Animation<TextureRegion> anim;
public static float stateTime;
//set form
private PolygonShape shape;
private GameScreen gs;
public Player(GameWorld world){
texture = new Texture(Gdx.files.internal("player/char_animation_standing.png"));
region = TextureRegion.split(texture, texture.getWidth() / 3, texture.getHeight() / 2);
idle = new TextureRegion[6];
int index = 0;
for(int i = 0; i < 2; i++){
for(int j = 0; j < 3; j++){
sprite = new Sprite(region[i][j]);
idle[index++] = sprite;
}
}
anim = new Animation<TextureRegion>(1 / 8f, idle);
stateTime = 0f;
def = new BodyDef();
def.fixedRotation = true;
def.position.set(gs.w / 4, gs.h / 4);
def.type = BodyType.DynamicBody;
body = world.getWorld().createBody(def);
shape = new PolygonShape();
shape.setAsBox(32 / 2 / PPM, 64/ 2 / PPM);
fd = new FixtureDef();
fd.shape = shape;
fd.density = 30;
body.createFixture(fd);
shape.dispose();
}
public static Body getBody() {
return body;
}
public static BodyDef getDef() {
return def;
}
public static Texture getTexture() {
return texture;
}
public static void keyInput(float delta){
int horizonForce = 0;
if(Gdx.input.isKeyJustPressed(Input.Keys.UP)){
body.applyLinearImpulse(0, 300f, body.getWorldCenter().x, body.getWorldCenter().y, true);
//body.applyForceToCenter(0, 1200f, true);
System.out.println("PRESSED");
}
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
horizonForce -= 1;
sprite.flip(!sprite.isFlipX(), sprite.isFlipY());
}
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
horizonForce += 1;
}
body.setLinearVelocity(horizonForce * 20, body.getLinearVelocity().y);
}
}
thank you in advance and any answer is appreciated :D
Your sprite variable contain only one frame at the time of pressing left key. So, it flip that current sprite of your animation frame.
To solve the Problem you have to flip all the animation frame on pressing the left key.
You're only flipping last frame of Animation by sprite reference, You need to flip all frames of your Animation anim. You can flip in this way :
if(keycode== Input.Keys.RIGHT) {
for (TextureRegion textureRegion:anim.getKeyFrames())
if(!textureRegion.isFlipX()) textureRegion.flip(true,false);
}
else if(keycode==Input.Keys.LEFT) {
for (TextureRegion textureRegion:anim.getKeyFrames())
if(textureRegion.isFlipX()) textureRegion.flip(true,false);
}
So I am just trying to make my game character, which is a texture (ball), to jump up in the air and then return back down to the position that it started at when the screen is pressed. I was just wondering if someone could give me a code example or help me to do this with my current code which is below. I have basically just drawn the background and the ball texture and positioned the ball where I want it to start the jump. The ball texture is what I want to make jump straight up.
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture background;
Texture ball;
#Override
public void create () {
batch = new SpriteBatch();
background = new Texture("gamebackground.png");
ball = new Texture("ball2.png");
ball.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
}
#Override
public void render () {
batch.begin();
float scaleFactor = 2.0f;
batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.draw(ball, 80, 145, ball.getWidth() * scaleFactor, ball.getHeight() * scaleFactor);
batch.end();
}
#Override
public void dispose () {}
}
There are a million ways to do this.
Here's a simple (and not very flexible way). Create a Ball class that has variables for x and y position, velocity, and acceleration. Then give it an update method for applying the acceleration and velocity to the position:
public class Ball {
public static final float GRAVITY = -100; // size depends on your world scale
public static final float BOUNCE_DAMPENING = 0.6f;
public final Vector2 position = new Vector2();
public final Vector2 velocity = new Vector2();
public final Vector2 acceleration = new Vector2(0, GRAVITY);
public void update (){
float dt = Gdx.graphics.getDeltaTime();
velocity.add(acceleration.x * dt, acceleration.y * dt));
position.add(velocity.x * dt, velocity.y * dt);
if (position.y <= 0){ // hit ground, so bounce
position.y = -position.y * BOUNCE_DAMPENING;
velocity.y = -velocity.y * BOUNCE_DAMPENING;
}
}
}
This is a very rudimentary way of handling physics. It would be more sophisticated to use Box2D, but the above is fine if you're just learning.
Now, you need to create a ball instance and use it to track your ball position. Use the Ball object's position when drawing it. And you can react to taps to apply a velocity.
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture background;
Texture ballTexture;
Ball ball;
#Override
public void create () {
batch = new SpriteBatch();
background = new Texture("gamebackground.png");
ballTexture = new Texture("ball2.png");
ballTexture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
ball = new Ball();
}
#Override
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // don't forget to clear screen
if (Gdx.input.justTouched())
ball.velocity.y += 100;
ball.update();
batch.begin();
float scaleFactor = 2.0f;
batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.draw(ballTexture, ball.position.x, ball.position.y, ballTexture.getWidth() * scaleFactor, ballTexture.getHeight() * scaleFactor);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
background.dispose();
ballTexture.dispose();
}
}
You also need to read up on pixel units vs. world units and how to solve the scale problem with Viewports. See https://xoppa.github.io/blog/pixels/ and https://github.com/libgdx/libgdx/wiki/Viewports
I have a Circle shape that is going to represent the character I will play and control. I have a tmx map, and in the map there are red squares that are meant to represent "fences". The fences are in each corner of the map, inside the fences I have the ground that looks the same as the rest of the ground in the map, but I want to make it so that the game knows when the character is standing on those tiles in the map. can anyone help me? I don't know if it will help but here is the code:
public class PlayScreen implements Screen{
private Game game;
private OrthographicCamera gamecam;
private Viewport gamePort;
private TmxMapLoader mapLoader;
private TiledMap map;
OrthogonalTiledMapRenderer renderer;
//Box#d variables
private World world;
private Box2DDebugRenderer b2dr;
private Hero hero;
private ArrayList<Rectangle> specGroundList;
private boolean heroOnGround;
public PlayScreen(BasicGame game){
this.game = game;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(BasicGame.V_WIDTH, BasicGame.V_HEIGHT, gamecam);
mapLoader = new TmxMapLoader();
map = mapLoader.load("Basic Map.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
gamecam.position.set(gamePort.getWorldWidth() / 2, gamePort.getWorldHeight() / 2, 0);
world = new World(new Vector2(0, 0), true);
b2dr = new Box2DDebugRenderer();
hero = new Hero(world, this);
specGroundList = new ArrayList<Rectangle>();
world.setContactListener(new WorldContactListener());
BodyDef bdef = new BodyDef();
PolygonShape shape = new PolygonShape();
FixtureDef fdef = new FixtureDef();
Body body;
//create fence bodies/fixtures
for(MapObject object: map.getLayers().get(3).getObjects().getByType(RectangleMapObject.class)){
Rectangle rect = ((RectangleMapObject) object).getRectangle();
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set(rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight() / 2);
body = world.createBody(bdef);
shape.setAsBox(rect.getWidth() / 2, rect.getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
}
//create special ground bodies/fixtures
for(MapObject object: map.getLayers().get(2).getObjects().getByType(RectangleMapObject.class)) {
Rectangle rect = ((RectangleMapObject) object).getRectangle();
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set(rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight() / 2);
body = world.createBody(bdef);
shape.setAsBox(rect.getWidth() / 2, rect.getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
}
}
#Override
public void render(float delta) {
update(delta);
// Clear the game screen with Black
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
b2dr.render(world, gamecam.combined);
}
#Override
public void show() {
}
public void handleInput(float dt){
if(Gdx.input.isTouched()) {
// gamecam.position.x += 100 * dt;
gamecam.position.y -= 100 * dt;
}
}
public void update(float dt){
handleInput(dt);
world.step(1/60f, 6, 0);
hero.update(dt);
for(Rectangle rect: specGroundList){
}
gamecam.update();
renderer.setView(gamecam);
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
public Viewport getGamePort() {
return gamePort;
}
}
Assuming your hero has a known position, and your regions of special ground are oriented rectangles then can't you just use a boolean function that returns something along the lines of:
Hero.x > rectangle.left & Hero.x < rectangle.right & hero.y > rectangle.bottom & hero.y < rectangle.top
So, I just want to draw Box2DDebugRenderer same with sprite size.
I have use same SpriteBatch same Camera and same Viewport. It took me 8 hours, tried finding a solution around google and still not solve the problem.
Here what I got:
I just change this line:
PolygonShape shape = new PolygonShape();
shape.setAsBox(32, 32);
Some tutorial said to div by 2. I tried that I got result like 2nd picture.
Here my script
PlayScreen.java:
public class PlayScreen implements Screen {
private SpriteBatch batch;
private TiledMap tileMap;
private TiledMapRenderer tiledMapRenderer;
private OrthographicCamera cam;
private Player player;
private World world;
private Box2DDebugRenderer debugRenderer;
private FitViewport gamePort;
public PlayScreen(HookaHookaGame game) {
this.batch = game.getSpriteBatch();
this.world = new World(new Vector2(0, -20), true);
// Create cam
cam = new OrthographicCamera();
gamePort = new FitViewport(800, 600, cam);
gamePort.apply(true);
//initially set our gamcam to be centered correctly at the start of of map
// cam.position.set(400, 300, 0);
// cam.update();
// Load tilemap
tileMap = new TmxMapLoader().load("simulation01.tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(tileMap, batch);
// Create box2d debug renderer
debugRenderer = new Box2DDebugRenderer();
// Create player sprite
player = new Player(this.world);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
//cam.update();
// Update sprite
player.update(delta);
//Clear the game screen with Black
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Draw tilemap
tiledMapRenderer.setView(cam);
tiledMapRenderer.render();
// Set camera to spritebatch
batch.setProjectionMatrix(cam.combined);
// Draw sprite
batch.begin();
batch.draw(player.getKeyFrame(), 300, 300);
player.draw(batch);
batch.end();
// Draw box2d debug renderer
debugRenderer.render(world, cam.combined);
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
Player.java, extended from Sprite Class:
public class Player extends Sprite {
private Animation anim;
private float stateTimer;
private World world;
private Body body;
// Debug
public Player(World world) {
stateTimer = 0;
this.world = world;
loadAnim();
}
private void loadAnim() {
Array<TextureRegion> temp = new Array<TextureRegion>(40);
Texture texture = new Texture("sprite.png");
temp.add(new TextureRegion(texture, 3*32, 3*32, 32, 32));
temp.add(new TextureRegion(texture, 2*32, 3*32, 32, 32));
temp.add(new TextureRegion(texture, 32, 3 * 32, 32, 32));
temp.add(new TextureRegion(texture, 0, 3*32, 32, 32));
anim = new Animation(0.1f, temp, Animation.PlayMode.LOOP);
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(100, 100);
bodyDef.type = BodyDef.BodyType.DynamicBody;
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(32, 32);
FixtureDef fixture = new FixtureDef();
fixture.shape = shape;
body.createFixture(fixture);
setBounds(0, 0, 32, 32);
setPosition(100, 100);
}
public void update(float delta) {
stateTimer += delta;
setRegion(getKeyFrame());
setSize(32, 32);
}
public TextureRegion getKeyFrame() {
return anim.getKeyFrame(stateTimer, true);
}
}
Could you explain what happen exactly?
Box2d and Textures have different origins.
The origin of the body is its center.
The origin of the Texture is the bottom left corner.
As you can see, the center of the box2d object is exactly at the bottom left corner of the texture, if you draw them both at the same position.
Pseudo code:
batch.draw(texture, body.x - texture.width / 2, body.y - texture.heigth / 2);
Otherwise you could set the origin of the box2d body to "the bottom left corner", but that might give you trouble if you follow other tutorials.
you can also put the origin of your sprite to center by calling the function setOriginCenter() of your Sprites before drawing them
so the spritebatch will draw them from center just like your box
I am having trouble implementing smooth slow-motion rendering in LibGDX with the Artemis framework. I understand how to change "delta" in order for this to work (using this), but I'm unable to figure out how to actually implement it in the Screen interface's render method. How can I change the delta parameter of the Screen's render method to essentially slow down time?
My Screen Class:
public class GameScreen implements Screen {
private SpriteRenderSystem spriteRenderSystem;
private OrthographicCamera camera;
private Game game;
private World world;
private Random r = new Random();
public GameScreen(Game game){
camera = new OrthographicCamera();
camera.setToOrtho(false, 640, 480);
this.game = game;
world = new World();
world.setManager(new GroupManager());
spriteRenderSystem = world.setSystem(new SpriteRenderSystem(camera), true);
world.setSystem(new VelocitySystem());
world.setSystem(new AccelerationSystem());
world.setSystem(new CollisionSystem());
world.setSystem(new ExpirationSystem());
world.initialize();
for(int i = 0; i < 40; i += 4){
EntityFactory.createBlock(world, i*16, 0, "tiles/water").addToWorld();
EntityFactory.createBlock(world, (i+1) * 16, 0, "tiles/grass").addToWorld();
EntityFactory.createBlock(world, (i+2) * 16, 0, "tiles/mud").addToWorld();
EntityFactory.createBlock(world, (i+3) * 16, 0, "tiles/sand").addToWorld();
}
for(Entity e : EntityFactory.createExplosion(world, 320, 240)){
e.addToWorld();
}
}
#Override
public void render(float delta) {
// NEED HELP HERE
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
world.setDelta(delta);
world.process();
spriteRenderSystem.process();
}
(...)
}
Note: I am using the LibGDX + Artemis demo SpriteRenderSystem for rendering entities.
Have a float:
public float speed = 0.5F; //half for example
And in your render method, just multiply your delta with it:
#Override
public void render(float delta) {
delta*=speed; //<---
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
world.setDelta(delta);
world.process();
spriteRenderSystem.process();
}