简体   繁体   中英

Java: Movement, Need to slow it down

Ok so I have been experimenting with java for a few weeks now, following both in class, and online tutorials. I made a simple game where squares fall towards the bottom of the screen, while the player controls a small ball, only moving on the x-axis and trys to avoid them.

The problem that I am having is that the squares start out falling too fast. Right now I have them set as follows:

    ix = 0;
    iy = 1;

Then in my move() method, I have the following:

    hitbox.x += ix;
    hitbox.y += iy;

In this example, ix and iy are both integers.

My first assumption was to change the ints to floats, then use:

    ix= 0;
    iy = 0.5;

and then:

 hitbox.x += ix;
 hitbox.y += 0.5f;

But this just freezes the objects in their tracks . I believe that this is because cords are taken as integers, so I figured that if I modified my getX() and getY() methods, maybe I could manipulate them somehow to use decimal numbers? But I am not quite sure how to. Any help/hints/solutions to this problem would be Greatly appreciated.

Here is some revelent code, let me know if anymore is needed!

Enemy Manager:

 public class EnemyManager {

private int amount;
private List<Enemy> enemies = new ArrayList<Enemy>();
private GameInJavaOne instance;

public EnemyManager(GameInJavaOne instance, int a){
    this.amount = a;
    this.instance = instance;
    spawn();
}

private void spawn(){
    Random random = new Random();
    int ss = enemies.size();
    // If the current amount of enemies is less than the desired amount, we spawn more enemies.
    if(ss < amount){
        for(int i = 0; i < amount - ss; i++){
             enemies.add(new Enemy(instance, random.nextInt(778), random.nextInt(100)+1));
        }
        // If its greater than the desired number of enemies, remove them.
    }else if (ss > 20){
        for(int i = 0; i < ss - amount; i++){
             enemies.remove(i);
        } 
    }
}

public void draw(Graphics g){
    update();
    for(Enemy e : enemies) e.draw(g);

}

private void update() {
    boolean re = false;
    for(int i = 0; i < enemies.size(); i ++){
        if(enemies.get(i).isDead()){
            enemies.remove(i);
            re = true;
        }

    }
    if(re) spawn();
}

public boolean isColliding(Rectangle hitbox){
    boolean c =false;
     for(int i = 0; i < enemies.size(); i ++){
         if(hitbox.intersects(enemies.get(i).getHitbox())) c = true;
        }
        return c;

}

 }

Entity:

 public abstract class Entity {

protected int x, y, w, h;
protected boolean removed = false;

public Entity(int x, int y){

    this.x = x;
    this.y = y;

}

public void Draw(Graphics g){

}

public int getX() { return x; }
public int getY() { return y; }
public int getH() { return h; }
public int getW() { return w; }




 }

and the enemy class:

 public class Enemy extends Entity{

private Rectangle hitbox;
private int ix, iy;
private boolean dead = false;
private GameInJavaOne instance;




public Enemy(GameInJavaOne instance, int x, int y){
    super(x, y);
    this.instance = instance;
    hitbox = new Rectangle(x, y, 32, 32);

    ix = 0;
    iy = 1;

}

private void move(){
    if(instance.getStage().isCollided(hitbox)){
        iy =0;
        dead = true;
    }
    hitbox.x += ix;
    hitbox.y += iy;
}


public boolean isDead() {return dead;}


public Rectangle getHitbox() {return hitbox; }


public void draw(Graphics g){
    move();
    g.setColor(Color.MAGENTA);
    g.fillRect(hitbox.x, hitbox.y, hitbox.height, hitbox.width);
}

 }

You are using a Rectangle class to represent the position of your box (even though you call it the hitbox), Rectangle does indeed have members x and y which are integers and so when you call

rectangle.x+=0.5f;

What you are really calling is rectangle.x+=(int)0.5f; and (int)0.5f==0 .

The Rectangle class is simply inappropriate for holding the position of the box if you want float precision. Consider holding the box's real position as a double or float and casting to int to render it.

So your rendering code would become;

g.fillRect((int)positionX,(int)positionY, hitbox.height, hitbox.width);

where positionX and positionY are doubles. (You could also use Vector2d if you'd prefer to keep x and y together)

Other points

  • You seem to be extending an Entity class with x , y , w and h and yet never use them, this seems dangerous, why are you extending Entity but recreating your own positional code.
  • Your game loop isn't shown, however, I can see that you hard code the change in x and y. This is presumably because in your game loop you 'ask for' some frame speed, say 60fps and assume you'll get it. This works fine on a resource rich system, but as soon as you have any resource shortage you will start getting frames that are shorter than 60fps. In most games you don't even notice this because it just makes a larger jump to compensate but here you assume 60fps. It is wise to get an actual frame time and multiply that by a velocity to get you change in x and y.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM