Что может заставить спрайт остановить направленное движение при столкновении в двухмерной игре (спрайт все еще оживляет)? - PullRequest
0 голосов
/ 07 января 2020

!! Это не мой код - я использую это, чтобы учиться !! Однако я не понимаю, что может заставить спрайт остановить его направленное движение при столкновении с объектом «КАМЕНЬ». Вся двумерная игра будет запущена, и спрайт работает правильно, но когда я подхожу ближе к концу экрана или слишком близко к камню, я застреваю на месте. Я не мог найти объяснение, которое я полностью понял. Я заранее прошу прощения, если это кому-то тривиальный вопрос.

Basi c Solid Класс плитки:

public class BasicSolidTile extends BasicTile {

    public BasicSolidTile(int id, int x, int y, int tileColour) {

        super(id, x, y, tileColour);
        this.solid = true;
    }

}

Класс плитки:

public abstract class Tile {

    public static final Tile[] tiles = new Tile[256];
    public static final Tile VOID = new BasicSolidTile(0, 0, 0, Colours.get(000, -1, -1, -1));
    public static final Tile STONE = new BasicSolidTile(1, 1, 0, Colours.get(-1, 333, -1, -1));
    public static final Tile GRASS = new BasicTile(2, 2, 0, Colours.get(-1, 131, 141, -1));

    protected byte id;
    protected boolean solid;
    protected boolean emitter;

    public Tile(int id, boolean isSolid, boolean isEmitter) {

        this.id = (byte) id;

        if (tiles[id] != null) {
            throw new RuntimeException("Duplicate tile id on" + id);
        }
        this.solid = isSolid;
        this.emitter = isEmitter;

        tiles[id] = this;
    }

    public byte getId() {
        return id;
    }

    public boolean isSolid() {
        return solid;
    }

    public boolean isEmitter() {
        return emitter;
    }

    public abstract void render(Screen screen, Level level, int x, int y);
}

Mob Class:

public abstract class Mob extends Entity {

    protected String name;
    protected int speed;
    protected int numSteps = 0;
    protected boolean isMoving;
    protected int movingDir = 1;
    protected int scale = 1;

    public Mob(Level level, String name, int x, int y, int speed) {
        super(level);

        this.name = name;
        this.x = x;
        this.y = y;
        this.speed = speed;

    }

    public void move(int xa, int ya) {

        // you want to check if they are not zero

        if (xa != 0 && ya != 0) {
            move(xa, 0);
            move(0, ya);
            numSteps--;
            return;
        }

        numSteps++;

        if (!hasCollided(x, y)) {
            if (ya < 0)
                movingDir = 0;
            if (ya > 0)
                movingDir = 1;
            if (xa < 0)
                movingDir = 2;
            if (xa > 0)
                movingDir = 3;

            x += xa * speed;
            y += ya * speed;

        }
    }

    public abstract boolean hasCollided(int xa, int ya);


    protected boolean isSolidTile(int xa, int ya, int x, int y) {

        if (level == null) {
            return false;
        }
        Tile lastTile = level.getTile((this.x + x) >> 3, (this.y + y) >> 3);
        Tile newTile = level.getTile((this.x + x + xa) >> 3, (this.y + y + ya) >> 3);

        if (!lastTile.equals(newTile) && newTile.isSolid()) {
            return true;
        }
        return false;

    }
    public String getName() {
        return name;
    }
}

Уровень класса:

public class Level {

    // array of id's
    private byte[] tiles;
    public int width;
    public int height;
    public List<Entity> entities = new ArrayList<Entity>();

    public Level(int width, int height) {

        tiles = new byte[width * height];
        this.width = width;
        this.height = height;
        this.generateLevel();
    }

    public void generateLevel() {

        for (int y = 0; y < height; y++) {

            for (int x = 0; x < width; x++) {

                if (x * y %10 < 7) {

                    tiles[x + y * width] = Tile.GRASS.getId();

                } else {

                    tiles[x + y * width] = Tile.STONE.getId();
                }
            }
        }
    }

    public void tick() {

        // loop through all the vars if you dont need an index var
        for (Entity e : entities) {
            e.tick();
        }

    }

    public void renderTiles(Screen screen, int xOffset, int yOffset) {

        if (xOffset < 0)
            xOffset = 0;
        if (xOffset > ((width << 3) - screen.width))
            xOffset = ((width << 3) - screen.width);

        if (yOffset < 0)
            yOffset = 0;
        if (yOffset > ((height << 3) - screen.height))
            yOffset = ((height << 3) - screen.height);

        screen.setOffset(xOffset, yOffset);

        for (int y = (yOffset >> 3); y < (yOffset + screen.height >> 3) + 1; y++) {

            for (int x = (xOffset >> 3); x < (xOffset + screen.width >> 3) + 1; x++) {

                getTile(x, y).render(screen, this, x << 3, y << 3);

            }
        }
    }

    public void renderEntities(Screen screen) {
        for (Entity e : entities) {
            e.render(screen);
        }

    }

    public Tile getTile(int x, int y) {

        if (0 > x || x >= width || 0 > y || y >= height)
            return Tile.VOID;

        return Tile.tiles[tiles[x + y * width]];
    }

    public void addEntity(Entity entity) {
        this.entities.add(entity);
    }
}

Класс игрока:

public class Player extends Mob {

    private InputHandler input;
    private int colour = Colours.get(-1, 111, 145, 543);
    private int scale = 1;

    public Player(Level level, int x, int y, InputHandler input) {
        super(level, "Player", x, y, 1);
        this.input = input;
    }

    public void tick() {

        int xa = 0;
        int ya = 0;

        if (input.up.isPressed()) {
            ya--;
        }

        if (input.down.isPressed()) {
            ya++;
        }

        if (input.left.isPressed()) {
            xa--;
        }

        if (input.right.isPressed()) {
            xa++;
        }

        if (xa != 0 || ya != 0) {
            move(xa, ya);
            isMoving = true;
        } else {
            isMoving = false;
        }
        this.scale = 1;

    }

    public void render(Screen screen) {
        int xTile = 0;
        int yTile = 28;

        int walkingSpeed = 4;
        int flipTop = (numSteps >> walkingSpeed) & 1;
        int flipBottom = (numSteps >> walkingSpeed) & 1;

        if (movingDir == 1) {
            xTile += 2;
        } else if (movingDir > 1) {
            xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2;
            flipTop = (movingDir - 1) % 2;
        }

        int modifier = 8 * scale;
        int xOffset = x - modifier / 2;
        int yOffset = y - modifier / 2 - 4;

        // upper body
        screen.render(xOffset + (modifier * flipTop), yOffset, xTile + yTile * 32, colour, flipTop, scale);
        screen.render(xOffset + modifier - (modifier * flipTop), yOffset, (xTile + 1) + yTile * 32, colour, flipTop, scale);

        // lower body
        screen.render(xOffset + (modifier * flipBottom), yOffset + modifier, xTile + (yTile + 1) * 32, colour, flipBottom, scale);
        screen.render(xOffset + modifier - (modifier * flipBottom), yOffset + modifier, (xTile + 1) + (yTile + 1) * 32, colour, flipBottom,
                scale);

    }

    public boolean hasCollided(int xa, int ya) {

        int xMin = 0;
        int xMax = 7;
        int yMin = 3;
        int yMax = 7;

        for (int x = xMin; x < xMax; x++) {
            if (isSolidTile(xa, ya, x, yMin)) {
            return true;
        }
    }

        for (int x = xMin; x < xMax; x++) {
            if (isSolidTile(xa, ya, x, yMax)) {
            return true;
        }
    }

        for (int y = yMin; y < yMax; y++) {
            if (isSolidTile(xa, ya, xMin, y)) {
            return true;
        }
    }

        for (int y = yMin; y < yMax; y++) {
            if (isSolidTile(xa, ya, xMax, y)) {
            return true;
        }
    }

        return false;
    }

}

1 Ответ

0 голосов
/ 07 января 2020

Хорошо. Это заняло у меня навсегда, но это было просто исправить. Все, что мне нужно было сделать, это изменить "(x, y)" на "(xa, ya)"

    if (!hasCollided(xa, ya)) {
        if (ya < 0)
            movingDir = 0;
        if (ya > 0)
            movingDir = 1;
        if (xa < 0)
            movingDir = 2;
        if (xa > 0)
            movingDir = 3;

        x += xa * speed;
        y += ya * speed;

    }

}
...