XNA 不跳台

Posted

技术标签:

【中文标题】XNA 不跳台【英文标题】:XNA doesn't jump of the platform 【发布时间】:2014-09-17 13:39:33 【问题描述】:

我正在使用 XNA 开发我的游戏。我从 YouTube 上找到了 Oyyou 的一系列教程,到目前为止已经进入了碰撞教程。我已经成功地处理了重力、运动和动画。但是我有碰撞问题。我角色的重生点悬而未决。

第一个值是我的 bool hasJumped。第二个是y速度。它正在加速 0.25。 角色正在缓慢加速下落。所有四个平台都以相同的方式制作。所有四个都在列表中,我没有特别与他们中的任何一个一起工作。

当我降落在最低(地面)时,我得到了我需要的参数。 hasJumped 为假,velocity.Y 为 0。

但是当我在三个非地面平台之一上时,结果并不如我所愿。即使我将速度设为 0,速度也是 0.25。hasJumped 不会变为真,因为我的速度是一个非零变量。不幸的是,我不能发布图片,所以我不能展示它。但我会发布我的代码: 这是我添加玩家和平台的主游戏类。

 protected override void LoadContent()
    
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        player = new Animation(Content.Load<Texture2D>("player"), Content.Load<Texture2D>("rect"), new Vector2(300 + 28, graphics.PreferredBackBufferHeight - 500), 47, 44, graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);
        platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(300,graphics.PreferredBackBufferHeight-100), 80,50));
        platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(500, graphics.PreferredBackBufferHeight - 50), 80, 50));
        platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(700, graphics.PreferredBackBufferHeight - 60),80,50));
        platformList.Add(new Platform(Content.Load<Texture2D>("Crate"), new Vector2(0, graphics.PreferredBackBufferHeight - 10), graphics.PreferredBackBufferWidth, 10));
        // TODO: use this.Content to load your game content here
    

这是我的动画课:

class Animation

    Texture2D texture;
    Texture2D rectText;
    public Rectangle rectangle;
    public Rectangle collisionRect;

    public Vector2 position;
    Vector2 origin;
    public Vector2 velocity;

    int currentFrame;
    int frameHeight;
    int frameWidth;
    int screenHeight;
    int screenWidth;

    float timer;
    float interval = 60;

    bool movingRight;
    public bool hasJumped;

    public Animation(Texture2D newTexture, Texture2D newRectText, Vector2 newPosition, int newHeight, int newWidth, int screenH, int screenW)
    
        rectText = newRectText;
        texture = newTexture;
        position = newPosition;
        frameHeight = newHeight;
        frameWidth = newWidth;
        screenHeight = screenH;
        screenWidth = screenW;
        hasJumped = true;
    

    public void Update(GameTime gameTime)
    
        rectangle = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
        collisionRect = new Rectangle((int)position.X-frameWidth/2, (int)position.Y - frameHeight/2, frameWidth, frameHeight);
        origin = new Vector2(rectangle.Width / 2, rectangle.Height / 2);
        position = position + velocity;


        if (Keyboard.GetState().IsKeyDown(Keys.Right))
        
            AnimateRight(gameTime);
            velocity.X = 5;
            movingRight = true;
        
        else if (Keyboard.GetState().IsKeyDown(Keys.Left))
        
            AnimateLeft(gameTime);
            velocity.X = -5;
            movingRight = false;
        
        else
        
            velocity.X = 0f;
            if (movingRight)
                currentFrame = 0;
            else currentFrame = 4;
        


        if(Keyboard.GetState().IsKeyDown(Keys.Space) && !hasJumped)
        
            position.Y -= 5f;
            velocity.Y = -10;
            hasJumped = true;
        

        if(hasJumped)
        
            velocity.Y += 0.25f;
        


        if(position.X<0+frameWidth/2)
        
            position.X = 0 + frameWidth / 2;
        
        else if (position.X>screenWidth-frameWidth/2)
        
            position.X = screenWidth - frameWidth / 2;
        
    

    public void AnimateRight(GameTime gameTime)
    
        timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds/2;
        if(timer>interval)
        
            currentFrame++;
            timer = 0;
            if (currentFrame > 3)
            
                currentFrame = 0;
            
        
    

    public void AnimateLeft(GameTime gameTime)
    
        timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds / 2;
        if (timer > interval)
        
            currentFrame++;
            timer = 0;
            if (currentFrame > 7 || currentFrame < 4)
            
                currentFrame = 4;
            
        
    

    public void Draw(SpriteBatch spriteBatch)
    
        spriteBatch.Draw(texture,position,rectangle,Color.White, 0f, origin, 1.0f, SpriteEffects.None, 0);
       // spriteBatch.Draw(rectText,collisionRect,Color.White);
    

平台类非常简单:

class Platform

    Texture2D texture;
    Vector2 position;
    public  Rectangle rectangle;



    public Platform(Texture2D newTexture, Vector2 newPosition, int platformWidth, int platformHeight)
    
        texture = newTexture;
        position = newPosition;

        rectangle = new Rectangle((int)position.X, (int)position.Y, platformWidth, platformHeight);
    

    public void Draw(SpriteBatch spriteBatch)
    
        spriteBatch.Draw(texture, rectangle, Color.White);

    

以及碰撞方式:

public static bool isOnTopOf(this Rectangle r1, Rectangle r2)
    
        return (r1.Bottom >= r2.Top - 10 && 
             r1.Bottom <= r2.Top + 10 && 
             r1.Right >= r2.Left + 10 && 
             r1.Left <= r2.Right - 10);
     

问题应该出在这里:

foreach (Platform a in platformList)
        
            if (player.collisionRect.isOnTopOf(a.rectangle) && player.velocity.Y>=0)
            
                player.hasJumped = false;
                player.velocity.Y = 0f;

                if(player.collisionRect.Bottom > a.rectangle.Top || player.collisionRect.Bottom - a.rectangle.Top <=10)
                
                    player.position.Y = a.rectangle.Y - 48 / 2;
                    player.hasJumped = false;

                
            

            else
            
                player.hasJumped = true;
            
        

但如果我排除最后一个 else 它不会掉到平台上。

感谢您提出问题。我添加了图像。

【问题讨论】:

你到底在哪里设置 hasJumped 为 false? @SKleanthous 抱歉,现在将更新问题 @Vendetta8247 看起来当你跳跃时,你正在设置 velocity.Y = -10。但是,在您检查播放器是否位于盒子顶部的代码中,您还要检查是否 velocity.Y >= 0。这可能是您的问题所在吗? @JasonZiaja 不,我试图改变这一点。这条线是为了从平台上方正确跳跃而设计的。这样它就不会在上升时停止,只会在下降时停止。 平台检查是在每次更新还是在特定时间进行?它应该可以通过断点轻松调试。看Conditional Breakpoints 【参考方案1】:

您的问题是,当用户在不是最低平台的平台上时,在 else 期间,当您检查用户是否在平台上时,您将 hasJumped 显式设置为 true。

您必须做的是在您的 foreach 中检查您的平台,通过增加 Y 坐标(很大程度上取决于您的相机设置)对它们进行排序,并在您将 hasJumped 设置为 false 后中断。这样你就可以避免你的问题:

foreach (Platform a in platformList.OrderByY())

    if (player.collisionRect.isOnTopOf(a.rectangle) && player.velocity.Y>=0)
    
        player.hasJumped = false;
        player.velocity.Y = 0f;

        if(player.collisionRect.Bottom > a.rectangle.Top || player.collisionRect.Bottom - a.rectangle.Top <=10)
        
            player.position.Y = a.rectangle.Y - 48 / 2;
            player.hasJumped = false;
        

        break;
    
    else
    
        player.hasJumped = true;
    

不幸的是,在 3D 开发中,我们经常需要做一些小技巧才能让应用程序正确渲染。在使用高级透明度渲染复杂项目时尤其如此。但是,在您的情况下,我建议您重新想象您处理碰撞的方式。

游戏开发并非易事。从表面上看,您工作的约束条件实施了一个不太理想的架构。 XNA 游戏中的所有内容都围绕更新循环进行,控制首先更新哪个项目的能力是如此简单和诱人,以至于人们倾向于使用它。然而,它通常是一种更好的方法来尝试和推断功能,使您的模型以事件驱动的方式运行。实现此目的的一种方法是将游戏的更新周期拆分为以下阶段:

    输入阶段:检索来自用户的输入并将其作为事件处理(这些可以是在 Update 以外的方法中对项目的简单方法调用,也可以是更复杂但更好的方法,例如使用 Rx) 运动阶段:在您的模型中开发一些物理特性(加速度、速度、重量等),并让它们在运动阶段自行完成定位和旋转工作。这是他们在更新中唯一应该做的事情。 碰撞阶段:测试碰撞,然后在对象上触发事件以处理碰撞。 清理阶段:清理任何问题,例如在碰撞检测阶段移动到墙内。或逐步淘汰粒子等。当您需要绘制精确的像素以避免模糊等时,这一点很重要。

上述方法不一定是最好的方法,但它确实有效。如果您只依赖更新周期,您很快就会达到模型之间的相互依赖关系以及按顺序触发某些事件的要求将成为支持的噩梦。执行事件驱动机制将使您免于大量废弃的工作,并且初始开销非常小。

对于 XNA 游戏,我建议使用 Rx 可能听起来有点奇怪,但相信我,这是处理事件的绝佳方式。最后,我想提一下MonoGame,如果你还不知道的话,它是一个为 Windows、Mac、Linux、android、iPhone、Windows Phone、WinRT(甚至更多)开发游戏的优秀框架。

【讨论】:

感谢您的回答。我更改了添加平台的顺序。现在它只适用于顶部。地面没有。它似乎只是检查添加的最后一个而不是 foreach。但我想知道是否有更好的方法来重做碰撞。我不是一个完整的新手,但这通常是我认为碰撞工作的方式。如果您能告诉我一些关于它的信息,我将不胜感激。 @Vendetta8247 我已经更新了我的答案以解决您当前的问题,并提供了一些关于如何最好从这里转移的信息。 非常感谢您的回答。事实证明 break 足以解决我的问题。但我会记住您的建议,希望它对我将来有所帮助。现在我将研究我的 AI、相机等。

以上是关于XNA 不跳台的主要内容,如果未能解决你的问题,请参考以下文章

XNA如何使xna不能读取透明颜色

处理 XNA + lidgren 中的延迟

XNA 与 Visual Studio 2012。/安装程序不工作

Microsoft XNA MediaPlayer.Play(song) 不播放某些歌曲

从 Maya 导入 XNA 曲线?

XNA 4.0 在 Windows 上加载外部 3D 对象