0

学校での A レベル コンピューティング プロジェクトでは、ロックマン ゲームに似たスタイルの 2D プラットフォームを作成しています。これまでのところ、衝突検出、移動、アニメーションなどのいくつかのメニューとプレーヤー メソッドが動作するようになりました。私のすべてのプレーヤー アニメーションは、サイズが異なる単一のスプライト シートにあるため、すべて同じではありません (79x136、118x128、88x136 など)。

これは私の特定の問題です:

ただし、ゲームをプレイして移動したりジャンプしたりしてアニメーションを見ていると、アニメーションの寸法が特定のサイズに引き伸ばされたり圧縮されたりしているように見えます。これは 118x140 だと思います。

これは、プレイヤーが静止しているときの静止アニメーションの 1 つが適切なサイズで正しく表示され、この解像度と一致し、他のすべてのアニメーションが同じサイズに収まるように見えるためです。

インターネットとこのサイトを調べて、誰かが同様の問題を抱えているかどうかを確認しましたが、この問題に直接関係しているようには見えないため、これに対する解決策を求めています.

これは、私の Player.java ファイルで使用されるコードで、ここで私のプレーヤーのすべての側面が定義されています。

package com.ultimate.robot.entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.math.Vector2;

public class Player extends Sprite implements InputProcessor {

    /** the movement velocity */
    private Vector2 velocity = new Vector2();

    private float speed = 240 * 2, gravity = 180 * 1.8f, animationTime = 0;

    private boolean canJump;

    private Animation still, left, right, jump, fall;
    private TiledMapTileLayer collisionLayer;

    private String blockedKey = "blocked";

    public Player(Animation still, Animation left, Animation right, 
                  Animation jump, Animation fall, TiledMapTileLayer 
                  collisionLayer) {

        super(still.getKeyFrame(0));
        this.still = still;
        this.left = left;
        this.right = right;
        this.jump = jump;
        this.fall = fall;
        this.collisionLayer = collisionLayer;
    }

    public void draw(Batch spriteBatch) {
        update(Gdx.graphics.getDeltaTime());
        super.draw(spriteBatch);
    }

    public void update(float delta) {
        // apply gravity
        velocity.y -= gravity * delta;

        // clamp velocity
        if(velocity.y > speed)
            velocity.y = speed;
        else if(velocity.y < -speed)
            velocity.y = -speed;

        // save old position
        float oldX = getX(), oldY = getY();
        boolean collisionX = false, collisionY = false;

        // move on x
        setX(getX() + velocity.x * delta);

        if(velocity.x < 0) // going left
            collisionX = collidesLeft();
        else if(velocity.x > 0) // going right
            collisionX = collidesRight();

        // react to x collision
        if(collisionX) {
            setX(oldX);
            velocity.x = 0;
        }

        // move on y
        setY(getY() + velocity.y * delta * 5f);

        if(velocity.y < 0) // going down
            canJump = collisionY = collidesBottom();
        else if(velocity.y > 0) // going up
            collisionY = collidesTop();

        // react to y collision
        if(collisionY) {
            setY(oldY);
            velocity.y = 0;
        }

        // update animation
        animationTime += delta;
        setRegion(velocity.x < 0 ? left.getKeyFrame(animationTime) :
                  velocity.x > 0 ? right.getKeyFrame(animationTime) :
                  velocity.y > 0 ? jump.getKeyFrame(animationTime) : 
                  velocity.y < 0 ? fall.getKeyFrame(animationTime) : 
                  still.getKeyFrame(animationTime));
    }

    private boolean isCellBlocked(float x, float y) {
        Cell cell = collisionLayer.getCell(
              (int) (x / collisionLayer.getTileWidth()), 
              (int) (y / collisionLayer.getTileHeight()));

        return cell != null && cell.getTile() != null 
           && cell.getTile().getProperties().containsKey(blockedKey);
    }

    public boolean collidesRight() {
        for(float step = 0; step < getHeight();
          step += collisionLayer.getTileHeight() / 2)
            if(isCellBlocked(getX() + getWidth(), getY() + step))
                return true;
        return false;
    }

    public boolean collidesLeft() {
        for(float step = 0; step < getHeight(); 
         step += collisionLayer.getTileHeight() / 2)
            if(isCellBlocked(getX(), getY() + step))
                return true;
        return false;
    }

    public boolean collidesTop() {
        for(float step = 0; step < getWidth();
          step += collisionLayer.getTileWidth() / 2)
            if(isCellBlocked(getX() + step, getY() + getHeight()))
                return true;
        return false;

    }

    public boolean collidesBottom() {
        for(float step = 0; step < getWidth(); 
          step += collisionLayer.getTileWidth() / 2)
            if(isCellBlocked(getX() + step, getY()))
                return true;
        return false;
    }

    public Vector2 getVelocity() {
        return velocity;
    }

    public void setVelocity(Vector2 velocity) {
        this.velocity = velocity;
    }

    public float getSpeed() {
        return speed;
    }

    public void setSpeed(float speed) {
        this.speed = speed;
    }

    public float getGravity() {
        return gravity;
    }

    public void setGravity(float gravity) {
        this.gravity = gravity;
    }

    public TiledMapTileLayer getCollisionLayer() {
        return collisionLayer;
    }

    public void setCollisionLayer(TiledMapTileLayer collisionLayer) {
        this.collisionLayer = collisionLayer;
    }

    @Override
    public boolean keyDown(int keycode) {
        switch(keycode) {
        case Keys.SPACE:
            if(canJump) {
                velocity.y = speed / 3f;
                canJump = false;
                animationTime = 0;
            }
            break;
        case Keys.LEFT:
            velocity.x = -speed;
            animationTime = 0;
            break;
        case Keys.RIGHT:
            velocity.x = speed;
            animationTime = 0;
        }
        return true;
    }

    @Override
    public boolean keyUp(int keycode) {
        switch(keycode) {
        case Keys.LEFT:
        case Keys.RIGHT:
            velocity.x = 0;
            animationTime = 0;
        }
        return true;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, 
                             int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, 
                           int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, 
                                int pointer) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        return false;
    }

}

この次のコードは、プレーヤーのテクスチャ アトラスとして機能し、領域を含む playersheet.sprites ファイルで使用されます。

playersheet.png
format: RGBA8888
filter: Nearest,Nearest
repeat: none
playerstill
  rotate: false
  xy: 363, 272
  size: 118, 140
  orig: 59, 70
  offset: 0, 0
  index: -1
playerstill
  rotate: false
  xy: 867, 152
  size: 118, 128
  orig: 59, 64
  offset: 0, 0
  index: -1
playerrun
  rotate: false
  xy: 688, 276
  size: 79, 136
  orig: 39, 68
  offset: 0, 0
  index: -1
playerrun
  rotate: false
  xy: 481, 272
  size: 92, 140
  orig: 46, 70
  offset: 0, 0
  index: -1
playerrun
  rotate: false
  xy: 767, 280
  size: 132, 132
  orig: 66, 66
  offset: 0, 0
  index: -1
playerrun
  rotate: false
  xy: 644, 140
  size: 88, 136
  orig: 44, 68
  offset: 0, 0
  index: -1
playerrun
  rotate: false
  xy: 422, 132
  size: 98, 140
  orig: 49, 70
  offset: 0, 0
  index: -1
playerrun
  rotate: false
  xy: 732, 144
  size: 135, 132
  orig: 67, 66
  offset: 0, 0
  index: -1
playershoot
  rotate: false
  xy: 592, 0
  size: 116, 136
  orig: 58, 68
  offset: 0, 0
  index: -1
playerjump
  rotate: false
  xy: 0, 44
  size: 74, 184
  orig: 74, 184
  offset: 0, 0
  index: -1
playerjumpshoot
  rotate: false
  xy: 0, 228
  size: 107, 184
  orig: 107, 184
  offset: 0, 0
  index: -1
playerfall
  rotate: false
  xy: 186, 76
  size: 108, 168
  orig: 108, 168
  offset: 0, 0
  index: -1
playerfallshoot
  rotate: false
  xy: 107, 244
  size: 124, 168
  orig: 124, 168
  offset: 0, 0
  index: -1
playerrunshoot
  rotate: false
  xy: 294, 132
  size: 128, 140
  orig: 128, 140
  offset: 0, 0
  index: -1
playerrunshoot
  rotate: false
  xy: 573, 276
  size: 115, 136
  orig: 115, 136
  offset: 0, 0
  index: -1
playerrunshoot
  rotate: false
  xy: 294, 0
  size: 150, 132
  orig: 150, 132
  offset: 0, 0
  index: -1
playerrunshoot
  rotate: false
  xy: 520, 136
  size: 124, 136
  orig: 124, 136
  offset: 0, 0
  index: -1
playerrunshoot
  rotate: false
  xy: 231, 272
  size: 132, 140
  orig: 132, 140
  offset: 0, 0
  index: -1
playerrunshoot
  rotate: false
  xy: 444, 0
  size: 148, 132
  orig: 148, 132
  offset: 0, 0
  index: -1
playerblock
  rotate: false
  xy: 708, 8
  size: 136, 132
  orig: 136, 132
  offset: 0, 0
  index: -1
playerduck
  rotate: false
  xy: 899, 304
  size: 96, 108
  orig: 96, 108
  offset: 0, 0
  index: -1
playerhurt
  rotate: false
  xy: 844, 48
  size: 136, 96
  orig: 136, 96
  offset: 0, 0
  index: -1
playervictory
  rotate: false
  xy: 74, 48
  size: 112, 180
  orig: 112, 180
  offset: 0, 0
  index: -1

そして最後に、このコードは、レベルのすべての要素を含み、プレーヤーを作成する LevelOne.java ファイルで使用されます。

package com.ultimate.robot.levels;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.ultimate.robot.entities.Player;

public class LevelOne implements Screen {

    private TiledMap map;
    private OrthogonalTiledMapRenderer renderer;
    private OrthographicCamera camera;
    private Music level1music;
    private Sprite desert, blueSky;
    private TextureAtlas playerAtlas;
    private Player player;

    @Override
    public void show() {
        map = new TmxMapLoader().load("maps/levelone.tmx");

        playerAtlas = new TextureAtlas("Sprites/playersheet.sprites");
        Animation still, left, right, jump, fall;
        still = new Animation(1/2f, playerAtlas.findRegions("playerstill"));
        left = new Animation(1 /6f, playerAtlas.findRegions("playerrun"));
        right = new Animation(1 /6f, playerAtlas.findRegions("playerrun"));
        jump = new Animation(1 /6f, playerAtlas.findRegions("playerjump"));
        fall = new Animation(1 /6f, playerAtlas.findRegions("playerfall"));
        still.setPlayMode(Animation.PlayMode.LOOP);
        left.setPlayMode(Animation.PlayMode.LOOP);
        right.setPlayMode(Animation.PlayMode.LOOP);
        jump.setPlayMode(Animation.PlayMode.NORMAL);
        fall.setPlayMode(Animation.PlayMode.NORMAL);

        player = new Player(still, left, right, jump, fall, 
                            (TiledMapTileLayer) map.getLayers().get(0));

        player.setPosition(5 * player.getCollisionLayer().getTileWidth(),
                         4 * player.getCollisionLayer().getTileHeight());

        // setting camera
        camera = new OrthographicCamera();

        // creating background
        desert = new Sprite(new Texture(
               Gdx.files.internal("Backgrounds/desert.png")));
        blueSky = new Sprite(new Texture(
               Gdx.files.internal("Backgrounds/bluesky.png")));

        // creating music
        level1music = Gdx.audio.newMusic(
               Gdx.files.internal("Music/level1.ogg"));

        // playing music
        level1music.setLooping(true);
        level1music.play();

        Gdx.input.setInputProcessor(player);

        renderer = new OrthogonalTiledMapRenderer(map);
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        camera.position.set(player.getX() + player.getWidth() / 2, 
                        player.getY() + player.getHeight() / 2, 0);

        camera.update();

        renderer.setView(camera);

        renderer.getBatch().begin();
        renderer.getBatch().draw(blueSky, 0, 0);
        renderer.getBatch().draw(desert, 0, 0);
        player.draw(renderer.getBatch());
        renderer.getBatch().end();

        renderer.render();
    }

    @Override
    public void resize(int width, int height) {
        camera.viewportWidth = width;
        camera.viewportHeight = height;
    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void hide() {
        dispose();
    }

    @Override
    public void dispose() {
        map.dispose();
        renderer.dispose();
        level1music.dispose();
        playerAtlas.dispose();
        desert.getTexture().dispose();
        blueSky.getTexture().dispose();
    }

}

これが解決策を見つけるのに役立つことを願っています。

4

2 に答える 2

0

心配しないでください。カスタム アニメーション クラスを使用して解決できましたが、別のチュートリアルに従っていると、引き伸ばされたアニメーションと圧縮されたアニメーションが修正されたようです。アニメーションが収まる必要があるテクスチャ領域を作成しますが、サイズを最大のアニメーションに設定して、すべてが領域内に収まるようにしました。多くのコードを書き直さなければなりませんでしたが、最終結果には問題ありません。

于 2015-01-25T14:48:32.140 に答える
0

いくつかのことを行うことができます.アルファチャネルのみが「より多くのメモリを消費する」場合は、すべて同じ画像を実行し、互いに異なるサイズにならないようにします.一方、アニメーションに特定の解像度がありyourSprite.size (w, h);、後者を機能させることができます.簡単に言えば、この解像度が変更された場合にスプライトにある画像を制御する関数を作成する必要があります。次に、スプ​​ライトのサイズを設定します。必要に応じてのみ変更し、サイズが変更されていない場合は設定を行いません。私が言いたいことを理解していただければ幸いです。

あなたのコメントの例:

たとえば、Gimpを開き、アルファチャネルを使用してサイズ118x140の画像を作成し、新しいレイヤーを作成して画像を貼り付け、必要な形式にエクスポートします。たとえば、png「レイヤーを下にマージして結合できます」しかし、表示してエクスポートする必要はありません。

inicial size before Gimp           size base 118x140 
 texture size 79x136        texture size 118x140 after export gimp 
 texture size 118x128       texture size 118x140 after export gimp 
 texture size 88x136        texture size 118x140 after export gimp 

yourSprite.size(118, 140);

于 2015-01-24T15:41:37.503 に答える