Game development. How are more than one game cycle made?

I use C #, but this is applicable for developing a game in any language.

Most games use a "game loop" that looks something like this:

while (game is running)
{
  UpdateEnvironment();
  DrawEnvironment();
}

I'm struggling to figure out how things that require more than one game cycle fit into the equation. For example, creating a ball of energy floats from one tile to another. Or if the player moves one tile (do not jump from tile to tile, but animate it).

The best I came up with is the time elapsed since the last cycle and passing it to the object / method so that it can do its job. But this makes it difficult to perform actions such as:

AI.MoveTo(10, 20); // Pathfind, then walk the path to this tile.
Player.Shoot(); // Shoot a bullet, and detect collisions and update along the way.

Where can I find more information on "completing events that require more than one game cycle?"

+3
5

- , . , , , , . - , , , , .

, MoveTo - 10, 20, AI . Shoot, , , , , , , .

, , , - .

+1

, , , . # , XNA , Dark GDK.NET "TheGameCreators".

, , "" . "" - , - (, , , , , , ..). , , , .. , , .., . , .

- , -, . , -, -. , .

//Generic Game Class
public class MySweetGame : Game
{
    Player _player = new Player(this);
    List<Bullet> _bullets = new List<Bullet>();
    public List<Bullet> AllBullets()
    {
        get { return _bullets; }
    }


    public void Update()
    {
        //You would obviously need some keyboard/mouse class to determine if a click took place
        if(leftMouseButtonClicked)
        {
            _player.Shoot();
        }

        //This would be assuming you have an object collection or array to hold all the bullets currently 'live' like the above '_bullets' collection
        //This is also assuming elapseGameTime is some built in game time management, like in XNA
        foreach(Bullet blt in _bullets)
        {
            blt.Update(elapsedGameTime);
        }
    }
}

//Generic Player Class
public class Player()
{
    Vector2 _position = new Vector2(0,0);
    int _ammunition = 50;
    MySweetGame _game;

    public Player(MySweetGame game)
    {
        _game = game;
    }

    public void Shoot()
    {
        if(_ammunition > 0){
            _game.AllBullets.Add(new Bullet(50, _position));
            _ammunition--;
        }
    }
}

//Generic Bullet Class
public class Bullet()
{
    float _metersPerSecond = 0;
    Vector2 _position = new Vector2(0, 0);

    public Bullet(float metersPerSecond, Vector3 position)
    {
        _metersPerSecond = metersPerSecond;
        _position = position;
    }

    //Here is the meat you wanted
    //We know the speed of the bullet, based on metersPerSecond - which we set when we instantiated this object
    //We also know the elapsedGameTime since we last called update
    //So if only .25 seconds have passed - we only moved (50 * .25) - and then update our position vector
    public void Update(float elapsedGameTime)
    {
        distanceTraveled = metersPerSecond * elapsedGameTime;
        _position.x += distanceTraveled;
    }
}
+1

, ; , MoveTo Shoot . AI , :

class AI
{
   StateEnum State; //Idle, Moving, Attacking, Dying, etc.
   PointF Location;
   PointF Velocity;
   PointF Destination;

MoveTo - - :

   void MoveTo(x, y)
   {
      Destination = new PointF(x, y);
      Velocity = new PointF(0.5, 0);
      State = StateEnum.Moving;
   }

Update .

   void Update()
   {
      switch (State)
      {
         case StateEnum.Moving:
            Location.Offset(Velocity); //advance 0.5 pixels to the right
            break;
         default:
            break;
      }
   }
}

(, 60 ), , , 30 . , .

, , , .

+1

WesleyJohnson Gannon, . WesleyJohnson Gannon , , . . , , , , . .

Task ( Process Job) Job. , MoveActorTask, PlayAnimationTask .. , , , , ,

, , :

class Task
{
public:

    /**
     * Constructor.
     *
     *  @param isDiscardable Set this true, if the Task goal can be reached in a single step.
     *         For instance if a Task is supposed to slowly close a window by fading
     *         its alpha to 0, then it is discardable, and Task#discard will just finish
     *         the process by closing the window.
     *
     *  @param destroyWhenDone Set this to true, when the TaskScheduler shall delete the
     *         Task, after execution is finished. This should usually be the case, but
     *         sometimes it is sensible to pool a number of Jobs for reuse.
     */
    Task(bool isDiscardable, 
        bool destroyWhenDone);

    virtual ~Task();

    /**
     * This is the function in which the Task is supposed to do whatever it is supposed to do.
     * This function is called by the TaskScheduler at most once per frame. The frequency depends
     * on the Job priority given with TaskScheduler#addTask.
     * @param time the time source time, since the last call of this function.
     * @return true, when the Task is done, false else. If false is returned, the Task will be
     * rescheduled for another execution.
     */
    virtual bool execute(Time time) = 0;

    virtual TimeSource::TimeSourceType getTimeSource() const = 0;

    /// Returns whether the Task can be removed from the queue by the scheduler,
    bool isDiscardable() const;

    /// Returns true, if the Task shall be deleted, if the Job is finished. Returns false else.
    bool destroyWhenDone() const;

    /// Finish whatever the Task is doing. It won't get a chance to continue.
    /// Overloaded functions must *not* call this implementation.
    virtual void discard();

protected:
    bool mIsDiscardable;
    bool mDestroyWhenDone;
};

TaskScheduler. TaskScheduler execute (Round robin), .

+1

, :

  • 1
  • 1
  • 1 ( ..)
  • 2
  • 2

"///" " " , . - (, , ) , , . .

However, you can often create your own system in such a way as to reduce the need to resort to something like that. For example, designing animations so that they can be processed one frame at a time.

-2
source

Source: https://habr.com/ru/post/1720387/


All Articles