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

Глава 4

Рисуем на море корабли

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

Для этого обратимся естественно к функции OnMouseMove()


void CField::OnMouseMove(UINT nFlags, CPoint point) {
if(m_Mode == OWN_FIELD && m_Operation == PLACEMENT) {
if(m_Position.x == -1 && (point.x/20)*20+80 <= 200) {
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
m_Draw = true;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x+80, m_Position.y+20));
}
if(m_Position.x != (point.x/20)*20 || m_Position.y != (point.y/20)*20) {
if(m_Direction == RIGHT && (point.x/20)*20 + m_Decks*20 <= 200) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + m_Decks*20, m_Position.y + 20));
UpdateWindow();
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
m_Draw = true;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + m_Decks*20, m_Position.y + 20));
}
if(m_Direction == TOP && (point.y/20)*20 - (m_Decks-1)*20 >= 0) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y - (m_Decks-1)*20,
m_Position.x + 21, m_Position.y+21));
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x+1, m_Position.y - (m_Decks-1)*20,
m_Position.x + 20, m_Position.y+20));
}
if(m_Direction == BOTTOM && (point.y/20)*20 + m_Decks*20 <= 200) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + 21, m_Position.y + m_Decks*20 + 1));
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + 21, m_Position.y + m_Decks*20 + 1));
}
if(m_Direction == LEFT && (point.x/20)*20 - (m_Decks-1)*20 >= 0) {
m_Draw = false;
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+21, m_Position.y + 21));
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+21, m_Position.y + 21));
}
}
}
CStatic::OnMouseMove(nFlags, point);
}

Анализ

Здесь введем несколько переменных, которые будут определять наши действия:

int m_Operation - тип операции
POINT m_Position - позиция корабля
int m_Decks, m_Direction - число палуб и направление корабля
int m_Mode - режим (находится ли курсор на нашем поле?)
int m_Draw - можно рисовать/нельзя рисовать



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

ЕСЛИ режим - "наше поле" И значение m_Operation == PLACEMENT,
это означает - надо размещать на поле корабли.
if(m_Mode == OWN_FIELD && m_Operation == PLACEMENT) {


ЕСЛИ курсор впервые заходит на поле. (Коодината m_Position.x == -1
- это говорит о том, что курсор еще не заходил на поле),
И координаты курсора таковы, что корабль полностью поместится на поле (а по умолчанию,
если курсор впервые заходит на поле, то направление корабля - вправо)
if(m_Position.x == -1 && (point.x/20)*20+80 <= 200) {

Присвоим координаты переданной точки переменной m_Position
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;

Можно рисовать
m_Draw = true;

Определим координаты и размеры прямоугольника (холста) в котором разметится корабль
InvalidateRect(CRect(m_Position.x, m_Position.y, m_Position.x+80, m_Position.y+20));

}

ЕСЛИ курсор уже находится на поле. Координата переменной m_Position
не равны координатам переданной точки
if(m_Position.x != (point.x/20)*20 || m_Position.y != (point.y/20)*20) {

Если направление корабля - вправо и достаточно места для его расположение
if(m_Direction == RIGHT && (point.x/20)*20 + m_Decks*20 <= 200) {

То расположим корабль от переданной точки вправо.
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + m_Decks*20, m_Position.y + 20));
UpdateWindow();
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
m_Draw = true;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + m_Decks*20, m_Position.y + 20));

}
Если направление корабля - вверх и достаточно места для его расположение
if(m_Direction == TOP && (point.y/20)*20 - (m_Decks-1)*20 >= 0) {
То расположим корабль от переданной точки вверх.
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y - (m_Decks-1)*20,
m_Position.x + 21, m_Position.y+21));
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x+1, m_Position.y - (m_Decks-1)*20,
m_Position.x + 20, m_Position.y+20));
}
Если направление корабля - вниз и достаточно места для его расположение
if(m_Direction == BOTTOM && (point.y/20)*20 + m_Decks*20 <= 200) {
То расположим корабль от переданной точки вниз.
m_Draw = false;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + 21, m_Position.y + m_Decks*20 + 1));
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x, m_Position.y,
m_Position.x + 21, m_Position.y + m_Decks*20 + 1));
}

Если направление корабля - влево и достаточно места для его расположение
if(m_Direction == LEFT && (point.x/20)*20 - (m_Decks-1)*20 >= 0) {

То расположим корабль от переданной точки влево.
m_Draw = false;
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+21, m_Position.y + 21));
m_Position.x = (point.x/20)*20;
m_Position.y = (point.y/20)*20;
UpdateWindow();
m_Draw = true;
InvalidateRect(CRect(m_Position.x - (m_Decks-1)*20, m_Position.y,
m_Position.x+21, m_Position.y + 21));
}
}
}
CStatic::OnMouseMove(nFlags, point);
}

Резюме:

Функция отслеживает движение курсора и постоянно переопределяет в связи с этим координаты прямоугольника (холста) в котором должен быть расположен корабль. При этом функция анализирует и учитывает переменные, определяющие направление корабля, число палуб. А так же тип операции и режим (если m_Mode - наше поле и m_Operation - ставить корабли). Присваивает переменной m_Draw одно из двух значений - рисовать/не рисовать.

Собственно само рисование кораблей будет выполнять другая специализированная функция - DrawShip().


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

Hosted by uCoz