游戏滞后(初学者)

发布于 2024-12-28 09:49:19 字数 5616 浏览 1 评论 0原文

我正在创建一个游戏,其中小行星产生并沿着屏幕移动。在游戏的更新方法中,我使用随机数来偶尔生成小行星。当我启动它时,它在前 5 秒内开始滞后。我可以看到这一点,因为分数计数器(每个刻度都会上升)开始以 30 为间隔。此外,小行星的图像甚至没有显示。

这是 gameObject 类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;  
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;  
using Microsoft.Xna.Framework.Storage;


namespace thedodger
{
public abstract class gameObject
{
    public static Texture2D texture;
    public Rectangle rectangle;

    public abstract void Draw(SpriteBatch spriteBatch);
    public abstract void Update(GameTime gameTime);
}
} 

这是小行星类;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace thedodger
{
public class Asteroid : gameObject
{
    Random rand = new Random(1);
    int yPos = -10;

    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        spriteBatch.Draw(texture, new Rectangle(rand.Next(32,400),      yPos,32,32),Color.White);
        spriteBatch.End();

    }

    public override void Update(GameTime gameTime)
    {
        yPos--;


    }
}
}

这是 game1 类:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace thedodger
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    int scorevalue = 0;
    SpriteFont font;
    player player1 = new player();
    List<gameObject> objectList = new List<gameObject>();
    Random rand = new Random(1);
    Asteroid asteroid = new Asteroid();


    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        font = Content.Load<SpriteFont>("font");
        //player1.image = Content.Load<Texture2D>("EnemyShip005.png");
        gameObject.texture = Content.Load<Texture2D>("asteroid");

        // TODO: use this.Content to load your game content here
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        scorevalue++;

        if (rand.Next(0, 8) == 2)
        {
            for (int i = 0; i < 30; i++)
            {

                objectList.Add(asteroid);


            }
        }

        foreach (Asteroid asteroid in objectList)
        {
            asteroid.Update(gameTime);
            asteroid.Draw(spriteBatch);
        }



        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
         spriteBatch.Begin();
         spriteBatch.DrawString(font, "Score: " + scorevalue, new Vector2(5, 5), Color.White);
         spriteBatch.End();



        base.Draw(gameTime);
    }
}
}

我们将不胜感激所有帮助。 对代码感到抱歉。我很难设置它。也请帮忙。

I am creating a game in which asteroids spawn and move down the screen. In the update method of the game, i am using a random number to spawn the asteroids sporatically. When i start it up, it begins to lag within the first 5 seconds. I can see this because the score counter(which goes up every tick) starts going in intervals of 30. Also, the images of the asteroid do not even show up.

Here is the gameObject class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;  
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;  
using Microsoft.Xna.Framework.Storage;


namespace thedodger
{
public abstract class gameObject
{
    public static Texture2D texture;
    public Rectangle rectangle;

    public abstract void Draw(SpriteBatch spriteBatch);
    public abstract void Update(GameTime gameTime);
}
} 

here is the asteroid class;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace thedodger
{
public class Asteroid : gameObject
{
    Random rand = new Random(1);
    int yPos = -10;

    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Begin();
        spriteBatch.Draw(texture, new Rectangle(rand.Next(32,400),      yPos,32,32),Color.White);
        spriteBatch.End();

    }

    public override void Update(GameTime gameTime)
    {
        yPos--;


    }
}
}

and here is the game1 class:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace thedodger
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    int scorevalue = 0;
    SpriteFont font;
    player player1 = new player();
    List<gameObject> objectList = new List<gameObject>();
    Random rand = new Random(1);
    Asteroid asteroid = new Asteroid();


    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        font = Content.Load<SpriteFont>("font");
        //player1.image = Content.Load<Texture2D>("EnemyShip005.png");
        gameObject.texture = Content.Load<Texture2D>("asteroid");

        // TODO: use this.Content to load your game content here
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        scorevalue++;

        if (rand.Next(0, 8) == 2)
        {
            for (int i = 0; i < 30; i++)
            {

                objectList.Add(asteroid);


            }
        }

        foreach (Asteroid asteroid in objectList)
        {
            asteroid.Update(gameTime);
            asteroid.Draw(spriteBatch);
        }



        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // TODO: Add your drawing code here
         spriteBatch.Begin();
         spriteBatch.DrawString(font, "Score: " + scorevalue, new Vector2(5, 5), Color.White);
         spriteBatch.End();



        base.Draw(gameTime);
    }
}
}

All help would be greatly appreciated.
sorry about the code. I am having difficult setting it up. Help on that too please.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泪痕残 2025-01-04 09:49:19

正如托比亚斯所说,您可能应该将其放在游戏开发网站上,但您似乎只实例化了一个 Asteroid 。在 Game1 对象中,您声明并实例化一个 Asteroid 对象。然后在 Update 方法中将其重复添加到 objectList 中。要获得我认为您想要的内容,您应该更改

Asteroid asteroid = new Asteroid();

Asteroid asteroid;

然后更改

for (int i = 0; i < 30; i++)
{
    objectList.Add(asteroid);
}

for (int i = 0; i < 30; i++)
{
    asteroid = new Asteroid();
    objectList.Add(asteroid);
}

在您的原始代码中,您将 asteroid 声明并实例化为特定的 Asteroid 但永远不要更改它。因此,在整个程序中,asteroid 都指向 Asteroid 的一个特定实例。然后,您重复将asteroid添加到objectList中。因此,在每一帧之后,对同一 asteroid 对象的 30 个新引用将被添加到 objectList 以及 Update()Draw 中() 方法在 asteroid 上被调用,用于 objectList 中对它的每次引用。因此,在 30 帧之后,如果以 30FPS 运行则为一秒,在 objectList 和第 30 帧 asteroid 中,最多有 900 个对同一个精确 小行星 对象的引用code> 的 Update()Draw() 方法被调用多达 900 次。我很确定这就是你滞后的根源。执行上面给出的更正将导致 objectList 填充最多 900 个不同 Asteroid,但肯定也会遇到滞后。您还需要做的是在任何给定时间对屏幕上的小行星数量添加限制(objectList 的长度只能是 x 数量)和/或减少每次创建的小行星数量时间。我建议类似的方法

for (int i = 0; i < 5; i++)
{
    if (objectList.Count < 50) // Maximum asteroids on screen
    {
        asteroid = new Asteroid();
        objectList.Add(asteroid);
    }
}

在一段时间内只会产生 5 颗新小行星,并且在任何给定时间最多产生 50 颗。如果您添加了摧毁小行星的功能,则必须记住将它们从 objectList 中删除。

编辑-正如 Neomex 所说,你的绘图也是一个问题。我建议您查看 GDC 2008 关于 XNA 框架性能的演讲:http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6082
它非常简要地介绍了一些绘图和计算性能以及您应该/不应该做什么。

EDIT2-实际上,由于你的随机概率,最多会出现 900 个对象引用和调用,而不是完整的 900 个。

As Tobias said, you probably should have put this on the Game Dev site and you appear to only have one Asteroid instantiated. In the Game1 object, you declare and instantiate an Asteroid object. Then in the Update method you add it repeatedly to the objectList. To get what I think you want, you should change

Asteroid asteroid = new Asteroid();

to

Asteroid asteroid;

Then change

for (int i = 0; i < 30; i++)
{
    objectList.Add(asteroid);
}

to

for (int i = 0; i < 30; i++)
{
    asteroid = new Asteroid();
    objectList.Add(asteroid);
}

In your original code you declare and instantiate asteroid as a specific Asteroid but then never change it. So, throughout the whole program asteroid is pointed to one specific instance of an Asteroid. Then you repeatedly add asteroid to the objectList. So after each frame, 30 new references to the same asteroid object are being added to the objectList and the Update() and Draw() methods are being called on asteroid for every reference to it in objectList. So after 30 frames, one second if running at 30FPS, up to 900 references to the same exact asteroid object are in objectList and on that 30th frame asteroid is having its Update() and Draw() methods called up to 900 times. I'm pretty sure this is the source of your lag. Doing the corrections given above will result in objectList being populated with up to 900 different Asteroids, but will certainly experience lag as well. What you need to do as well is add a limit to the amount of asteroids on screen at any given time (the length of objectList can only be x amount) and/or lower the amount of asteroids created each time. I would suggest something like

for (int i = 0; i < 5; i++)
{
    if (objectList.Count < 50) // Maximum asteroids on screen
    {
        asteroid = new Asteroid();
        objectList.Add(asteroid);
    }
}

will result in only five new asteroids for time and a maximum of 50 at any given time. If you add in functionality to destroy asteroids though, you'll have to remember to remove them from the objectList.

EDIT- As Neomex has said, your drawing is also a problem. I would suggest checking out the GDC 2008 talk on the XNA Framework performance here: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6082
It very briefly covers some drawing and calculation performances and what you should/shouldn't do.

EDIT2- Actually, because of your random probability, it would be up to 900 object references and calls, not a full 900.

朦胧时间 2025-01-04 09:49:19

尝试尽可能少地进行开始结束调用,它们通常会大大减慢游戏速度。
(小行星类)

您在更新功能中显示图形,这确实是一件坏事。

如果这些失败,请尝试下载最新的驱动程序。

总结:

的小行星类更改

public override void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Begin();
    spriteBatch.Draw(texture, new Rectangle(rand.Next(32,400),      yPos,32,32),Color.White);
    spriteBatch.End();

}

public override void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(texture, new Rectangle(rand.Next(32,400),      yPos,32,32),Color.White);
}

将更新函数中

foreach (Asteroid asteroid in objectList)
{
    asteroid.Update(gameTime);
    asteroid.Draw(spriteBatch);
}

Now并将

foreach (Asteroid asteroid in objectList)
{
    asteroid.Update(gameTime);
}

其添加到绘图函数中:

foreach (Asteroid asteroid in objectList)
{
    asteroid.Draw(spriteBatch);
}

Try to make as least begin-end calls as possible, they often slow down game a lot.
( Asteroid class )

You are displaying graphics in your update function which is really bad thing.

If these fail, try to download newest drivers.

Reasuming:

Change in your asteroid class

public override void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Begin();
    spriteBatch.Draw(texture, new Rectangle(rand.Next(32,400),      yPos,32,32),Color.White);
    spriteBatch.End();

}

to

public override void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(texture, new Rectangle(rand.Next(32,400),      yPos,32,32),Color.White);
}

Now in your update function

foreach (Asteroid asteroid in objectList)
{
    asteroid.Update(gameTime);
    asteroid.Draw(spriteBatch);
}

to

foreach (Asteroid asteroid in objectList)
{
    asteroid.Update(gameTime);
}

And add this in draw function:

foreach (Asteroid asteroid in objectList)
{
    asteroid.Draw(spriteBatch);
}
浮光之海 2025-01-04 09:49:19

正如托比亚斯已经指出的那样,每次你想要生成一个新的 asteriod 时,你都会使用相同的 asteriod 对象。您需要将 new Asteriod() 添加到对象列表中,而不是使用相同的对象列表。

此外,这段代码很可能是您遭受性能损失的原因。

    if (rand.Next(0, 8) == 2)
    {
        for (int i = 0; i < 30; i++)
        {

            objectList.Add(asteroid);


        }
    }

每次更新调用时,您都会将同一对象的 30 个实例添加到集合中(每秒大约 60 次)。我知道您使用的是随机数,但它仍然发生在大约 12.5% 的更新调用中。

因此,在 5 到 10 秒内,您现在拥有数千个这样的对象,并且正在绘制相同的图像数千次。

As Tobias has already pointed out, you are using the same asteriod object every time you want to spawn a new asteriod. You need to do add a new Asteriod() to the object list instead of using the same one.

Also, this code is mostly likely the reason you are suffering performance wise.

    if (rand.Next(0, 8) == 2)
    {
        for (int i = 0; i < 30; i++)
        {

            objectList.Add(asteroid);


        }
    }

You are adding 30 instances of the same object to the collection on every update call (with is around 60 times a second). I realize you are using a random number, but it sill happens to about 12.5% of the update calls.

So within a 5-10 seconds, you now have thousands of these objects and are drawing the same image thousands and thousands of times.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文