I have looked around online and some things have helped but I am still yet to get this thing working. I am making a simple pong game but I want it so all my code is well set out. So I have a class for the player1 paddle, the computer paddle, the ball, the main screen and also the play screen.
So, for example, my player1Paddle class will have all the movement for that paddle, the computer paddle class(player2) will have all the movement for that and so on.
But when it comes to coding the simple AI of the computer paddle (basically follow the ball left to right) I am unable to get access to the balls position
if(player2Pong.position.x > ballPong.position.x)
It brings an error. Now i have instantiated the ball class and it works but I have basically made another ball but the movement is not there. Here are parts of the code to try and help. I know there's a lot of code, and probably some un-needed.
On my playScreen i call player2movement -
player2Pong.Player2Movement();
Heres the majority of the player2pong class.
public class Player2Pong {
public Vector2 position;
String textureLoc;
Texture Player2Texture;
float stateTime;
Rectangle player2Bounds;
String movement;
int speed = 2;
int playerXVector = 5;
SpriteBatch batch;
//PlayerPong playerpong;
Player2Pong player2pong;
Ball ballPong;
public int paddle_player2_Width = 80;
public int paddle_player2_Height = 10;
//PlayerPong player;
public Player2Pong(Vector2 position, Ball ball){
Player2Texture = new Texture(Gdx.files.internal(("paddle_player2.png")));
this.position = position;
player2Bounds = new Rectangle(position.x,position.y,paddle_player2_Width, paddle_player2_Height);
//this.player2pong = player2pong;
this.ballPong = ball;
}
public void update(){
}
public void Player2Movement(){
player2pong = new Player2Pong(new Vector2(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() - (Gdx.graphics.getHeight()/8)), ballPong);
System.out.println(player2pong.position.x);
if(player2pong.position.x > ballPong.getPosition().x){
System.out.println("right");
player2pong.position.x -= playerXVector;
}
else if(player2pong.position.x < ballPong.getPosition().x){
System.out.println("right");
player2pong.position.x += playerXVector;
}
if(player2pong.position.x > Gdx.graphics.getWidth() - player2pong.getPaddle_player2_Width()-5){
player2pong.position.x -= playerXVector;
}
if(player2pong.getPosition().x < 3){
player2pong.position.x += playerXVector;
}
}
public void draw(SpriteBatch batch){
batch.draw(Player2Texture, position.x, position.y, paddle_player2_Width, paddle_player2_Height);
}
Here is majority of the playScreen class
public class PlayScreenPong implements Screen{
private static final Color WHITE = null;
SpriteBatch batch;
PlayerPong playerPong;
Player2Pong player2Pong;
InputProcessor inputProcessor;
Game game;
Ball ballPong;
Texture paddle_player1, paddle_player2;
ArrayList<Ball> balls;
ArrayList<Player2Pong> player2;
Iterator<Ball> ballsIterator;
Vector2 position;
ShapeRenderer borderSR, ballSR;
Sound sound;
boolean rectangles = true;
Stage PlayScreenStage;
Label label;
LabelStyle style;
BitmapFont font;
int playerXVector = 10;
int player1Score = 0;
int player2Score = 0;
public PlayScreenPong(Game game){
this.game = game;
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0,0,0,0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
playerPong.update();
//player2Pong.update();
borderSR.begin(ShapeType.Line);
borderSR.rect(1, 1, Gdx.graphics.getWidth()-5, Gdx.graphics.getHeight()-4);
borderSR.setColor(1,1,1,1);
borderSR.end();
batch.begin();
ballsIterator = balls.iterator();
while(ballsIterator.hasNext()){
Ball cur = ballsIterator.next();
cur.update();
cur.draw(batch);
}
batch.draw(playerPong.getPlayerTexture(), playerPong.getPosition().x, playerPong.getPosition().y, playerPong.paddle_player1_Width, playerPong.paddle_player1_Height);
player2Pong.draw(batch);
//batch.draw(player2Pong.getPlayer2Texture(), player2Pong.getPosition().x, player2Pong.getPosition().y, player2Pong.paddle_player2_Width, player2Pong.paddle_player2_Height);
batch.end();
score();
PlayScreenStage.act();
PlayScreenStage.draw();
if(rectangles == true){
ballPong.drawRectangle();
}
player2Pong.Player2Movement();
}
#Override
public void show() {
batch = new SpriteBatch();
paddle_player1 = new Texture(Gdx.files.internal("paddle_player1.png"));
paddle_player2 = new Texture(Gdx.files.internal("paddle_player2.png"));
borderSR = new ShapeRenderer();
balls = new ArrayList<Ball>();
player2 = new ArrayList<Player2Pong>();
if(Gdx.files.local("paddle_player1.dat").exists()){
try {
playerPong = new PlayerPong(new Vector2(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 8), "paddle_player1.png");
playerPong.setPosition(PlayerPong.readPlayer());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("File exists, reading file");
}else{
playerPong = new PlayerPong(new Vector2(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 8),"paddle_player1.png");
try {
PlayerPong.savePlayer(playerPong);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Player doesnt exist, creating and saving player");
}
// player2Pong = new Player2Pong(new Vector2(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() - (Gdx.graphics.getHeight()/8)), playerPong);
// player2.add(player2Pong);
ballPong = new Ball(new Vector2(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2), playerPong);
balls.add(ballPong);
}
public void score(){
PlayScreenStage = new Stage();
font = new BitmapFont(Gdx.files.internal("font.fnt"), false);
style = new LabelStyle(font, Color.WHITE);
label = new Label("Player 1: " + player1Score + " : " + player2Score + " :Player 2", style);
label.setPosition(Gdx.graphics.getWidth()/2 - label.getWidth()/2, Gdx.graphics.getHeight()/25);
label.setFontScale((float) 0.8);
PlayScreenStage.addActor(label);
Gdx.input.setInputProcessor(PlayScreenStage);
batch = new SpriteBatch();
//System.out.println(ballPong.getPosition().y);
//-------------------------------------if someone scores
if(ballPong.getPosition().y< 1){
player2Score = player2Score +1;
//oppositionScore +=1;
System.out.println("goal");
//ballPong.reset();
}
if(ballPong.getPosition().y > Gdx.graphics.getHeight()-1 -ballPong.getBallSizeY()){
player1Score = player1Score + 1;
//ballPong.reset();
}
}
As I said before its a bit long winded but all I want to do is sort the movement of the AI in the player2pong class, the movement of the ball in the ball class and the movement of the player in the player class and then call the methods in the render or show methods in the playscreen class. Feel free to ask any questions. I know its an easy answer but im new :( Got to start somewhere
Okay, so, I might be wrong with this, but it's worth a shot.
First off, you don't need to create a new Player2pong object every time you call the PlayerMovement() function, you already have one:P
Secondly, you never make assign anything to the player2Pong attribute. So when you try and call draw() on it, there's nothing to call it on!:P
Related
I'm new to android development and I'm having a problem regarding the memory used by my game. It constantly rises until it crashes. I would appreciate if you could help me. Thank you.
Also, regarding the Spritebatch do i need to call this.dispose in the java class where i extend to game for it to be disposed? If so where can i call it? Thank you
public class Zero implements Screen, InputProcessor {
Pmacgame game;
private Stage stage;
private Skin skin;
private Sound sound ,laser;
private Music musicbg;
private Sprite spritebg, playerImage;
private ImageButton imgbtnLeft, imgbtnRight, fire, color1, color2, color3, color4,
bullet1, bullet2, bullet3, bullet4;
public static final float fireDelay = 0.3f;
String rr2;
private static int o = 0;
Rectangle player;
ArrayList<Bullet> bullets;
ArrayList<Target> targets;
ArrayList<Explode> explodes;
//long lastDrop;
int score;
boolean a, b;
public static final float minSpawnTime = 0.5f;
public static final float maxSpawnTime = 1.25f;
float shootTimer, targetSpawnTimer;
Random random;
public static int select;
public static int dis = 0;
public float health = 1;
private Sprite greenBar, redBar, blueBar, pinkBar, greenBarO, redBarO, blueBarO, pinkBarO;
public Zero(Pmacgame game){
#Override
public void render(float delta) {
shootTimer += Gdx.graphics.getDeltaTime();
ArrayList<Bullet> bulletsToRemove = new ArrayList<>();
if (fire.isPressed() && shootTimer >= fireDelay) {
shootTimer = 0;
bullets.add(new Bullet(player.x + 32f));
}
for (Bullet bullet : bullets) {
bullet.update(Gdx.graphics.getDeltaTime());
if (bullet.remove)
bulletsToRemove.add(bullet);
}
targetSpawnTimer -= Gdx.graphics.getDeltaTime();
if (targetSpawnTimer<=0){
targetSpawnTimer = random.nextFloat() * (maxSpawnTime -minSpawnTime) + minSpawnTime;
targets.add(new Target(MathUtils.random(267, Gdx.graphics.getWidth()-350f)));
}
ArrayList<Target> targetsToRemove = new ArrayList<>();
for (Target target: targets){
target.update(delta);
if (target.remove)
targetsToRemove.add(target);
if (target.getY()<=0){
health -= 0.1f;
if (health<=0){
select = 0;
dis = 1;
this.dispose();
game.setScreen(new GameOverScreen(game, score));
return;
}
}
}
ArrayList<Explode> explodesToRemove = new ArrayList<>();
for (Explode explode: explodes){
explode.update(delta);
if (explode.remove)
explodesToRemove.add(explode);
}
explodes.removeAll(explodesToRemove);
for (Bullet bullet: bullets){
for (Target target: targets){
if (bullet.getCollisionRect().collidesWith(target.getCollisionRect())){
targetsToRemove.add(target);
bulletsToRemove.add(bullet);
score+=5;
explodes.add(new Explode(target.getX(), target.getY()));
sound.play(1f, 1.3f, 0f);
}
}
}
targets.removeAll(targetsToRemove);
bullets.removeAll(bulletsToRemove);
//Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.begin();
spritebg.draw(game.batch);
game.batch.draw(blueBarO, 0, 575, blueBarO.getWidth(), blueBarO.getHeight());
game.batch.draw(redBarO, 0, 550, redBarO.getWidth(), redBarO.getHeight());
game.batch.draw(greenBarO, 0, 525, greenBarO.getWidth(), greenBarO.getHeight());
game.batch.draw(pinkBarO, 0, 600, pinkBarO.getWidth(), pinkBarO.getHeight());
game.font.draw(game.batch, "SCORE: " + score, 40, Gdx.graphics.getHeight() - 40 );
for (Bullet bullet: bullets){
bullet.render(game.batch);
}
for (Target target: targets){
target.render(game.batch);
}
for (Explode explode: explodes){
explode.render(game.batch);
}
if (health == 0) greenBar.setSize(greenBar.getWidth(), 0f);
game.batch.draw(greenBar, 0, 525, greenBar.getWidth() * health, greenBar.getHeight());
game.batch.draw(redBar, 0, 550, redBar.getWidth(), redBar.getHeight());
game.batch.draw(blueBar, 0, 575, blueBar.getWidth(), blueBar.getHeight());
game.batch.draw(pinkBar, 0, 600, pinkBar.getWidth(), pinkBar.getHeight());
game.batch.draw(playerImage, player.x, player.y, player.width, player.height);
game.batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
if (a) player.x -= 450 * Gdx.graphics.getDeltaTime();
if (b) player.x += 450 * Gdx.graphics.getDeltaTime();
if (player.x < 65f + imgbtnLeft.getWidth() + imgbtnRight.getWidth())
player.x = 65f + imgbtnLeft.getWidth() + imgbtnRight.getWidth();
if (player.x > Gdx.graphics.getWidth() - 350f)
player.x = Gdx.graphics.getWidth() - 350f;
}
#Override
public void dispose () {
musicbg.dispose();
laser.dispose();
stage.dispose();
skin.dispose();
sound.dispose();
}
}
public class Pmacgame extends Game {
SpriteBatch batch;
BitmapFont font;
#Override
public void create () {
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("r.fnt"));
this.setScreen(new Zero(this));
}
#Override
public void render () {
super.render();
}
#Override
public void dispose() {
font.dispose();
batch.dispose();
}
}
I'm reading between the lines, but it looks like you must be loading a Texture in the constructor of Bullet/Target/Explosion, since I don't see you passing a Texture or TextureRegion reference to their constructors or render methods.
You should be loading all your Textures in a single class and passing references to your game objects for them to "borrow" and draw with. Otherwise, you are loading many copies of the same images for no reason.
Also, a Texture is a Disposable, which means it uses native memory and must have dispose() called on it before you let the garbage collector take it. Otherwise, the native memory is leaked.
In your case, all these Bullets, Targets, and Explosions are loading many Textures over and over and never disposing them when you remove them.
Regarding your question about the SpriteBatch. Yes, you should dispose of it in the same class you instantiate it, and dispose() is the right place to do it.
Edit, barebones example:
public class Assets implements Disposable {
public final Texture horse;
public final Texture bullet;
// etc.
public Assets (){
horse = new Texture("horse.png");
//...
}
public void dispose(){
horse.dispose();
//...
}
}
public class Zero implements Screen, InputProcessor {
private final Assets assets;
//...
public Zero (){
assets = new Assets();
//...
}
//...
public void dispose(){
assets.dispose();
//...
}
}
public class Bullet {
//...
public void render(SpriteBatch batch, Assets assets){
batch.render(assets.bullet, /*...*/);
}
}
My sprite moves too slowly. Basically I want to apply less force to move my player. Current this:
getBody().applyForceToCenter(new Vector2(-10000000f,0f), true);
is the force needed to make it move a tiny bit.
I know the reason why I am not able to move it is since I haven't scaled the sprite (64x64) it weights more than 400kg. What should be the correct scale?
This is my game screen.
public class GameScreen implements Screen {
//Reference to our Game, used to set Screens
private Logang game;
//basic playscreen variables
private OrthographicCamera gamecam;
private Viewport gamePort;
//Box2d variables
private World world;
private Box2DDebugRenderer b2dr;
boolean drawn = true;
private Player p;
private int pX = 100, pY = 300;
public GameScreen(Logang game) {
this.game = game;
//create cam used to follow mario through cam world
gamecam = new OrthographicCamera();
gamePort = new ScalingViewport(Scaling.stretch, Logang.GWIDTH, Logang.GHEIGHT, gamecam);
gamePort.apply();
gamecam.position.set(gamecam.viewportWidth / 2, gamecam.viewportHeight / 2, 0);
gamecam.update();
Box2D.init();
//create our Box2D world, setting no gravity in X, -10 gravity in Y, and allow bodies to sleep
world = new World(new Vector2(0, Logang.GRAVITY), true);
//allows for debug lines of our box2d world.
b2dr = new Box2DDebugRenderer();
//create a FitViewport to maintain virtual aspect ratio despite screen size
p = new Player(new Sprite(new Texture("hud_p3.png")), world, pX, pY, 1);
//initially set our gamcam to be centered correctly at the start of of map
line();
}
#Override
public void show() {
}
public void update(float dt) {
//handle user input first
p.update(dt);
//update our gamecam with correct coordinates after changes
}
#Override
public void render(float delta) {
//separate our update logic from render
update(delta);
//Clear the game screen with Black
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(1f / 60f, 6, 2);
gamecam.position.set(p.getSprite().getX(),Logang.GHEIGHT / 2, 0); // x and y could be changed by Keyboard input for example
gamecam.update();
game.getBatch().setProjectionMatrix(gamecam.combined);
//renderer our Box2DDebugLines
b2dr.render(world, gamecam.combined);
System.out.println("Player x: " + p.getSprite().getX() + " Camera X: " + gamecam.position.x + " Body X: " + p.getBody().getPosition().x);
//System.out.println("Player y: " + p.getSprite().getY() + " Camera Y: " + gamecam.position.y + " Body Y: " + p.getBody().getPosition().y);
game.getBatch().begin();
if (p.getBody() != null)
p.render(game.getBatch());
EntityManager.renderTerra(game.getBatch(), delta);
game.getBatch().end();
}
public void line() {
Texture tmp = new Texture("hud_p3.png");
tmp.setWrap(Texture.TextureWrap.MirroredRepeat, Texture.TextureWrap.MirroredRepeat);
for (int i = 0; i < 50; i++) {
EntityManager.add(new Ground(new Sprite(tmp), world, (int)(i * Logang.TILE), 1, 2));
}
// EntityManager.changeSize(((Logang.TILE) * 5),Logang.TILE);
}
#Override
public void resize(int width, int height) {
//updated our game viewport
gamePort.update(width, height);
gamecam.position.set(gamecam.viewportWidth / 2, gamecam.viewportHeight / 2, 0);
}
public World getWorld() {
return world;
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
world.dispose();
b2dr.dispose();
}
And this is my entity class
private World world;
private Sprite sprite;
private Body body;
private int tipo;
public Entity(Sprite sprite, World world, int x, int y, int tipo) {
this.sprite = sprite;
this.world = world;
getSprite().setPosition(x, y);
sprite.setSize(Logang.TILE, Logang.TILE);
sprite.setOriginCenter();
define(tipo);
this.tipo = tipo;
}
public void update(float dt){
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
getBody().applyForceToCenter(new Vector2(-10000000f,0f), true);
}
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
getBody().applyForceToCenter(new Vector2(10000000f,0f), true);
}
if(Gdx.input.isKeyPressed(Input.Keys.SPACE)){
//getBody().applyLinearImpulse(0f,-Logang.GRAVITY,
getBody().getPosition().x, getBody().getPosition().y, true);
}
}
public void define(int tipo) {
BodyDef bdef = new BodyDef();
bdef.position.set((getSprite().getX() + getSprite().getWidth() / 2),
(getSprite().getY() + getSprite().getHeight() / 2));
switch (tipo) {
case 1: {
bdef.type = BodyDef.BodyType.DynamicBody;
break;
}
case 2: {
bdef.type = BodyDef.BodyType.StaticBody;
break;
}
case 3: {
bdef.type = BodyDef.BodyType.DynamicBody;
break;
}
}
body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
fdef.density=0.001f; // (weight: range 0.01 to 1 is good)
PolygonShape shape = new PolygonShape();
shape.setAsBox(getSprite().getWidth() / 2, getSprite().getHeight() / 2);
fdef.shape = shape;
body.createFixture(fdef);
body.setUserData(this);
shape.dispose();
}
public void render(SpriteBatch batch) {
if (tipo != 2) {
float posX = getBody().getPosition().x;
float posY = getBody().getPosition().y;
getSprite().setPosition(posX - getSprite().getWidth() / 2, posY -
getSprite().getHeight() / 2);
}
getSprite().draw(batch);
}
public Sprite getSprite() {
return sprite;
}
public void setSprite(Sprite sprite) {
this.sprite = sprite;
}
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
And this are the in game variables
public static final int GWIDTH = 800;
public static final int GHEIGHT = (GWIDTH/16)*9;
public static final float PPM = 100f;
public static final float GRAVITY = -10f;
public static final float TILE = 64;
Could you please give me a fix?
I already tried to divide body and gamecam position still no effect
What should be the correct scale?
The right scale would be the scale in real life where 1 unit in LibGDX (Box2D) represents 1 meter in real life. I always advice people to use this scale and zoom the camera properly.
Mind though, if you are using very large objects and zoom the camera all the way back objects appear to be falling slowly. This is obviously because your camera contains a much larger space. Not only would it fall slowly but it won't interact properly with the world if the item is supposed to be smaller.
Adept the camera to your world, not your world to your camera.
More detailed answer I gave
I am using the Android Studio IDE, with the libGDX framework to develop a game. It is a clone of the Pac-Man game with a similar gameplay to flappy bird. The concept is that the pac man moves through the planks while avoiding the ghosts coming from the right direction, that are moving off straight into the left direction (not chasing the position of the player). I am not sure how I create a 'for loop' for the ghost animations, I want the ghosts to consistently reposition and re-appear from the right side after a few seconds, with the exception that they completely gone off the screen initially.
The class for one of the Ghosts.
public class Blinky {
private Vector3 position; //x y and z axis
private Rectangle bounds;
private Texture texture1;
private Animation blinkyAnimLeft;
public Blinky(int x, int y) {
position = new Vector3(x, y, 0);
Texture texture1 = new Texture("blinkyLeft.png");
blinkyAnimLeft = new Animation(new TextureRegion(texture1), 2, 0.5f);
//bounds = new Rectangle(x,y,texture1.getWidth() / 2, texture1.getHeight());
}
public void update(float dt) {
blinkyAnimLeft.update(dt);
//bounds.setPosition(position.x, position.y);
}
public Vector3 getPosition() {
return position;
}
public TextureRegion getTexture() {
return blinkyAnimLeft.getFrame();
}
//public Rectangle getBounds() {
return bounds;
}
public void dispose() {
texture1.dispose();
}
}
Ghosts and Player initialised in the GamePlayState Class
public class GamePlayState extends State {
//Variables
private float timePassed = 0;
private Texture background;
public static final int WALK = 1;
public static final double GHOST_WALK = 0.5;
private static final int PLANKS_SPACING = 125; //gap betwen the planks
private static final int PLANK_COUNT = 4;
private Array<Obstacle> planks;
private Player player;
private Blinky blinky;
private Inky inky;
private Texture missile;
public GamePlayState(GameStateManager gsm) {
super(gsm);
player = new Player(50, 100);
blinky = new Blinky(400, 220);
inky = new Inky(400, 240);
// missile = new Texture("missile.png");
background = new Texture("black.jpg");
cam.setToOrtho(false, PacMan.WIDTH/2, PacMan.HEIGHT/2);
planks = new Array<Obstacle>();
for (int i = 1; i<= PLANK_COUNT; i++) {
planks.add(new Obstacle(i * (PLANKS_SPACING + Obstacle.PLANK_WIDTH)));
}
}
#Override
public void handleInput() {
}
#Override
public void update(float dt) {
handleInput();
player.update(dt);
blinky.update(dt);
inky.update(dt);
cam.position.x = player.getPosition().x + 80; //update the position of the camera with the bird
//update when pacman cam viewport has passed plank
//make cam follow the player
for (Obstacle plank: planks) {
if (cam.position.x - (cam.viewportWidth/1) > plank.getPosTopPlank().x + plank.getTopPlank().getWidth()) {
plank.respositionPlanks(plank.getPosTopPlank().x + ((Obstacle.PLANK_WIDTH + PLANKS_SPACING * PLANK_COUNT )));
}
if (plank.collision (player.getBounds()))
gsm.set(new GamePlayState(gsm));
}
cam.update();
}
#Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(background, cam.position.x - (cam.viewportWidth/2), 0);
timePassed += Gdx.graphics.getDeltaTime();
//Moving Inky
sb.draw(inky.getTexture(), inky.getPosition().x, inky.getPosition().y);
inky.getPosition().x -= GHOST_WALK;
//Moving Blinky
sb.draw(blinky.getTexture(), blinky.getPosition().x, blinky.getPosition().y);
blinky.getPosition().x -= GHOST_WALK;
You should get x, y( and z) position from Vector3.
Then check for borders
if (inky.getPosition().x < 0){
Thread.sleep(/*a few sdeconds*/2000);/*Android studio would ask you about wrapping it with try - catch*/
inky.setPostion( x + /*screen x size*/,
inky.getPosition().y,inky.getPosition().z)/*add setter in ghost class*/
}
In fact, this is not the best way to do it, but the simplest one
I'm a beginner android game programmer, I use LIBgdx
I have a playState class
public PlayState(GameStateManager gsm) {
super(gsm);
obj = new Objects();
cam.setToOrtho(false, Game.WIDTH , Game.HEIGHT);
}
#Override
public void update(float dt) {
obj.update(dt);
}
I have an Objects class
public class Objects {
private Vector2 posObj;
private static final int MOVEMENT = 2;
private Vector2 velo;
private Texture objTx;
private Random rand;
private static final int FLUCTUATION = 400;
public Objects(){
objTX = new Texture("objies.png");
rand = new Random();
posObj = new Vector2(rand.nextInt(FLUCTUATION),rand.nextInt(FLUCTUATION));
velo = new Vector2(0, 0);
}
public void update(float dt){
}
Now, What I'm tring to do is:
Move this randomly generated object to the center of the screen and then dispose.
Serious Help required! Thank-you
Well, you know where your object is and you know where the middle is (Game.WIDTH/2 , Game.HEIGHT/2)
If the center is to the left of the object move it to the left, if center is above move object up etc.
So a very simple solution:
public void update(float delta){
if(posObj.x < Game.WIDTH/2){
velocity.x = MOVEMENT;
}
else {
velocity.x = -MOVEMENT;
}
if(posObj.y < Game.HEIGHT/2){
velocity.y = MOVEMENT;
}
else {
velocity.y = -MOVEMENT;
}
posObj.y += velocity.y * delta;
posObj.x += velocity.x * delta;
}
This might cause your object to jump around the middle without ever really hitting the exact coordinates. So you can check the distance from the object to the middle by adding this method to your object:
public Vector2d getPosition(){
return posObj;
}
And then check for the distance:
if( obj.dst(Game.WIDTH , Game.HEIGHT) <= closeEnough ){
obj = new Objects();
}
closeEnough is a distance you set.
I'm learning libgdx and currently doing a flappy bird demo. For fun I tried to implement when the score reached a certain number the bird sprite texture will update and change to another color. Instead of using the spritebatch and changing the color through tinting I wanted to create a new texture(png file).
The problem is since it is a sprite it needs to be animated so the wings will flap. When I try and update the texture at runtime it will only work but the animation wont play.
Here is my bird class:
public class Bird {
private static final int GRAVITY = -15;
private static final int MOVEMENT = 100;
private Vector3 position;
private Vector3 velocity;
private Rectangle bounds;
private Animation birdAnimation;
private Texture birdTexture;
private TextureRegion textureRegion;
private Sound flap;
public Bird(int x, int y){
position = new Vector3(x, y, 0);
velocity = new Vector3(0, 0, 0);
textureRegion = new TextureRegion(returnTexture());
birdAnimation = new Animation(textureRegion, 3, 0.5f);
bounds = new Rectangle(x, y, returnTexture().getWidth() / 3, returnTexture().getHeight());
flap = Gdx.audio.newSound(Gdx.files.internal("sfx_wing.ogg"));
}
public void update(float dt){
textureRegion = new TextureRegion(returnTexture());
birdAnimation = new Animation(textureRegion, 3, 0.5f);
birdAnimation.update(dt);
if(position.y > 0){
velocity.add(0, GRAVITY, 0);
}
velocity.scl(dt);
position.add(MOVEMENT * dt, velocity.y, 0);
if(position.y < 0){
position.y = 0;
}
velocity.scl(1/dt);
bounds.setPosition(position.x, position.y);
}
public TextureRegion getTexture() {
return birdAnimation.getFrame();
}
public Texture returnTexture(){
if(PlayState.score > 1){
return birdTexture = new Texture("birdanimation1.png");
}else{
return birdTexture = new Texture("birdanimation.png");
}
}
public Vector3 getPosition() {
return position;
}
public void jump(){
velocity.y = 250;
flap.play(0.15f);
}
public Rectangle getBounds(){
return bounds;
}
public void dispose(){
returnTexture().dispose();
flap.dispose();
}
}
Here is my animation class:
public class Animation {
private Array<TextureRegion> frames;
private float maxFrameTime;
private float currentFrameTime;
private int frameCount;
private int frame;
public Animation(TextureRegion region, int frameCount, float cycleTime){
frames = new Array<TextureRegion>();
int frameWidth = region.getRegionWidth() / frameCount;
for(int i = 0; i < frameCount; i++){
frames.add(new TextureRegion(region, i * frameWidth, 0, frameWidth, region.getRegionHeight()));
}
this.frameCount = frameCount;
maxFrameTime = cycleTime / frameCount;
frame = 0;
}
public void update(float dt){
currentFrameTime += dt;
if(currentFrameTime > maxFrameTime){
frame++;
currentFrameTime = 0;
}
if(frame >= frameCount){
frame = 0;
}
}
public TextureRegion getFrame(){
return frames.get(frame);
}
}
Here's my render code in my play state:
#Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(bg, cam.position.x - (cam.viewportWidth /2), 0);
sb.draw(bird.getTexture(), bird.getPosition().x, bird.getPosition().y);
for(Tube tube : tubes){
sb.draw(tube.getTopTube(), tube.getPosTopTube().x, tube.getPosTopTube().y);
sb.draw(tube.getBottomTube(), tube.getPosBotTube().x, tube.getPosBotTube().y);
}
sb.draw(ground, groundPos1.x, groundPos1.y);
sb.draw(ground, groundPos2.x, groundPos2.y);
font.draw(sb, text, cam.position.x - gl.width / 2, cam.position.y + 200);
sb.end();
}
If you need any other classes just ask. I'm probably making a stupid mistake or just coding it entirely wrong for what I'm trying to achieve.
Thanks, Jackson
You need to NOT load your textures every single frame.
libgdx has its own Animation class so you don't need to make your own.
Here is an example on animation from libgdx's github:
2D Animation
To make it simple, just have 2 animaitons on Bird and switch between them when you need to.