java - LibGdx - 我怎样才能不加载我的纹理每一帧?
问题描述
我对 Java 和 LibGdx 有点陌生,但是对于我的学校项目,我需要为 Player-Sprite 设置动画。对于每个玩家只有一个动画,我为此制作的 Methode 一切都很好,但现在我还需要一个行走、空闲和战斗动画。我设法让动画切换,但现在的问题是,每个动画只有一帧被显示。经过一些研究,我知道我需要停止每帧更新我的纹理,但我不知道该怎么做。到目前为止,我在更新之前尝试了一个简单的计时器,但这看起来很奇怪。这是我的代码:
public Player(){
img3 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_idle_anim_strip_4.png");
img = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_idle_anim_strip_4.png");
img1 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_run_anim_strip_6.png");
img2 = new Texture("platform_metroidvania asset pack v1.01/herochar sprites(new)/herochar_sword_attack_anim_strip_4.png");
animation();
changeCharacter();
}
public static void animation(){
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
img3 = img2;
amount = 3;
tileWidth = 32;
}else if(Gdx.input.isKeyPressed(Input.Keys.D) || Gdx.input.isKeyPressed(Input.Keys.A)){
img3 = img1;
tileWidth = 16;
amount = 3;
}else{
img3 = img;
amount = 3;
tileWidth = 16;
}
}
public static void changeCharacter(){
batch = new SpriteBatch();
regions = TextureRegion.split(img3, tileWidth, 16);
sprite = new Sprite(regions[0][0]);
sprite.setPosition(x,y);
Timer.schedule(new Timer.Task() {
@Override
public void run() {
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[0][frame]);
}
}, 0, 1 / 12f);
}
在 render() 中调用方法“动画”和“changeCharacter”。我知道在 LibGdx 中有更简单的解决方案,但我的其余代码基于此,我基本上必须重写整个项目......如果您需要任何其他类,请询问。我可能会问一个非常简单的事情,但我不知道该怎么做。
解决方案
您需要先重命名。
img3
看起来它的目的是作为指向 currentTextureSet 的指针。因此,当您初始化时,Player()
您可能希望重命名img3
为currentTextureSet
然后,而不是重复加载,herochar_idle_anim_strip_4.png
设置
currentTextureSet = img;
之后(您可能还想重命名img
,,,img1
和)。img2
idleTextureSet
runTextureSet
swordAttackTextureSet
除此之外,绝对摆脱您从渲染调用的 Timer.schedule 将在您不希望的后台线程中运行。
在此处查看资产包https://o-lobster.itch.io/platformmetroidvania-pixel-art-asset-pack?download如果这是同一个,则应从左到右选择图像,即x
不应递增y
。然而,看起来你增加了y
......
sprite.setRegion(regions[0][frame]);
并且不正确的数组访问被吞没了,因为在后台计时器任务中,你可以访问的唯一 textureRegion[0][0]
就是你只看到一个帧。
所以转储这个
Timer.schedule(new Timer.Task() {
@Override
public void run() {
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[0][frame]);
}
}, 0, 1 / 12f);
并替换为
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[frame][0]);
*编辑所以这意味着你的帧随着每次渲染而更新,这太快了。所以 - 简单易碎的方式 - (不是最好的 deltaTime 请阅读这篇优秀的文章https://gafferongames.com/post/fix_your_timestep/)。在没有时间的情况下,最简单的方法不是最好的方法是声明
long renderCallCount =0;
把上面的框架声明,然后在你的渲染方法
renderCallCount++; //One more render call
if (renderCallCount % 60 == 0) { //Should I update frame?
frame++;
if (frame > amount) {
frame = 0;
}
sprite.setRegion(regions[0][frame]);
}
因此,只要使用 mod 运算符https://www.edureka.co/blog/mod-method-in-java/renderCallCount
可整除,如果您的刷新率为 60hz,则每秒一次,那么您的帧就会增加。要每秒切换两次帧,请更改为. 这假设您的显示器只能以 60hz 运行。我认为您的应用程序可能取决于位置更新的刷新率时间,因此您可能希望将来根据文章中的一些想法对其进行更新。在具有更快帧速率的显示器上,一切都会(始终如一地)加速。60
60
30
推荐阅读
- c - 基于值的二叉搜索树复杂度
- javascript - 在 WebSocket 连接中获取 404
- r - data.table:查找每个组的子集的最小值
- python - sess.run 动态增加内存使用量
- c# - 如何在第一个循环 C# 后停止 PictureBox GIF 动画?
- apache-spark - Spark 按顺序执行连接,即使它们是在并行线程中提交的
- c# - 设置默认文件夹位置,然后给它一个从其他表单中选择路径的选项
- java - 如何将对象的 sql 时间转换为 java 时间?
- java - 在 JTextArea 中复制单击的行
- wcf - 调试时如何查看从 WCF 休息服务返回的 400 http 错误请求的原因