显示轨迹指示器 [英] Showing trajectory indicator

查看:64
本文介绍了显示轨迹指示器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从图像中您可以看到,向左射击的球向后方射击,与计算的轨迹不匹配.我使用来自SO 问题的方程式绘制球的轨迹,将其修改为考虑到每秒30帧的box2d步骤.这确实会计算有效轨迹,但它与球的实际轨迹不匹配,因为球的轨迹较小.我正在向球施加box2d力,这也具有密度设置和形状.形状半径根据球的类型而变化.我会在着陆事件中设置开始速度.

From the image you can see that the ball fired on the left that fire behind it, does not match the calculated trajectory. Im drawing the ball trajectory using an equation from a SO question, this is modified to take into consideration the box2d steps of 30 frames per second. This does calculate a valid trajectory but it does not match the actual trajectory of the ball, the ball has a smaller trajectory. I am applying a box2d force to the ball, this also has a density set and a shape. The shape radius varies depending on the type of ball. Im setting the start velocity in the touchdown event.

public class ProjectileEquation {  

    public float gravity;  
    public Vector2 startVelocity = new Vector2();  
    public Vector2 startPoint = new Vector2();  
    public Vector2 gravityVec = new Vector2(0,-10f);

    public float getX(float n) {  
        return startVelocity.x * (n * 1/30f) + startPoint.x;  
    }  

    public float getY(float n) {
        float t = 1/30f * n;
        return 0.5f * gravity * t * t + startVelocity.y * t + startPoint.y;  
    }  



} 

@Override  
    public void draw(SpriteBatch batch, float parentAlpha) {  
        float t = 0f;  
        float width = this.getWidth();  
        float height = this.getHeight();  

        float timeSeparation = this.timeSeparation;  

        for (int i = 0; i < trajectoryPointCount; i+=timeSeparation) {  
            //projectileEquation.getTrajectoryPoint(this.getX(), this.getY(), i);
            float x = this.getX() + projectileEquation.getX(i);  
            float y = this.getY() + projectileEquation.getY(i);  

            batch.setColor(this.getColor());  
            if(trajectorySprite != null) batch.draw(trajectorySprite, x, y, width, height);  

           // t += timeSeparation;  
        }  
    } 



public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
                if(button==1 || world.showingDialog)return false;
                touchPos.set(x, y);
                float angle = touchPos.sub(playerCannon.position).angle();
                if(angle > 270 ) {
                    angle = 0;
                }
                else if(angle >70) {
                    angle = 70;
                }
                playerCannon.setAngle(angle);
                world.trajPath.controller.angle = angle;
                float radians =  (float) angle * MathUtils.degreesToRadians;
                float ballSpeed = touchPos.sub(playerCannon.position).len()*12;
                world.trajPath.projectileEquation.startVelocity.x = (float) (Math.cos(radians) * ballSpeed);
                world.trajPath.projectileEquation.startVelocity.y = (float) (Math.sin(radians) * ballSpeed);
                return true;
            }



public CannonBall(float x, float y, float width, float height, float damage, World world,  Cannon cannonOwner) {
        super(x, y, width, height, damage, world);
        active = false;
        shape = new CircleShape();
        shape.setRadius(width/2);

        FixtureDef fd = new FixtureDef();
        fd.shape = shape;
        fd.density = 4.5f;
        if(cannonOwner.isEnemy) { //Enemy cannon balls cannot hit other enemy cannons just the player
            fd.filter.groupIndex = -16;
        }
        bodyDef.type = BodyType.DynamicBody;
        bodyDef.position.set(this.position);

        body = world.createBody(bodyDef);
        body.createFixture(fd);
        body.setUserData(this);
        body.setBullet(true);
        this.cannonOwner = cannonOwner; 
        this.hitByBall = null;
        this.particleEffect = null;
    }

  private CannonBall createCannonBall(float radians, float ballSpeed, float radius, float damage)
    {
        CannonBall cannonBall =  new CannonBall(CannonEnd().x, CannonEnd().y, radius * ballSizeMultiplier, radius * ballSizeMultiplier, damage, this.world, this);
        cannonBall.velocity.x = (float) (Math.cos(radians) * ballSpeed);
        //cannonBall.velocity.x = (float) ((Math.sqrt(10) * Math.sqrt(29) *
            //  Math.sqrt((Math.tan(cannon.angle)*Math.tan(cannon.angle))+1)) / Math.sqrt(2 * Math.tan(cannon.angle) - (2 * 10 * 2)/29))* -1f;
        cannonBall.velocity.y = (float) (Math.sin(radians) * ballSpeed);
        cannonBall.active = true;
        //cannonBall.body.applyLinearImpulse(cannonBall.velocity, cannonBall.position);
        cannonBall.body.applyForce(cannonBall.velocity, cannonBall.position );
        return cannonBall;
    }


trajPath = new TrajectoryActor(-10f);
        trajPath.setX(playerCannon.CannonEnd().x);
        trajPath.setY(playerCannon.CannonEnd().y);
        trajPath.setWidth(10f);
        trajPath.setHeight(10f);
        stage.addActor(trajPath);

推荐答案

这是我在其他一款游戏中使用的代码,事实证明它非常精确.诀窍是将脉冲施加到身体上并读取初始速度.据此,我计算出身体在0.5秒内处于的10个位置.该语言称为Squirrel,它是基于Lua的语法(类似于C/C ++).您应该能够掌握那里发生的事情.从getTrajectoryPointsForObjectAtImpulse返回的结果是一个10个位置的数组,球将在0.5秒内通过.

Here is a code that I used for one of my other games, which proved to be very precise. The trick is to apply the impulse on the body and read the initial velocity. Having that I calculate 10 positions where the body will be within 0.5 seconds. The language is called Squirrel which is Lua based with C/C++ like syntax. You should be able to grasp what is going on there. What returns from the getTrajectoryPointsForObjectAtImpulse is an array of 10 positions through which the ball will pass within 0.5 seconds.

const TIMESTER_DIVIDOR = 60.0;

function getTrajectoryPoint( startingPosition, startingVelocity, n )
{
    local gravity = box2DWorld.GetGravity();
    local t = 1 / 60.0;
    local stepVelocity =  b2Vec2.Create( t * startingVelocity.x, t * startingVelocity.y );
    local stepGravity = b2Vec2.Create( t * t * gravity.x, t * t * gravity.y );

    local result = b2Vec2.Create( 0, 0 );
    result.x = ( startingPosition.x + n * stepVelocity.x + 0.5 * ( n * n + n ) * stepGravity.x ) * MTP;
    result.y = ( startingPosition.y + n * stepVelocity.y + 0.5 * ( n * n + n ) * stepGravity.y ) * -MTP;

    return result;
}

function getTrajectoryPointsForObjectAtImpulse (object, impulse) 
{
    if( !object || !impulse ) return [];

    local result = [];

    object.bBody.ApplyLinearImpulse( impulse, object.bBody.GetWorldCenter() );

    local initialVelocity = object.bBody.GetLinearVelocity();

    object.bBody.SetLinearVelocity( b2Vec2.Create(0, 0) );
    object.bBody.SetActive(false);

    for ( local i = 0.0 ; i < ( 0.5 * TIMESTER_DIVIDOR ) ; )
    {
        result.append( getTrajectoryPoint(object.bBody.GetPosition(), initialVelocity, i.tointeger() ) );

        i += ( (0.5 * TIMESTER_DIVIDOR) * 0.1 );
    }
    return result;
}

如果您不理解代码的任何部分,请告诉我,我将尽力解释.

If you do not understand any part of the code, please let me know and I will try to explain.

这篇关于显示轨迹指示器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆