|
Быть может кто-то из Вас знает игру Sims, к какому жанру она относиться? Жизненная симуляция, ролевая игра, там можно и дома строить..... |
Взаимодействие объектов
Задачи работы:
- Изучить теоретические основы обработки столкновений объектов в двумерном пространстве
- Изучить алгоритмы обработки столкновений объектов в двумерном пространстве
- Рассмотреть алгоритм проверки принадлежности точки фигуре в двумерном пространстве
- Создать простую игру – игровой объект автоматически перемещается по экрану, отскакивая от его границ. Игрок должен с помощью мыши попасть по объекту. Каждое попадание должно привести к выводу информации о количестве попаданий в заголовок игрового окна.
- Создать простую игру "Стрельба по мишени" с реализацией алгоритма проверки принадлежности точки окружности
Обработка столкновений
Выше мы уже имели дело с простым примером обработки столкновений объектов. Были созданы правила, в соответствии с которыми игровой объект не мог пересечь границы экрана. Часто для обработки столкновений двумерных объектов обрабатывают столкновения прямоугольников, описывающих эти объекты. Для этого нужно знать координаты прямоугольника, в нашем случае координаты задаются координатой левой верхней вершины, шириной и высотой фигуры.
На рис. 8.1. вы можете видеть пример объектов, которые не сталкиваются друг с другом.
На рис. 8.2. вы можете видеть пересекающиеся прямоугольники.
Алгоритмически условие пересечения прямоугольников можно записать в виде такого условия (листинг 8.1.)
Если (А.X+A.Ширина > B.X И A.X < B.X+B.Ширина И A.Y+A.Высота>В.Высота И A.Y<B.Y+B.Высота) Тогда Есть столкновение Иначе Нет столкновенияЛистинг 8.1. Проверка пересечения прямоугольников
Создадим пример, иллюстрирующий этот алгоритм. Возьмем за основу проект P3_6. Назовем новый проект P4_1. Напомним, что в проекте P3_6 мы рассматривали централизованное управление объектами из основного игрового объекта. Продолжим этот пример, доработав основной игровой объект таким образом, чтобы при перемещении объектов проводилась проверка на их столкновение.
В листинге 8.2. приведен код объекта Game1, где мы и реализовали такую проверку. Так как объекты перемещаются путем модификации их позиции на игровом экране, реализуем проверку на столкновение при попытке перемещения объекта. Если объекты сталкиваются – мы таким образом модифицируем их координаты, чтобы они не перекрывались.
using System;
using System.Collections.Generic;
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.Net;
using Microsoft.Xna.Framework.Storage;
namespace P4_1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
spriteComp gameObject1, gameObject2;
Texture2D texture;
Rectangle scrBounds;
float sprSpeed;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Services.AddService(typeof(SpriteBatch), spriteBatch);
texture = Content.Load<Texture2D>("BallandBats");
scrBounds = new Rectangle(0, 0,
this.Window.ClientBounds.Width,
this.Window.ClientBounds.Height);
sprSpeed = 5;
CreateNewObject();
// TODO: use this.Content to load your game content here
}
protected void CreateNewObject()
{
gameObject1 = new spriteComp(this, ref texture,
new Rectangle(18, 9, 17, 88),
new Vector2(100, 150));
Components.Add(gameObject1);
gameObject2 = new spriteComp(this, ref texture,
new Rectangle(17, 106, 17, 88),
new Vector2(200, 150));
Components.Add(gameObject2);
}
void Test(spriteComp spr, Rectangle scr)
{
if (spr.sprPosition.X < scr.Left)
{
spr.sprPosition.X = scr.Left;
}
if (spr.sprPosition.X > scr.Width - spr.sprRectangle.Width)
{
spr.sprPosition.X = scr.Width - spr.sprRectangle.Width;
}
if (spr.sprPosition.Y < scr.Top)
{
spr.sprPosition.Y = scr.Top;
}
if (spr.sprPosition.Y > scr.Height - spr.sprRectangle.Height)
{
spr.sprPosition.Y = scr.Height - spr.sprRectangle.Height;
}
}
void MoveUp(spriteComp spr, float speed)
{
spr.sprPosition.Y -= speed ;
}
void MoveDown(spriteComp spr,float speed)
{
spr.sprPosition.Y += speed;
}
void MoveLeft(spriteComp spr, float speed)
{
spr.sprPosition.X -= speed ;
}
void MoveRight(spriteComp spr, float speed)
{
spr.sprPosition.X += speed ;
}
bool IsCollide(spriteComp sp1, spriteComp sp2)
{
if (sp1.sprPosition.X < sp2.sprPosition.X + sp2.sprRectangle.Width &&
sp1.sprPosition.X + sp1.sprRectangle.Width > sp2.sprPosition.X &&
sp1.sprPosition.Y < sp2.sprPosition.Y + sp2.sprRectangle.Height &&
sp1.sprPosition.Y + sp1.sprRectangle.Height > sp2.sprPosition.Y)
{
return true;
}
else return false;
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// TODO: Add your update logic here
KeyboardState kbState = Keyboard.GetState();
if (kbState.IsKeyDown(Keys.Up))
{
MoveUp(gameObject1, sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveDown(gameObject1, (sprSpeed / 10));
}
}
if (kbState.IsKeyDown(Keys.Down))
{
MoveDown(gameObject1, sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveUp(gameObject1, (sprSpeed / 10));
}
}
if (kbState.IsKeyDown(Keys.Left))
{
MoveLeft(gameObject1, sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveRight(gameObject1, (sprSpeed / 10));
}
}
if (kbState.IsKeyDown(Keys.Right))
{
MoveRight(gameObject1,sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveLeft(gameObject1, (sprSpeed / 10));
}
}
Test(gameObject1, scrBounds);
if (kbState.IsKeyDown(Keys.W))
{
MoveUp(gameObject2,sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveDown(gameObject2, (sprSpeed / 10));
}
}
if (kbState.IsKeyDown(Keys.S))
{
MoveDown(gameObject2,sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveUp(gameObject2, (sprSpeed / 10));
}
}
if (kbState.IsKeyDown(Keys.A))
{
MoveLeft(gameObject2,sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveRight(gameObject2, (sprSpeed / 10));
}
}
if (kbState.IsKeyDown(Keys.D))
{
MoveRight(gameObject2,sprSpeed );
while (IsCollide(gameObject1, gameObject2))
{
MoveLeft(gameObject2, (sprSpeed / 10));
}
}
Test(gameObject2, scrBounds);
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)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
base.Draw(gameTime);
spriteBatch.End();
}
}
}
Листинг
8.2.
Код объекта Game1, реализующий проверку столкновений объектов

