对于我在学校的 A 级计算项目,我一直在创建一个与 Mega-Man 游戏风格相似的 2D 平台模型。到目前为止,我已经获得了一些菜单和播放器方法,例如碰撞检测、移动和动画。我所有的播放器动画都在一个大小不同的精灵表中,因此它们并不完全相同(79x136、118x128、88x136 等)。
这是我的具体问题:
但是,在玩游戏并通过移动和跳跃观看动画时,动画的尺寸似乎被拉伸或压缩成特定的尺寸,我认为是 118x140。
我这样说是因为当玩家静止不动时,其中一个静止动画以适当的尺寸正确显示,并且与此分辨率相匹配,并且似乎所有其他动画都试图适应相同的尺寸。
我浏览了互联网和这个网站,看看是否有人有类似的问题,但似乎没有人与这个问题直接相关,因此我要求解决这个问题。
这是我的 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();
}
}
我希望这可以帮助找到解决方案。