Добавить в цитаты Настройки чтения

Страница 16 из 18



Рис. 5.3. Сыр отскочил от хлеба. Рис. 5.4. Три схемы столкновений.

Рис. 5.5. Четыре схемы столкновений.

В схемах 1 и 4 маленький прямоугольник ударяется о большой прямоугольник сбоку под углом 45 градусов и отражается под этим же углом и по этой же линии. В схемах 2 и 3 маленький прямоугольник падает на большой прямоугольник под углом 45 градусов, но отражается не по линии падения, а по линии отражения, перпендикулярной линии падения.

Для реализации более правильных схем столкновений, показанных на рис. 5.5, в нашем проекте вместо приведённого выше метода updatePositions для изменения координат записываем следующий метод, дополненный новым кодом для обнаружения столкновения объектов.

Листинг 5.3. Метод для изменения координат и обнаружения столкновения объектов.

private void updatePositions()

{

if (goingRight)

{

cx += xSpeed;

}

else

{

cx -= xSpeed;

}

if ((cx + cheeseImage.Width) >= this.Width)

{

goingRight = false;

//At the time of collision, the signal Beep is given:

Microsoft.VisualBasic.Interaction.Beep();

}

if (cx <= 0)

{

goingRight = true;

//At the time of collision, the signal Beep is given:

Microsoft.VisualBasic.Interaction.Beep();

}

if (goingDown)

{

cy += ySpeed;

}

else

{

cy -= ySpeed;

}

//That cheese did not come for the button3.Location.Y:

if ((cy + cheeseImage.Height) >= button3.Location.Y)

{

goingDown = false;

//At the time of collision, the signal Beep is given:

Microsoft.VisualBasic.Interaction.Beep();

}

if (cy <= 0)

{

goingDown = true;

//At the time of collision, the signal Beep is given:

Microsoft.VisualBasic.Interaction.Beep();

}

//We check the collision of objects:

if (goingDown)

{

//If cheese moves down and there is the collision:

if (cheeseRectangle.IntersectsWith(breadRectangle))

{

//At the time of collision, the signal Beep

//is given:

Microsoft.VisualBasic.Interaction.Beep();

//We have the collision:

bool rightIn = breadRectangle.Contains(

cheeseRectangle.Right,

cheeseRectangle.Bottom);

bool leftIn = breadRectangle.Contains(

cheeseRectangle.Left,

cheeseRectangle.Bottom);

//types of collisions:

if (rightIn & leftIn)

{

//bounce up:

goingDown = false;

}

else

{

//bounce up:

goingDown = false;

//the bounces in horizontal direction:

if (rightIn)

{

goingRight = false;

}

if (leftIn)

{

goingRight = true;



}

}

}

}

} //End of the method updatePositions.

В режиме выполнения (Build, Build Selection; Debug, Start Without Debugging) при помощи кнопок Button и мыши мы можем перемещать хлеб и этим хлебом, как ракеткой, отбивать сыр вверх не только верхней стороной прямоугольника (описанного вокруг объекта), как было в предыдущем коде, но теперь и боковыми сторонами этого прямоугольника. Однако мы можем отбивать, только если сыр перемещается сверху вниз.

5.5. Добавление новых объектов

Продолжаем усложнять игру за счёт добавления в неё новых объектов в виде продуктов питания, например, помидоров (tomatoes) в виде файла tomato.gif, рис. 5.6.

Рис. 5.6.

Помидор.

В начале игры несколько i-х помидоров в виде массива tomatoes[i] должны появиться в верхней части экрана в качестве мишеней (рис. 5.7), которые должны исчезать после попадания в них летающего сыра (рис. 5.8).

Попадание сыра в помидор определяется уже применяемым выше методом IntersectWith.

Исчезновение помидоров выполняется при помощи свойства visible, которому присваивается булево значение false (в коде: tomatoes[i].visible = false;).

Управляя при помощи кнопок Button и мыши перемещением батона хлеба, игрок может отражать сыр вверх таким образом, чтобы уничтожить как можно больше помидоров за меньшее время, набирая при этом очки.

Добавляем в наш проект (из отмеченной выше статьи или из Интернета) файл изображения помидора tomato.gif по стандартной схеме, а именно: в меню Project выбираем Add Existing Item, в этой панели в окне “Files of type” выбираем “All Files”, в центральном окне находим и выделяем имя файла и щёлкаем кнопку Add (или дважды щёлкаем по имени файла). В панели Solution Explorer мы увидим этот файл.

Теперь этот же файл tomato.gif встраиваем в проект в виде ресурса по разработанной выше схеме, а именно: в панели Solution Explorer выделяем появившееся там имя файла, а в панели Properties (для данного файла) в свойстве Build Action (Действие при построении) вместо заданного по умолчанию выбираем значение Embedded Resource (Встроенный ресурс).

Рис. 5.7. Помидоры – мишени. Рис. 5.8. Помидоры исчезают после попадания в них сыра.

Для программной реализации рисования и уничтожения помидоров после попадания в них сыра, в классе Form1 нашего проекта записываем следующий код.

Листинг 5.4. Переменные и методы для помидоров (tomatoes).

//We declare the object of the System.Drawing.Image class

//for product:

Image tomatoImage;

//Position and state of tomato

struct tomato

{

public Rectangle rectangle;

public bool visible;

}

// Spacing between tomatoes. Set once for the game

int tomatoSpacing = 4;

// Height, at which the tomatoes are drawn. Will change

// as the game progresses. Starts at the top.

int tomatoDrawHeight = 4;

// The number of tomatoes on the screen. Set at the start

// of the game by initialiseTomatoes.

int noOfTomatoes;

// Positions of the tomato targets.

tomato[] tomatoes;

// called once to set up all the tomatoes.

void initialiseTomatoes()

{

noOfTomatoes = (this.ClientSize.Width – tomatoSpacing) /

(tomatoImage.Width + tomatoSpacing);

// create an array to hold the tomato positions

tomatoes = new tomato[noOfTomatoes];

// x coordinate of each potato

int tomatoX = tomatoSpacing / 2;

for (int i = 0; i < tomatoes.Length; i++)

{

tomatoes[i].rectangle =

new Rectangle(tomatoX, tomatoDrawHeight,

tomatoImage.Width, tomatoImage.Height);

tomatoX = tomatoX + tomatoImage.Width + tomatoSpacing;

}

}

// Called to place a row of tomatoes.

private void placeTomatoes()

{

for (int i = 0; i < tomatoes.Length; i++)

{

tomatoes[i].rectangle.Y = tomatoDrawHeight;

tomatoes[i].visible = true;

}

}

Приведённый выше код в теле метода Form1_Paint заменяем на тот, который дан на следующем листинге.

Листинг 5.5. Метод для рисования изображения.

private void Form1_Paint(object sender, PaintEventArgs e)

{

//If it is necessary, we create the new buffer:

if (backBuffer == null)

{

backBuffer = new Bitmap(this.ClientSize.Width,

this.ClientSize.Height);

}

//We create a object of the Graphics class from the buffer:

using (Graphics g = Graphics.FromImage(backBuffer))

{

//We clear the form:

g.Clear(Color.White);

//We draw the image in the backBuffer:

g.DrawImage(cheeseImage, cx, cy);