Назад | Начало урока | Вперед
Содержание

Глава 1

При щелчке пользователем на правой кнопке, происходит поворот корабля на 90 градусов
по часовой стрелке, но только в том случае, если при повороте корабля не будет задета
стенка (край поля боя). Поэтому в каждом из 4-х случаев осуществляется проверка:
При многократных щелчках правой кнопкой, корабль устраивает некое шоу, вертясь вокруг
одной точки по часовой стрелке.


void CField::OnRButtonDown(UINT nFlags, CPoint point) {
if(m_Mode == OWN_FIELD && m_Operation == PLACEMENT) {
switch(m_Direction) {
case LEFT:
if(m_Position.y - (m_Decks-1)*20 >= 0) {
m_Draw = false;
//предыдущая позиция
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+20, m_Position.y + 21));
UpdateWindow();
m_Draw = true;
m_Direction = TOP;
//новая позиция
InvalidateRect(CRect(m_Position.x, m_Position.y - (m_Decks-1)*20,
m_Position.x + 20, m_Position.y+21));
}
break;
case TOP:
if(m_Position.x + m_Decks*20 <= 200) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y - (m_Decks-1)*20,
m_Position.x + 21, m_Position.y+21));
UpdateWindow();
m_Draw = true;
m_Direction = RIGHT;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + m_Decks*20 + 1, m_Position.y + 21));
}
break;
case RIGHT:
if(m_Position.y + m_Decks*20 <= 200) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + m_Decks*20 + 1, m_Position.y + 21));
UpdateWindow();
m_Draw = true;
m_Direction = BOTTOM;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + 20, m_Position.y + m_Decks*20));

}
break;
case BOTTOM:
if(m_Position.x - (m_Decks-1)*20 >= 0) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + 21, m_Position.y + m_Decks*20+1));
m_Direction = LEFT;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+20, m_Position.y + 20));
}
break;
}
}
CStatic::OnRButtonDown(nFlags, point);
}

Анализ:

При щелчке пользователем на правой кнопке, происходит поворот корабля на 90 градусов
по часовой стрелке, но только в том случае, если при повороте корабля не будет задета
стенка (край поля боя). Поэтому в каждом из 4-х случаев осуществляется проверка этого.

void CField::OnRButtonDown(UINT nFlags, CPoint point) {

Проверка: если щелчек на нашем поле и если операция при этом - постановка корабля:
if(m_Mode == OWN_FIELD && m_Operation == PLACEMENT) {

Передаем направление в котором должен быть расположен корабль:
switch(m_Direction) {

В случаях TOP и BOTTOM проверяется позиция x, не выйдет ли новое изображение изображение корабля за пределы поля слева либо справа?
case TOP:

if(m_Position.x + m_Decks*20 <= 200)
case BOTTOM:
if(m_Position.x - (m_Decks-1)*20 >= 0)

В случаях RIGHT и LEFT проверяется позиция y, не выйдет ли новое изображение
изображение корабля за пределы поля сверху либо снизу?
case RIGHT:

if(m_Position.y + m_Decks*20 <= 200)
case LEFT:
if(m_Position.y - (m_Decks-1)*20 >= 0)

Это проверка, чтобы не выйти за рамки поля боя.

Внутри if код имеет в общем одинаковую структуру:

case LEFT:

if(m_Position.y - (m_Decks-1)*20 >= 0) {
m_Draw = false;
//предыдущая позиция
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+20, m_Position.y + 21));

UpdateWindow();
m_Draw = true;
m_Direction = TOP;
//новая позиция
InvalidateRect(CRect(m_Position.x, m_Position.y - (m_Decks-1)*20,
m_Position.x + 20, m_Position.y+21));

}

Суть данного кода в том, что в инструкции:

InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,

m_Position.x+20, m_Position.y + 21));

даны размеры холста (прямоугольника) точно такие, что это прямоугольник,
расположенный по длине влево на три ячейки и вправо на одну ячейку начиная
от заданной точки. По ширине вниз на одну ячейку начиная от заданной плюс
один пиксел. При условии, что здесь m_Decks = 4, четырехклеточный корабль.
Это предыдущая позиция корабля.

Далее обновляется окно, затем переменным m_Draw и m_Direction даются новые значения.

UpdateWindow();
m_Draw = true;
m_Direction = TOP;

А в следующей инструкции:

InvalidateRect(CRect(m_Position.x, m_Position.y - (m_Decks-1)*20,

m_Position.x + 20, m_Position.y+21));

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

При условии, что здесь m_Decks = 4, четырехклеточный корабль.
Это новая позиция корабля.

Интересно, что во всех случаях сначала рисуется прежняя позиция корабля,
потом обновляется окно и устанавливается новая позиция корабля.

Интересно, что переданные параметры используются только в последней инструкции:
CStatic::OnRButtonDown(nFlags, point);

А в самой функции используются переменные класса Field: m_Operation, m_Position,
m_Direction, m_Mode, m_Decks, m_Draw.
Доступ к этим переменным из функции своего класса свободный.

А так же четыре глобальные константы означающие направление

//directions
#define RIGHT 3000
#define BOTTOM 3001
#define LEFT 3002
#define TOP 3003

public-переменные класса
int m_Operation

private-переменные класса
int m_Mode
POINT m_Position
int m_Direction
int m_Decks - размер одной ячейки корабля равен 4 пиксела
int m_Draw


Назад | Начало урока | Вверх | Вперед
Содержание

Hosted by uCoz