Игра отстает (новичок) - PullRequest
1 голос
/ 22 января 2012

Я создаю игру, в которой астероиды появляются и движутся вниз по экрану.В методе обновления игры я использую случайное число, чтобы порождать астероиды.Когда я запускаю его, он начинает отставать в течение первых 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);
    }
}
}

Любая помощь будет принята с благодарностью.извините за код.У меня проблемы с настройкой.Помогите, пожалуйста, тоже.

Ответы [ 3 ]

4 голосов
/ 22 января 2012

Как сказал Тобиас, вам, вероятно, следовало бы разместить это на сайте Game Dev, и у вас, похоже, только один экземпляр Asteroid.В объекте Game1 вы объявляете и создаете экземпляр объекта Asteroid.Затем в методе обновления вы добавляете его повторно в 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 в список объектов.Таким образом, после каждого кадра 30 новых ссылок на один и тот же объект asteroid добавляются к objectList, а методы Update() и Draw() вызываются на asteroid для каждой ссылки на него в objectList.Таким образом, после 30 кадров, одной секунды, если скорость 30FPS, до 900 ссылок на один и тот же точный объект asteroid находятся в objectList, и в этом 30-м кадре asteroid вызывает свои методы 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);
    }
}

приведет только к пяти новым астероидам за время и максимум 50 в любой момент времени.Однако, если вы добавите функциональность для уничтожения астероидов, вам придется помнить об их удалении из objectList.

РЕДАКТИРОВАТЬ. Как сказал Neomex, ваш рисунок также является проблемой.Я бы посоветовал ознакомиться с докладом GDC 2008 о производительности XNA Framework здесь: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6082 В нем очень кратко описаны некоторые характеристики рисования и расчетов, а также то, что вы должны / не должны делать.

EDIT2- Фактическииз-за вашей случайной вероятности это будет до 900 ссылок на объекты и вызовов, а не целых 900.

3 голосов
/ 22 января 2012

Старайтесь делать как можно меньше начальных звонков, они часто сильно замедляют игру.(Класс астероидов)

В функции обновления вы отображаете графику, что очень плохо.

Если это не помогло, попробуйте загрузить новейшие драйверы.

Повторное использование:

Измените свой класс астероидов

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);
}

на

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

И добавить это в функции рисования:

foreach (Asteroid asteroid in objectList)
{
    asteroid.Draw(spriteBatch);
}
0 голосов
/ 22 января 2012

Как уже указывал Тобиас, вы используете один и тот же объект астероида каждый раз, когда хотите создать новый астероид.Вам нужно добавить new Asteriod() в список объектов вместо того, чтобы использовать тот же самый.

Кроме того, этот код, скорее всего, является причиной, по которой вы страдаете из-за производительности.Вы добавляете 30 экземпляров одного и того же объекта в коллекцию при каждом вызове обновления (примерно 60 раз в секунду).Я понимаю, что вы используете случайное число, но это примерно 12,5% вызовов обновлений.

Итак, через 5-10 секунд у вас есть тысячи таких объектов, и вы рисуете одно и то же изображение тысячи и тысячи раз.

...