Спонсор: Microsoft
Опубликован: 10.04.2009 | Уровень: специалист | Доступ: свободно
Самостоятельная работа 11:

Организация многоуровневых игр, конструктор уровней

В листинге 15.4. вы можете видеть код класса Ball. Этот класс отвечает за перемещение мяча и за обработку столкновений мяча и других объектов.

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

namespace P11_1
{
    public class Ball : gBaseClass
    {
        //для хранения границ экрана
        Rectangle scrBounds;
        //скорость мяча
        public Vector2 speed;
        Random rand = new Random();
        public Ball(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            speed = new Vector2(1, -1);
            scrBounds = new Rectangle(0, 0,
              game.Window.ClientBounds.Width,
              game.Window.ClientBounds.Height);
        }

        
        //Проверка на столкновение с границами экрана
        void Check()
        {
            if (sprPosition.X < scrBounds.Left)
            {
                sprPosition.X = scrBounds.Left;
                RandomiseSpeed();
                speed.X *= -1;
            }
            if (sprPosition.X > scrBounds.Width - sprRectangle.Width)
            {
                sprPosition.X = scrBounds.Width - sprRectangle.Width;
                RandomiseSpeed();
                speed.X *= -1;
            }
            if (sprPosition.Y < scrBounds.Top)
            {
                sprPosition.Y = scrBounds.Top;
                RandomiseSpeed();
                speed.Y *= -1;
            }
            if (sprPosition.Y > scrBounds.Height - sprRectangle.Height)
            {
                this.Dispose();
            }
            
        }

        //Проверка на столкновение с объектом
        bool IsCollideWithObject(gBaseClass spr)
        {
            return (this.sprPosition.X + this.sprRectangle.Width > spr.sprPosition.X &&
                        this.sprPosition.X < spr.sprPosition.X + spr.sprRectangle.Width &&
                        this.sprPosition.Y + this.sprRectangle.Height > spr.sprPosition.Y &&
                        this.sprPosition.Y < spr.sprPosition.Y + spr.sprRectangle.Height);


        }
        //Процедуры случайного изменения скорости при контакте с объектами
        //Для всех объектов - скорость может либо возрасти, либо упасть
        void RandomiseSpeed()
        {
            speed.Y += (float)((rand.NextDouble() - rand.NextDouble())*0.2 );
            speed.X += (float)((rand.NextDouble() - rand.NextDouble())*0.2 );
        }
        //Для объектов типа Brick1 скорость лишь растет
        void RandomiseSpeedB1()
        {
            speed.Y += (float)(0.3*Math.Sign(speed.Y) * Math.Abs(((rand.NextDouble() - rand.NextDouble()))));
            speed.X += (float)(0.3*Math.Sign(speed.X) * Math.Abs(((rand.NextDouble() - rand.NextDouble()))));
        }
        //Проверка на столкновения
       public void IsCollide()
        {
            gBaseClass FindObj=null;
            Bat FindedBat;          
            foreach (gBaseClass spr in Game.Components)
            {
                    if (IsCollideWithObject(spr))
                    {
                        //Если столкнулись с блоком Brick1
                        if (spr.GetType() == (typeof(Brick1)))
                        {
                            //сохраним найденный объект
                            FindObj = spr;
                            //Изменим скорость
                            RandomiseSpeedB1();
                            //Обратим скорость
                            speed *= -1;
                        }
                        //Если столкнулись с блоком 2
                        //обращаем скорость
                        if (spr.GetType() == (typeof(Brick2)))
                        {
                            speed *= -1;
                        }
                        //если столкнулись с битой
                        if (spr.GetType() == (typeof(Bat)))
                        {
                            FindedBat =(Bat) spr;
                            RandomiseSpeed();
                            //Если бита двигалась влево
                            //Мяч отразится от нее влево
                            if (FindedBat.direction)
                            {
                                speed.Y = Math.Abs(speed.Y);
                                speed.X = Math.Abs(speed.X);
                                speed *= -1;
                            }
                            //Если двигалась вправо
                            //отразится вправо
                            else
                            {
                                speed.Y = Math.Abs(speed.Y);
                                speed.X = Math.Abs(speed.X);
                                speed.Y *= -1;
                            }
                            
                            
                        }

                    }
            }
            //Если был найден блок Block1
            if (FindObj != null)
            {
               //Уничтожить его
                FindObj.Dispose();
                FindObj = null;
            }

        }

        
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            //Переместить мяч в соответствии со скоростью
            this.sprPosition += this.speed;
            //Ограничить скорость мяча 1.5 пикселями
            if (speed.Y > 2) speed.Y = (float)2;
            if (speed.Y < -2) speed.Y = (float)-2;
            if (speed.X > 2) speed.X = (float)2;
            if (speed.X < -2) speed.X = (float)-2;
            //Проверить столкновение с границами
            Check();
            //проверить столкновение с объектами
            IsCollide();
            base.Update(gameTime);
        }
    }
}
Листинг 15.4. Код класса Ball

Листинг 15.5. содержит коды классов Brick1, Brick2 и BrickBuilder. Эти классы наследованы от gBaseClass и не вносят в его функциональность никаких дополнений.

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

namespace P11_1
{
    public class Brick1 : gBaseClass
    {
        public Brick1(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            // TODO: Construct any child components here
        }
    }
}

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

namespace P11_1
{
    public class Brick2 : gBaseClass
    {
        public Brick2(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            // TODO: Construct any child components here
        }

    }
}

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

namespace P11_1
{
    public class BrickBuilder : gBaseClass
    {
        public BrickBuilder(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, int x_c, int y_c)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, x_c, y_c)
        {
            // TODO: Construct any child components here
        }
    }
}
Листинг 15.5. Коды классов Brick1, Brick2 и BrickBuilder

Выводы

В этой лабораторной работе мы создали игру, предусматривающую несколько игровых уровней и конструктор уровней для пользователя. Как правило, разработка реальных игр включает в себя создание конструктора уровней, с помощью которого разработчик создает игровые уровни. Этот конструктор можно включить в поставку игры, предоставив пользователю возможность самостоятельно создавать новые уровни к игре. Конструкторы уровней так же разнообразны, как сами игры.

Задание

В этой лабораторной работе мы создали макет игры, допускающей использование нескольких уровней и содержащей конструктор уровней. Доработайте этот макет. А именно, выполните следующие улучшения исходного проекта:

  1. Переработайте процедуры обработки столкновений мяча с блоками. Мяч должен отскакивать от блоков точно так же, как он отскакивает от границ экрана.
  2. Создайте интерфейс игры – меню, систему справки.
  3. Предусмотрите сохранение пользовательского уровня в файл (с помощью сериализации специально созданного объекта) и загрузку его из файла
  4. Создайте систему подсчета очков, предусмотрите сохранение данных о набранных очках в файле.
  5. Улучшите процесс прохождения игры – разработайте дополнительные уровни, сделайте игровой процесс разнообразнее, разработав бонусные объекты, которые появляются при уничтожении некоторых из блоков. Игрок должен "поймать" бонусный объект битой для того, чтобы активировать соответствующий бонус.
Alina Lasskaja
Alina Lasskaja

Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить.....