Codename One动画发生了什么?我使用了很多,截至12月,我的应用程序已不再有效。当我在六月离开时,一切都很好(并且已经超过一年了。)
我的应用程序是一个草稿(跳棋)游戏,自2013年起在应用程序商店中可用。在看到CN1扑克演示之后,我完全重写了我的GUI,因为我想将这些动画添加到我的应用程序中。现在发生的是我突然得到索引超出限制的异常。我把它缩小到以下情况:
cont.addComponent(comp);
...
...
cont.getComponent(0); <-- index out of bound exception: 0 out of 0
我相信,六月份我已经使用了newVM = true,现在是默认值。我尝试通过添加
来解决问题cont.animateLayoutAndWait(100);
在addComponent调用之后。这修复了索引超出绑定的异常,但现在应用程序在短时间工作正常后随机崩溃。我试过,但一直无法找到问题的根源。 CN1中的某些内容发生了变化,因此我的代码不再有效。 (另请参阅旧论坛,搜索&#34;草稿&#34;,我在其中发布了我的基本设计的完整列表。)
我研究了新的Solitaire演示,它具有我需要的大部分动画功能。在我的所有iOS / Android设备上,Solitaire的应用商店版本运行良好。一个小错误是可以拖动一组卡片,包括一些朝下的卡片,这些卡片在拖动操作期间面朝上。另外很难准确地拿出适量的卡片。拖动一组卡片也会在屏幕上留下白色痕迹,看起来并不是很好。这也发生在模拟器中。
作为一项实验,我重新设计了我的GUI布局以完全类似于纸牌代码:两层按钮,唯一的区别是我使用GridLayout(10,10),其中Solitaire使用SolitaireLayout()。这是有效的,除了一件事:如果检查员向下移动板,它正确地移动到其他检查器,但如果检查器向上移动板,它移动到其他检查器。
我的代码如下所示:
Button pc = (Button)piecesCnt.getComponentAt(a1);
Button to = (Button)piecesCnt.getComponentAt(a2);
piecesCnt.removeComponent(pc);
piecesCnt.addComponent(a1, createPieceButton(Piece.EMPTY_PIECE, true));
piecesCnt.removeComponent(to);
piecesCnt.addComponent(a2, pc);
piecesCnt.animateLayoutAndWait(1000);
所以似乎按钮总是按照GridLayout顺序绘制,而我希望动画(移动)按钮最后/顶部绘制,就像纸牌中的移动卡一样。
在SolitaireLayout和GridLayout中处理动画是否有区别?如果是这样,可以在动画逻辑中更改吗?否则我必须添加一个额外的动画层和大量的开销。
在Android上,动画(动作)无法正常工作。因此,我决定使用当前的CN1版本(插件3.2.6,libs 2016-01-11)在我的设备上自行构建和测试Solitaire演示。我将动画更改为慢了10倍,以便更好地了解正在发生的事情。在模拟器中,布局和动画效果很好,但在我的iOS和Android设备上存在很多问题。
模拟器(Windows 7,NetBeans 8.0.2): - 我删除了字体图标,因为它们丢失了。 - 但是如何进入汉堡包菜单?我没有看到3个点,甚至没有空间。 - 有时候可以用一些下注卡来拖动一组牌;拖着他们暂时翻转面朝上。 - 自动播放似乎总是起作用。 (并非所有动作都被播放。)
在iOS 9.2(iPad 4),iOS 8.4(iPhone 4)上: - [?]显示在汉堡菜单复选框中。 - 启动后,画面背景卡片后退跳转到容器/屏幕的底部。 - 有时,在甲板上的动画片中,最右边的画面中的卡片暂时朝上,而面朝上的卡片面朝下翻转。然而,最终的交易状态是正确的。 - 撤消/重做:有时会在甲板0上形成面朝上的牌,在甲板1上面朝下。 - 重做有时会跳跃&#39;到新的布局而不是动画。 仅限iPhone: - 一系列自动播放动作留下了不稳定的基础状态:顶级牌心-J,俱乐部-10,俱乐部-K,钻石-Q;即两张不同基础筹码上的俱乐部牌。
在Android 5.1.1(Nexus 7)上存在更多问题。 - 来自甲板的交易动画不是很好看。卡片插入(滑动到)桌面堆叠的底部,因此它们可以在其他卡片下方滑动。移动的卡片应朝下,但通常朝上,始终显示第一张卡片送到画面1.最右边的画面卡片暂时朝上。最后,面朝上的卡片面朝下翻转,然后再翻转。然而,最终的交易状态是正确的。 - 连续多次移动时,自动播放也不正确。在动画期间,面朝上的几张基础卡暂时改变其卡片值(正面)。此外,移动的卡片在基础卡片下面滑动(有时会超过,但这是例外)。 - 完成游戏后,完成的屏幕已损坏,因为文本似乎显示未覆盖但在卡片下方(在大的白色空间中),这些仅在屏幕顶部的一小部分中部分可见。 - 开始一个新游戏经常失败,因为没有开始从甲板交易;屏幕显示一个甲板和四个国王在基础上空,画面空。当敲击牌组时,会发出一张牌并显示完成的顺序。有时重复此操作会导致成功开始新游戏。
所有这些已经花费了很多时间,我仍然没有让我的应用再次工作,这非常令人沮丧。对于这个主题有这么多麻烦,即使使用下载的演示应用程序,使用Codename One构建这种类型的应用程序感觉就像在流沙上构建一样。请帮忙!
答案 0 :(得分:1)
一旦你遇到麻烦而不是在帖子上努力工作,你可能应该问过这个问题。是的,我们确实做了一个主要的兼容性破坏性更改,作为长期动画问题的错误修复的一部分(并行运行的动画可能会发生碰撞)。
这引入了一些冲突,但减少了设备/模拟器之间的不一致性,这总是一件好事。
我们在此宣布:https://www.codenameone.com/blog/new-animation-manager.html
现在创建便携式动画实际上更简单,因为所有内容都会同步以避免动画冲突,例如如果在动画进行过程中进行Component.removeComponent()
,它将隐式添加到动画队列中,并在动画完成后执行,而不是立即执行。
要推迟你的下一个动作,直到我们有动画:
form.getAnimationManager().flushAnimation(() -> doThisAfterAnimation());
更简单,没有特殊情况的全局锁定。
有点难以&#34;端口&#34;代码直接用于新方法,但看起来你的动画逻辑依赖于动画花费1000毫秒并且当方法返回时它完全结束,这可能并非总是如此(因为添加/删除调用或其他逻辑可能会妨碍) 。
过去,保证动画完成的唯一方法是将它们分开,但现在您可以使用flushAnimation
确保所有动画都已完成。请记住,一些不明确动画的东西现在可能会偶然变成动画,例如如果在调用动画时正在进行动画,则添加/删除组件将成为动画...
答案 1 :(得分:0)
对不起,我错过了12月16日新动画经理的博客文章。纸牌演示日期是10月8日,我检查了12月31日的开发者指南,所以我认为我是最新的。尽管如此,我还不清楚如何使用新的动画管理器。 Januari 11的新开发人员指南没有说明这个主题,你的回答/博客文章也不是很精细。
如果将更新Solitaire演示以与新的动画管理器一起工作,它也会有很大帮助。
现在我的问题是:
1)如何重写以下代码以使用新的动画管理器?这是一个现实的场景,因为我的动画有多个应该连续执行的步骤。
// simplified code (background layer omitted)
public void start() {
if(current != null){
current.show();
return;
}
Form form = new Form("Draughts 2");
Container piecesCnt = new Container(new GridLayout(10, 10));
for (int i=0; i<100; i++) {
piecesCnt.addComponent(createPieceButton(piece(i), true));
}
form.addComponent(piecesCnt);
form.show();
new UITimer(() -> {
testAnimation(piecesCnt, 0,9 , 9,0); // moves UNDER other pieces
testAnimation(piecesCnt, 9,0 , 0,9); // " OVER " "
testAnimation(piecesCnt, 1,0 , 9,8); // " OVER " "
testAnimation(piecesCnt, 9,8 , 1,0); // " UNDER " "
}).schedule(1500, false, form);
}
private void testAnimation(Container piecesCnt, int x1,int y1, int x2,int y2) {
int a1 = 10 * y1 + x1;
int a2 = 10 * y2 + x2;
Button pc = (Button)piecesCnt.getComponentAt(a1);
Button to = (Button)piecesCnt.getComponentAt(a2);
piecesCnt.removeComponent(pc);
piecesCnt.addComponent(a1, createPieceButton(Piece.EMPTY_PIECE, true));
piecesCnt.removeComponent(to);
piecesCnt.addComponent(a2, pc);
piecesCnt.animateLayoutAndWait(1000);
}
2)重写这个也解决了一块(棋子)移动而不是其他棋子的问题?
3)如何在两个testAnimation调用之间暂停? (显然不是通过睡觉。)
更新2016-01-14(另请参阅评论部分):
我用flushAnimations尝试了两件事:
1)使用如下函数:
private void flushAnimations(Form f) {
f.getAnimationManager().flushAnimation(() -> {});
}
并在连续的动画之间调用它。这不起作用。
2)嵌套flushAnimations:
testAnimation(piecesCnt, 0,9 , 9,0);
f.getAnimationManager().flushAnimation(() -> {
testAnimation(piecesCnt, 9,0 , 0,9);
f.getAnimationManager().flushAnimation(() -> {
testAnimation(piecesCnt, 1,0 , 9,8);
f.getAnimationManager().flushAnimation(() -> {
testAnimation(piecesCnt, 9,8 , 1,0);
});
});
});
这似乎适用于iOS但不适用于我的Android设备:通常在第二个动画之后,屏幕会闪烁并跳转到下一个状态而不是动画。除此之外,它不是一个很好的解决方案。
然后我尝试了UITimer解决方案:
blockUI(piecesCnt);
new UITimer(() -> { testAnimation(piecesCnt, 0,9 , 9,0); }).schedule(2000, false, f);
new UITimer(() -> { testAnimation(piecesCnt, 9,0 , 0,9); }).schedule(3500, false, f);
new UITimer(() -> { testAnimation(piecesCnt, 1,0 , 9,8); }).schedule(5000, false, f);
new UITimer(() -> { testAnimation(piecesCnt, 9,8 , 1,0); }).schedule(6500, false, f);
new UITimer(() -> {
unblockUI(piecesCnt);
}).schedule(8000, false, f);
private boolean blocked = false;
private void blockUI(Container piecesCnt) {
blocked = true;
int n = piecesCnt.getComponentCount();
for (int i=0; i<n; i++) {
piecesCnt.getComponentAt(i).setDraggable(false);
}
}
private void unblockUI(Container piecesCnt) {
...
}
这有效,但也不是一个非常理想的解决方案。我有一个功能&#39;自动播放&#39;重放包含> 100个动作的整个游戏,每个动作由1个或多个动画步骤组成。用户可以通过按停止按钮来中断此过程。
我非常希望看到扑克和纸牌(自动播放!)演示应如何使用新的动画处理进行编码。
请花一点时间关注此链接,了解我所说的功能:http://toernooibase.kndb.nl/opvraag/applet.php?taal=1&kl=46&Id=4579&r=10&jr=16&wed=845502。只需按下电路板下方的自动播放按钮(&#39;&gt;&#39;)即可。 (我的应用程序也可以玩游戏,您可以将其设置为每次移动1分钟,在此期间GUI被阻止。)
我看到开发者指南已于1月13日更新,现在有一个关于休闲游戏编程的章节/附录。这很好,虽然它列出的CN1Poker版本仍然无法在Android设备上正常工作:交易卡动画显示卡片大多是跳跃,有时滑动到他们的位置。 (它在模拟器和iOS设备上运行良好。)
你怎么能说现在创建一个便携式动画实际上更简单?&#39;?我认为在我的情况下它实际上变得更加困难。我需要一种旧方法的替代品,它也用于扑克和纸牌演示:使用animateLayoutAndWait并且在动画期间没有添加/删除动作(也由程序逻辑确定)。
作为基本订阅者(3年后)我必须使用最新的CN1版本,但是对于当前的CN1版本,我不再知道如何编写代码。我认为这是一个非常基本的问题,因为所有游戏都使用这样的功能。