首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在onDraw中进行位置计算比在游戏循环线程中更快.为什么?

在onDraw中进行位置计算比在游戏循环线程中更快.为什么?
EN

Stack Overflow用户
提问于 2019-09-04 15:56:38
回答 2查看 217关注 0票数 0

我正在开发一个简单的游戏,它使用普通的安卓视图,而不是openGL或其他apis,只使用视图并在屏幕上移动它们。我有一个游戏循环,它调用AsteroidManager.updateAsteroidsPositions(),在所有屏幕小行星中迭代,计算它的位置。

之后,线程使用runOnUiThread()方法调用一个runOnUiThread方法,因为在Android中,您需要操纵主线程上的视图。AsteroidManager.invalidateAsteroids()方法简单地迭代所有小行星,并将x,y的位置设置为视图,并调用calls ()。

问题是,我发现如果将calculatePositions的逻辑放入视图的onDraw方法中,它会提供一个更平滑和更快的行为。这样,计算位置的逻辑在游戏循环线程中没有被执行.它是在主UI线程中完成的!

那件事怎么可能?它打破了所有游戏发展的逻辑..。关于在游戏循环线程上进行位置计算,而不是像主线程或onDraws这样的位置计算。

这是较慢的原始代码:

AsteroidManager类:

代码语言:javascript
运行
复制
public void updateAsteroidsPositions(){
    for (int i = 0; i<onScreenAsteroids.size(); i++){
        onScreenAsteroids.get(i).updatePosition();
    }
}

public void invalidateAsteroids() {
    for (int i = 0; i<onScreenAsteroids.size(); i++){
        onScreenAsteroids.get(i).invalidate();
    }
}

小行星类:

代码语言:javascript
运行
复制
public void updatePosition(){
    currentScale = (Float) scaleX.getAnimatedValue();
    factor = currentScale/MAX_SCALE;

    //adding a minimum of factor, because with too low factor the movement is not realistic
    if (factor < 0.250f)
        factor = 0.250f;

    x = x-((float)GameState.getInstance().getJoyX()*factor);
    y = y-((float)GameState.getInstance().getJoyY()*factor);
}

public void invalidate(){
    view.setX(x);
    view.setY(y);
    view.invalidate();
}

这是在Asteroid类中所做的技巧,它使游戏的行为变得更流畅和更快:

小行星类:

代码语言:javascript
运行
复制
public Asteroid(Bitmap bitmap, Context context) {
    view = new ImageView(context){
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            currentScale = (Float) scaleX.getAnimatedValue();
            factor = currentScale/MAX_SCALE;

            //adding a minimum of factor, because with too low factor the movement is not realistic
            if (factor < 0.250f)
                factor = 0.250f;

            x = x-((float)GameState.getInstance().getJoyX()*factor);
            y = y-((float)GameState.getInstance().getJoyY()*factor);

            view.setX(x);
            view.setY(y);
        }
    };
    view.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    view.setImageBitmap(bitmap);
}

public void updatePosition(){
}

public void invalidate(){
    view.invalidate();
}
EN

回答 2

Stack Overflow用户

发布于 2019-09-04 19:23:56

如果onScreenAsteroids列表中有太多的项,那么对每个条目执行updatePosition()都需要一些时间。尝试对它们使用单一的方法:

代码语言:javascript
运行
复制
public void updateAndInvalidateAsteroidsPositions(){
    for (int i = 0; i<onScreenAsteroids.size(); i++){
        onScreenAsteroids.get(i).updatePosition();
        onScreenAsteroids.get(i).invalidate();
    }
}
票数 1
EN

Stack Overflow用户

发布于 2019-09-04 21:09:30

不是所有的游戏都需要游戏循环。线程切换有其自身的成本。

游戏循环将游戏状态与呈现分离开来。理想情况下,游戏循环负责处理游戏中所有屏幕上的对象,对象有责任在其位置绘制自己。这样,我们就有了对事件做出反应的中心位置(鼠标点击、用户触摸等)和更新视图的位置和视图,并有责任在更新的位置绘制自己。

考虑到我们屏幕上有10颗正在移动的小行星,我们正在onDraw()中更新它们,现在它们中的两颗碰撞了,但是asteroid1不知道asteroid2的位置,那么它们将如何检测碰撞呢?根据游戏逻辑,游戏回路知道所有10颗小行星的位置,它可以检测碰撞。如果不关心混乱的代码,那么在onDraw中也可以检测到冲突。但考虑下..。

如果两颗小行星发生碰撞,那么我们需要检查其他小行星是否在碰撞区域附近,如果是的话,那么撞击程度是多少?乱七八糟的东西线性增加。

碰撞后,我们决定显示碰撞图形效果。烂摊子成倍增加..。

小行星相撞,游戏状态=‘天空中的爆炸’,用户接到呼叫,游戏进入后台,游戏状态被拯救,但我们的小行星掌握着自己的命运,现在我们需要为我们的活动提供每个小行星的状态,并在onPause()中保存它。现在一团糟..。

用户在几个小时后返回,我们不能直接欢迎他们‘在天空中爆炸’,需要倒转到小行星即将碰撞的状态,然后显示爆炸.乱得乱七八糟.

观点是奴隶,不应该赋予他们权力。

在哪里显示视图,它的酒窝?->来自外部。

看什么呢?->来自外部/在这里几乎没有发言权。

如何动画视图?->来自外部。

关于您的具体情况,您使用的两个版本不同,在onDraw()的情况下,您是直接使小行星的失效(第一个是立即绘制的),而在游戏循环的情况下,您首先计算所有小行星的位置,然后失效,我不知道您有多少个小行星,但是如果它们是重要的数目,再加上线程切换成本,可能会欺骗您相信onDraw()更快。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57792056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档